arch: arc: update the ARC port

* add basic synopsys arc em processor support
* add basic arc nsim em virtual board support
* add basic arc mwdt toolchain support

Signed-off-by: Watson Zeng <zhiwei@synopsys.com>
This commit is contained in:
Watson Zeng
2020-03-25 17:11:52 +08:00
committed by Jingru
parent 13eaef3d46
commit 0d4593ee5e
169 changed files with 871 additions and 46371 deletions

Submodule platform/vendor_bsp/Synopsys/ARC/embarc_bsp added at 7595aae3c2

View File

@@ -1,403 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_CACHE
* @brief Cache manipulation
*
* This module contains functions for manipulation caches.
*/
#include "arc/arc_cache.h"
struct cache_config {
uint8_t ver; /* Version */
uint8_t assoc; /* Cache Associativity */
uint16_t line; /* Cache line/block size */
uint32_t capacity; /* Capacity */
};
static struct cache_config icache_config, dcache_config;
/**
* @brief Invalidate instruction cache lines
*
* @param start_addr Start address in instruction cache
* @param size Bytes to be invalidated
* @return 0, succeeded, -1, failed
*/
int32_t icache_invalidate_mlines(uint32_t start_addr, uint32_t size)
{
uint32_t end_addr;
uint32_t line_size;
uint32_t status;
if ((size == 0) || (size > icache_config.capacity)) {
return -1;
}
line_size = (uint32_t)(icache_config.line);
end_addr = start_addr + size - 1;
start_addr &= (uint32_t)(~(line_size - 1));
status = cpu_lock_save();
do {
arc_aux_write(AUX_IC_IVIL, start_addr);
arc_nop();
arc_nop();
arc_nop();
start_addr += line_size;
} while (start_addr <= end_addr);
cpu_unlock_restore(status);
return 0;
}
/**
* @brief Lock instruction cache lines
*
* @param start_addr Start address in instruction cache
* @param size Bytes to be locked
* @return 0, succeeded, -1, failed (cache already locked or other reasons)
*/
int32_t icache_lock_mlines(uint32_t start_addr, uint32_t size)
{
uint32_t end_addr;
uint32_t line_size;
uint32_t status;
int32_t ercd = 0;
if ((size == 0) || (size > icache_config.capacity)) {
return -1;
}
line_size = (uint32_t)(icache_config.line);
end_addr = start_addr + size - 1;
start_addr &= (uint32_t)(~(line_size - 1));
status = cpu_lock_save();
do {
arc_aux_write(AUX_IC_LIL, start_addr);
if (arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) {
start_addr += line_size;
} else {
ercd = -1; /* the operation failed */
break;
}
} while (start_addr <= end_addr);
cpu_unlock_restore(status);
return ercd;
}
#if ARC_FEATURE_ICACHE_FEATURE == 2
/**
* @brief Directly write icache internal ram
*
* @param cache_addr Icache internal address(way+index+offset)
* @param tag Cache tag to write (tag+lock bit+valid bit)
* @param data Cache data to write
* @return 0, succeeded, -1, failed
*/
int32_t icache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data)
{
if (arc_aux_read(AUX_IC_CTRL) & IC_CTRL_INDIRECT_ACCESS) {
return -1;
}
arc_aux_write(AUX_IC_RAM_ADDR, cache_addr);
arc_aux_write(AUX_IC_TAG, tag);
arc_aux_write(AUX_IC_DATA, data);
return 0;
}
/**
* @brief Directly read icache internal ram
*
* @param cache_addr Icache internal address(way+index+offset)
* @param tag Cache tag to read (tag+index+lock bit+valid bit)
* @param data Cache data to read
* @return 0, succeeded, -1, failed
*/
int32_t icache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data)
{
if (arc_aux_read(AUX_IC_CTRL) & IC_CTRL_INDIRECT_ACCESS) {
return -1;
}
arc_aux_write(AUX_IC_RAM_ADDR, cache_addr);
*tag = arc_aux_read(AUX_IC_TAG);
*data = arc_aux_read(AUX_IC_DATA);
return 0;
}
/**
* @brief Indirectly read icache internal ram
*
* @param mem_addr Memory address
* @param tag Cache tag to read
* @param data Cache data to read
* @return 0, succeeded, -1, failed
*/
int32_t icache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data)
{
if (!(arc_aux_read(AUX_IC_CTRL) & IC_CTRL_INDIRECT_ACCESS)) {
return -1;
}
arc_aux_write(AUX_IC_RAM_ADDR, mem_addr);
if (arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) {
*tag = arc_aux_read(AUX_IC_TAG);
*data = arc_aux_read(AUX_IC_DATA);
} else {
return -1; /* the specified memory is not in icache */
}
return 0;
}
#endif
/**
* @brief Invalidate data cache lines
*
* @param start_addr Start address in data cache
* @param size Bytes to be invalidated
* @return 0, succeeded, -1, failed
*/
int32_t dcache_invalidate_mlines(uint32_t start_addr, uint32_t size)
{
uint32_t end_addr;
uint32_t line_size;
uint32_t status;
if ((size == 0) || (size > dcache_config.capacity)) {
return -1;
}
line_size = (uint32_t)(dcache_config.line);
end_addr = start_addr + size - 1;
start_addr &= (uint32_t)(~(line_size - 1));
status = cpu_lock_save();
do {
arc_aux_write(AUX_DC_IVDL, start_addr);
arc_nop();
arc_nop();
arc_nop();
/* wait for flush completion */
while (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) {
;
}
start_addr += line_size;
} while (start_addr <= end_addr);
cpu_unlock_restore(status);
return 0;
}
/**
* @brief Flush data cache lines to memory
*
* @param start_addr Start address
* @param size Bytes to be flushed
* @return 0, succeeded, -1, failed
*/
int32_t dcache_flush_mlines(uint32_t start_addr, uint32_t size)
{
uint32_t end_addr;
uint32_t line_size;
uint32_t status;
if ((size == 0) || (size > dcache_config.capacity)) {
return -1;
}
line_size = (uint32_t)(dcache_config.line);
end_addr = start_addr + size - 1;
start_addr &= (uint32_t)(~(line_size - 1));
status = cpu_lock_save();
do {
arc_aux_write(AUX_DC_FLDL, start_addr);
arc_nop();
arc_nop();
arc_nop();
/* wait for flush completion */
while (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) {
;
}
start_addr += line_size;
} while (start_addr <= end_addr);
cpu_unlock_restore(status);
return 0;
}
/**
* @brief Lock data cache lines
*
* @param start_addr Start address in data cache
* @param size Bytes to be locked
* @return 0, succeeded, -1, failed
*/
int32_t dcache_lock_mlines(uint32_t start_addr, uint32_t size)
{
uint32_t end_addr;
uint32_t line_size;
uint32_t status;
int32_t ercd = 0;
if ((size == 0) || (size > dcache_config.capacity)) {
return -1;
}
line_size = (uint32_t)(dcache_config.line);
end_addr = start_addr + size - 1;
start_addr &= (uint32_t)(~(line_size - 1));
status = cpu_lock_save();
do {
arc_aux_write(AUX_DC_LDL, start_addr);
arc_nop();
if (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) {
start_addr += line_size;
} else {
ercd = -1; /* the operation failed */
break;
}
} while (start_addr <= end_addr);
cpu_unlock_restore(status);
return ercd;
}
/**
* @brief Directly write dcache internal ram
*
* @param cache_addr Dcache internal address(way+index+offset)
* @param tag Cache tag to write
* @param data Cache data to write
* @return 0, succeeded, -1, failed
*/
int32_t dcache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data)
{
if (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_INDIRECT_ACCESS) {
return -1;
}
arc_aux_write(AUX_DC_RAM_ADDR, cache_addr);
arc_aux_write(AUX_DC_TAG, tag);
arc_aux_write(AUX_DC_DATA, data);
return 0;
}
/**
* @brief Directly read dcache internal ram
*
* @param cache_addr Dcache internal address(way+index+offset)
* @param tag Cache tag to read
* @param data Cache data to read
* @return 0, succeeded, -1, failed
*/
int32_t dcache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data)
{
if (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_INDIRECT_ACCESS) {
return -1;
}
arc_aux_write(AUX_DC_RAM_ADDR, cache_addr);
*tag = arc_aux_read(AUX_DC_TAG);
*data = arc_aux_read(AUX_DC_DATA);
return 0;
}
/**
* @brief Indirectly read dcache internal ram
*
* @param mem_addr Memory address(tag+index+offset)
* @param tag Cache tag to read
* @param data Cache data to read
* @return 0, succeeded, -1, failed
*/
int32_t dcache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data)
{
if (!(arc_aux_read(AUX_DC_CTRL) & DC_CTRL_INDIRECT_ACCESS)) {
return -1;
}
arc_aux_write(AUX_DC_RAM_ADDR, mem_addr);
if (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) {
*tag = arc_aux_read(AUX_DC_TAG);
*data = arc_aux_read(AUX_DC_DATA);
} else {
return -1; /* the specified memory is not in dcache */
}
return 0;
}
/**
* @brief Initialize cache
* 1. invalidate icache and dcache
* 2. Only support ARCv2 cache
*/
void arc_cache_init(void)
{
uint32_t build_cfg;
build_cfg = arc_aux_read(AUX_BCR_D_CACHE);
dcache_config.ver = build_cfg & 0xff;
if (dcache_config.ver >= 0x04) { /* ARCv2 */
dcache_enable(DC_CTRL_DISABLE_FLUSH_LOCKED |
DC_CTRL_INDIRECT_ACCESS | DC_CTRL_INVALID_FLUSH);
dcache_invalidate();
dcache_config.assoc = 1 << ((build_cfg >> 8) & 0xf);
dcache_config.capacity = 512 << ((build_cfg >> 12) & 0xf);
dcache_config.line = 16 << ((build_cfg >> 16) & 0xf);
}
build_cfg = arc_aux_read(AUX_BCR_I_CACHE);
icache_config.ver = build_cfg & 0xff;
if (icache_config.ver >= 0x04) { /* ARCv2 */
icache_config.assoc = 1 << ((build_cfg >> 8) & 0xf);
icache_config.capacity = 512 << ((build_cfg >> 12) & 0xf);
icache_config.line = 8 << ((build_cfg >> 16) & 0xf);
icache_enable(IC_CTRL_IC_ENABLE);
icache_invalidate();
}
}

View File

@@ -1,964 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_CONNECT
* @brief ar connect driver
*
* This module contains functions for arc connect module.
*/
#include "arc/arc_connect.h"
#include "arc/arc_mp.h"
static ARC_SPINLOCK_T arc_connect_lock;
/**
* @brief Execute arc connect command
*
* @param op Pointer to arc connect operation
* @return Result of arc connect command
*/
static uint32_t arc_connect_cmd_execute(ARC_CONNECT_OP_T *op)
{
uint32_t regval = 0;
if (!op) {
return 0;
}
regval = op->cmd | ((op->param) << 8);
arc_spinlock_get(&arc_connect_lock);
switch (op->type) {
case ARC_CONNECT_CMD_TYPE_CMD_ONLY:
arc_aux_write(AUX_CONNECT_CMD, regval);
break;
case ARC_CONNECT_CMD_TYPE_CMD_RETURN:
arc_aux_write(AUX_CONNECT_CMD, regval);
break;
case ARC_CONNECT_CMD_TYPE_CMD_WDATA:
arc_aux_write(AUX_CONNECT_WDATA, op->wdata);
arc_aux_write(AUX_CONNECT_CMD, regval);
break;
case ARC_CONNECT_CMD_TYPE_CMD_WDATA_RETURN:
arc_aux_write(AUX_CONNECT_WDATA, op->wdata);
arc_aux_write(AUX_CONNECT_CMD, regval);
break;
default:
break;
}
regval = arc_aux_read(AUX_CONNECT_READBACK);
arc_spinlock_release(&arc_connect_lock);
return regval;
}
/**
* @brief Get the core id in arc connect
*
* @return Core id
*/
uint32_t arc_connect_check_core_id(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_CHECK_CORE_ID, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Enable interrupt distribute unit
*
*/
void arc_connect_idu_enable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_IDU_ENABLE, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief Disable interrupt distribute unit
*
*/
void arc_connect_idu_disable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_IDU_DISABLE, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief Read interrupt distribute enable status
*
* @return Enable status
*/
uint32_t arc_connect_idu_read_enable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_READ_ENABLE, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Set the mode of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @param trigger_mode Trigger mode, level or pulse
* @param distri_mode Distribute mode
*/
void arc_connect_idu_set_mode(uint32_t irq_num, uint16_t trigger_mode, uint16_t distri_mode)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_IDU_SET_MODE, \
irq_num, (distri_mode | (trigger_mode << 4)));
arc_connect_cmd_execute(&op);
}
/**
* @brief Read the mode of irq connected to idu
*
* @param irq_num Number of irq connected to idu
*
*/
uint32_t arc_connect_idu_read_mode(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_READ_ENABLE, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Set the target core to handle the irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @param target_core Target core
*/
void arc_connect_idu_set_dest(uint32_t irq_num, uint32_t target_core)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_IDU_SET_DEST, irq_num, target_core);
arc_connect_cmd_execute(&op);
}
/**
* @brief Read the target core to handle the irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Target core
*/
uint32_t arc_connect_idu_read_dest(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_READ_DEST, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Generate the irq connected to idu in software
*
* @param irq_num Number of irq connected to idu
*/
void arc_connect_idu_gen_cirq(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_IDU_GEN_CIRQ, irq_num);
arc_connect_cmd_execute(&op);
}
/**
* @brief Acknowledge irq connected to idu
*
* @param irq_num Number of irq connected to idu
*/
void arc_connect_idu_ack_cirq(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_IDU_ACK_CIRQ, irq_num);
arc_connect_cmd_execute(&op);
}
/**
* @brief Check the status of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Status of irq connected to idu
*/
uint32_t arc_connect_idu_check_status(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_CHECK_STATUS, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Check the source of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Source of irq connected to idu
*/
uint32_t arc_connect_idu_check_source(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_CHECK_SOURCE, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Set the interrupt mask of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @param mask Interrupt mask
*/
void arc_connect_idu_set_mask(uint32_t irq_num, uint32_t mask)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_IDU_SET_MASK, irq_num, mask);
arc_connect_cmd_execute(&op);
}
/**
* @brief Read the interrupt mask of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Interrupt mask
*/
uint32_t arc_connect_idu_read_mask(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_READ_MASK, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Check the first core to handle the irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Core number
*/
uint32_t arc_connect_idu_check_first(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_CHECK_FIRST, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Configure the irq connected to idu
*
* @param core Target core to handle the irq
* @param irq_num Number of irq connected to idu
* @param trigger_mode Trigger mode
* @param distri_mode Distribute mode
*/
void arc_connect_idu_config_irq(uint32_t core, uint32_t irq_num, uint16_t trigger_mode, uint16_t distri_mode)
{
arc_connect_idu_disable();
arc_connect_idu_set_mode(irq_num, trigger_mode, distri_mode);
arc_connect_idu_set_dest(irq_num, core);
arc_connect_idu_set_mask(irq_num, 0x0);
arc_connect_idu_enable();
}
/**
* @brief generate inter-core interrupt
* the calling core will raise an interrupt to the target core
* @param core_id the target core
*/
void arc_connect_ici_generate(uint32_t core_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_INTRPT_GENERATE_IRQ, core_id);
arc_connect_cmd_execute(&op);
}
/**
* @brief acknowledge the raised inter-core interrupt
*
* @param core_id the core rasing the inter-core interrupt
*/
void arc_connect_ici_ack(uint32_t core_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_INTRPT_GENERATE_ACK, core_id);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the status of inter-core interrupt
*
* @param core_id the target core
* @return 1 the inter-core interrupt is pending, 0 the inter-core interrupt
* is acknowledged
*/
uint32_t arc_connect_ici_read_status(uint32_t core_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_INTRPT_READ_STATUS, core_id);
return arc_connect_cmd_execute(&op);
}
/**
* @brief check the source of inter-core interrupt
*
* @return the source of inter-core interrupt
*/
uint32_t arc_connect_ici_check_src(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_INTRPT_CHECK_SOURCE, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief taka a inter-core semaphore
*
* @param sem_id semaphore id
* @return 0 failed, 1 success
*/
uint32_t arc_connect_ics_take(uint32_t sem_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_SEMA_CLAIM_AND_READ, sem_id);
return arc_connect_cmd_execute(&op);
}
/**
* @brief release a inter-core semaphore
*
* @param sem_id semaphore id
*/
void arc_connect_ics_release(uint32_t sem_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_SEMA_RELEASE, sem_id);
arc_connect_cmd_execute(&op);
}
/**
* @brief compulsively release and make available a semaphore
*
* @param sem_id semaphore id
*/
void arc_connect_ics_force_release(uint32_t sem_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_SEMA_FORCE_RELEASE, sem_id);
arc_connect_cmd_execute(&op);
}
/**
* @brief set the address of message-passing sram for subsequent read or
write sram operations
*
* @param addr sram address
*/
void arc_connect_icm_addr_set(uint32_t addr)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_SET_ADDR, addr);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the value of internal MSG_ADDR reg
*
* @return value of MSG_ADDR reg
*/
uint32_t arc_connect_icm_addr_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_ADDR, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set the offset address of message-passing sram for subsequent read or
write sram operations
*
* @param offset address offset
*/
void arc_connect_icm_addr_offset_set(uint32_t offset)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_SET_ADDR_OFFSET, offset);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the value of address offset reg
*
* @return value of address offset reg
*/
uint32_t arc_connect_icm_addr_offset_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_ADDR_OFFSET, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief write data to the message-passing sram
*
* @param data data to write
*/
void arc_connect_icm_msg_write(uint32_t data)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_WRITE, 0, data);
arc_connect_cmd_execute(&op);
}
/**
* @brief incremental write to the message-passing sram
*
* @param data data to write
*/
void arc_connect_icm_msg_inc_write(uint32_t data)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_WRITE_INC, 0, data);
arc_connect_cmd_execute(&op);
}
/**
* @brief write data into the message passing sram with the address
* specified by an immediate value.
*
* @param addr the specified address
* @param data data to write
*/
void arc_connect_icm_msg_imm_write(uint32_t addr, uint32_t data)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_WRITE_IMM, addr, data);
arc_connect_cmd_execute(&op);
}
/**
* @brief read data from the message passing sram
*
* @return read data
*/
uint32_t arc_connect_icm_msg_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief incremental read data from the message passing sram
*
* @return read data
*/
uint32_t arc_connect_icm_msg_inc_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_INC, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read data at the specified address from the message passing sram
*
* @param addr the specified address
* @return read data
*/
uint32_t arc_connect_icm_msg_imm_read(uint32_t addr)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_IMM, addr);
return arc_connect_cmd_execute(&op);
}
/**
* @brief enable or disable ECC or parity protection on the message data
*
* @param val 0 = enable protection, 1= disable protection
*/
void arc_connect_icm_ecc_ctrl_set(uint32_t val)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_SET_ECC_CTRL, 0, val);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the status ofECC or parity protection on the message data
*
* @return 0 = enable protection, 1= disable protection
*/
uint32_t arc_connect_icm_ecc_ctrl_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_ECC_CTRL, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief generate reset request to cores in the system.
*
* @param cores the target cores
*/
void arc_connect_debug_reset(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_RESET, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief generate halt request to cores in the system.
*
* @param cores the target cores
*/
void arc_connect_debug_halt(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_HALT, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief generate run request to cores in the system.
*
* @param cores the target cores
*/
void arc_connect_debug_run(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_RUN, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief set the internal MASK reg in ICD
* the MASK register determines whether a global halt is triggered
* if a core is halted in response to one of the following events:
* core halt, actionpoint halt, self-halt, and breakpoint halt
* @param cores the cores for which the MASK register should be updated
* @param mask mask bits
*/
void arc_connect_debug_mask_set(uint32_t cores, uint32_t mask)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_SET_MASK, mask, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the internal MASK reg in ICD
*
* @param cores the cores for which the MASK register should be read
* @return mask bits
*/
uint32_t arc_connect_debug_mask_read(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_RUN, 0, cores);
return arc_connect_cmd_execute(&op);
}
/**
* @brief select cores that should be halted if the core issuing the command is halted
*
* @param cores cores to select
*/
void arc_connect_debug_select_set(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_SET_SELECT, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief ead the internal SELECT register in ICD
*
* @return SELECT register value
*/
uint32_t arc_connect_debug_select_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_READ_SELECT, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read the status, halt or run,of all cores
*
* @return bits: 1 running, 0 halted
*/
uint32_t arc_connect_debug_en_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_READ_EN, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief check the last command sent to ICD.
*
* @return ICD command
*/
uint32_t arc_connect_debug_cmd_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_READ_CMD, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read the value of internal MCD_CORE register in ICD
*
* @return MCD_CORE register
*/
uint32_t arc_connect_debug_core_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_READ_CORE, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief clear the global free running counter
*
*/
void arc_connect_gfrc_clear(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_GFRC_CLEAR, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief read low 32-bit of gfrc
*
* @return low 32-bit of gfrc
*/
uint32_t arc_connect_gfrc_lo_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_GFRC_READ_LO, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read high 32-bit of gfrc
*
* @return high 32-bit of gfrc
*/
uint32_t arc_connect_gfrc_hi_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_GFRC_READ_HI, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief enable gfrc
*
*/
void arc_connect_gfrc_enable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_GFRC_ENABLE, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief disable gfrc
*
*/
void arc_connect_gfrc_disable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_GFRC_DISABLE, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief set the relevant cores to halt the GFRC
*
* @param cores the relevant cores
*/
void arc_connect_gfrc_core_set(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_GFRC_SET_CORE, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the status of gfrc
*
* @return gfrc status
*/
uint32_t arc_connect_gfrc_halt_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_GFRC_READ_HALT, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read the internal CORE register
*
* @return CORE register value
*/
uint32_t arc_connect_gfrc_core_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_GFRC_READ_CORE, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set the power mode for specific ARConnect group
*
* @param group the ARConnect group
* @param cmd power mode
*/
void arc_connect_pdm_pm_set(uint32_t group, uint32_t cmd)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_PDM_SET_PM, group, cmd);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the internal PM register of the specified ARConnect group.
*
* @param group the ARConnect group
* @return status value
*/
uint32_t arc_connect_pdm_pdstatus_read(uint32_t group)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_PDM_READ_PSTATUS, group);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set PUCNT
*
* @param cnt cnt to set
*/
void arc_connect_pmu_pucnt_set(uint32_t cnt)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_PMU_SET_PUCNT, 0, cnt);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the PUNCNT
*
* @return PUNCNT's value
*/
uint32_t arc_connect_pmu_pucnt_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_PMU_READ_PUCNT, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set RSTCNT
*
* @param cnt cnt to set
*/
void arc_connect_pmu_rstcnt_set(uint32_t cnt)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_PMU_SET_RSTCNT, 0, cnt);
arc_connect_cmd_execute(&op);
}
/**
* @brief read RSTCNT
*
* @return RSTCNT's value
*/
uint32_t arc_connect_pmu_rstcnt_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_PMU_READ_RSTCNT, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set PDCCNT
*
* @param cnt cnt to set
*/
void arc_connect_pmu_pdccnt_set(uint32_t cnt)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_PMU_SET_PDCNT, 0, cnt);
arc_connect_cmd_execute(&op);
}
/**
* @brief read PDCCNT
*
* @return PDCCNT's vaule
*/
uint32_t arc_connect_pmu_pdccnt_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_PMU_READ_PDCNT, 0);
return arc_connect_cmd_execute(&op);
}

View File

@@ -1,159 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_EXCEPTION_CPU
* @brief Assembly part of exception and interrupt processing
*/
/**
* @addtogroup ARC_HAL_EXCEPTION_CPU
* @{
*/
/* function documentation */
/**
* @fn void exc_entry_cpu(void)
* @brief Default entry of CPU exceptions, such as TLB miss and swap.
*
* @fn void exc_entry_int(void)
* @brief Normal interrupt exception entry.
* In default, all interrupt exceptions are installed with normal entry.
* If FIRQ is required, exc_entry_firq should be the entry.
*
* @fn void exc_entry_firq(void)
* @brief firq exception entry
*/
/** }@ */
/** @cond EXCEPTION_ASM */
#define __ASSEMBLY__
#include "arc/arc.h"
#include "arc/arc_asm_common.h"
.file "arc_exc_asm.s"
/****** entry for cpu exception handling *******/
.text
.global exc_entry_cpu
.weak exc_entry_cpu
.align 4
exc_entry_cpu:
EXCEPTION_PROLOGUE
/* find the exception cause */
lr r0, [AUX_ECR]
lsr r0, r0, 16
bmsk r0, r0, 7
mov r1, exc_int_handler_table
ld.as r2, [r1, r0]
/* jump to exception handler where interrupts are not allowed! */
mov r0, sp
jl [r2]
exc_return:
EXCEPTION_EPILOGUE
rtie
/****** entry for normal interrupt exception handling ******/
.global exc_entry_int
.weak exc_entry_int
.align 4
exc_entry_int:
#if ARC_FEATURE_FIRQ == 1
#if ARC_FEATURE_RGF_NUM_BANKS > 1
/* check whether it is P0 interrupt */
lr r0, [AUX_IRQ_ACT]
btst r0, 0
bnz exc_entry_firq
#else
PUSH r10
lr r10, [AUX_IRQ_ACT]
btst r10, 0
POP r10
bnz exc_entry_firq
#endif
#endif
/* save scratch regs */
INTERRUPT_PROLOGUE
/* critical area */
lr r0, [AUX_IRQ_CAUSE]
mov r1, exc_int_handler_table
/* r2 = _kernel_exc_tbl + irqno *4 */
ld.as r2, [r1, r0]
/* for the case of software triggered interrupt */
lr r3, [AUX_IRQ_HINT]
cmp r3, r0
bne.d irq_hint_handled
xor r3, r3, r3
sr r3, [AUX_IRQ_HINT]
irq_hint_handled:
/* jump to interrupt handler */
mov r0, sp
jl [r2]
int_return:
INTERRUPT_EPILOGUE
rtie
/****** entry for fast irq exception handling ******/
.global exc_entry_firq
.weak exc_entry_firq
.align 4
exc_entry_firq:
SAVE_FIQ_EXC_REGS
lr r0, [AUX_IRQ_CAUSE]
mov r1, exc_int_handler_table
/* r2 = _kernel_exc_tbl + irqno *4 */
ld.as r2, [r1, r0]
/* for the case of software triggered interrupt */
lr r3, [AUX_IRQ_HINT]
cmp r3, r0
bne.d firq_hint_handled
xor r3, r3, r3
sr r3, [AUX_IRQ_HINT]
firq_hint_handled:
/* jump to interrupt handler */
mov r0, sp
jl [r2]
firq_return:
RESTORE_FIQ_EXC_REGS
rtie
/** @endcond */

View File

@@ -1,812 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT
* @brief ARC interrupt and exception handling
*/
#include "arc/arc_exception.h"
#include "arc/arc_cache.h"
#define DBG_LESS
#include "embARC_debug.h"
/**
* @addtogroup ARC_HAL_EXCEPTION_CPU
* @{
* @var EXC_ENTRY_T exc_entry_table
* @brief exception entry table
*
* Install exception entry table to ARC_AUX_INT_VECT_BASE in startup.
* According to ARCv2 ISA, vectors are fetched in instruction space and thus
* may be present in ICCM, Instruction Cache, or
* main memory accessed by instruction fetch logic.
* So it is put into a specific section .vector.
*
* Please note that the exc_entry_table maybe cached in ARC. Some functions is
* defined in .s files.
*
*/
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
/* For EV_ProtV, the numbering/semantics of the parameter are consistent across
* several codes, although not all combination will be reported.
*
* These codes and parameters do not have associated* names in
* the technical manual, just switch on the values in Table 6-5
*/
static void dump_protv_access_err(uint32_t parameter)
{
switch (parameter) {
case 0x1:
EMBARC_PRINTF("code protection scheme");
break;
case 0x2:
EMBARC_PRINTF("stack checking scheme");
break;
case 0x4:
EMBARC_PRINTF("MPU");
break;
case 0x8:
EMBARC_PRINTF("MMU");
break;
case 0x10:
EMBARC_PRINTF("NVM");
break;
case 0x24:
EMBARC_PRINTF("Secure MPU");
break;
case 0x44:
EMBARC_PRINTF("Secure MPU with SID mismatch");
break;
default:
EMBARC_PRINTF("unknown parameter");
break;
}
}
static void dump_protv_exception(uint32_t cause, uint32_t parameter)
{
switch (cause) {
case 0x0:
EMBARC_PRINTF("Instruction fetch violation: ");
dump_protv_access_err(parameter);
break;
case 0x1:
EMBARC_PRINTF("Memory read protection violation: ");
dump_protv_access_err(parameter);
break;
case 0x2:
EMBARC_PRINTF("Memory write protection violation: ");
dump_protv_access_err(parameter);
break;
case 0x3:
EMBARC_PRINTF("Memory read-modify-write violation: ");
dump_protv_access_err(parameter);
break;
case 0x10:
EMBARC_PRINTF("Normal vector table in secure memory");
break;
case 0x11:
EMBARC_PRINTF("NS handler code located in S memory");
break;
case 0x12:
EMBARC_PRINTF("NSC Table Range Violation");
break;
default:
EMBARC_PRINTF("unknown cause");
break;
}
}
static void dump_machine_check_exception(uint32_t cause, uint32_t parameter)
{
switch (cause) {
case 0x0:
EMBARC_PRINTF("double fault");
break;
case 0x1:
EMBARC_PRINTF("overlapping TLB entries");
break;
case 0x2:
EMBARC_PRINTF("fatal TLB error");
break;
case 0x3:
EMBARC_PRINTF("fatal cache error");
break;
case 0x4:
EMBARC_PRINTF("internal memory error on instruction fetch");
break;
case 0x5:
EMBARC_PRINTF("internal memory error on data fetch");
break;
case 0x6:
EMBARC_PRINTF("illegal overlapping MPU entries");
if (parameter == 0x1) {
EMBARC_PRINTF(" (jump and branch target)");
}
break;
case 0x10:
EMBARC_PRINTF("secure vector table not located in secure memory");
break;
case 0x11:
EMBARC_PRINTF("NSC jump table not located in secure memory");
break;
case 0x12:
EMBARC_PRINTF("secure handler code not located in secure memory");
break;
case 0x13:
EMBARC_PRINTF("NSC target address not located in secure memory");
break;
case 0x80:
EMBARC_PRINTF("uncorrectable ECC or parity error in vector memory");
break;
default:
EMBARC_PRINTF("unknown cause");
break;
}
}
static void dump_privilege_exception(uint32_t cause, uint32_t parameter)
{
switch (cause) {
case 0x0:
EMBARC_PRINTF("Privilege violation");
break;
case 0x1:
EMBARC_PRINTF("disabled extension");
break;
case 0x2:
EMBARC_PRINTF("action point hit");
break;
case 0x10:
switch (parameter) {
case 0x1:
EMBARC_PRINTF("N to S return using incorrect return mechanism");
break;
case 0x2:
EMBARC_PRINTF("N to S return with incorrect operating mode");
break;
case 0x3:
EMBARC_PRINTF("IRQ/exception return fetch from wrong mode");
break;
case 0x4:
EMBARC_PRINTF("attempt to halt secure processor in NS mode");
break;
case 0x20:
EMBARC_PRINTF("attempt to access secure resource from normal mode");
break;
case 0x40:
EMBARC_PRINTF("SID violation on resource access (APEX/UAUX/key NVM)");
break;
default:
EMBARC_PRINTF("unknown parameter");
break;
}
break;
case 0x13:
switch (parameter) {
case 0x20:
EMBARC_PRINTF("attempt to access secure APEX feature from NS mode");
break;
case 0x40:
EMBARC_PRINTF("SID violation on access to APEX feature");
break;
default:
EMBARC_PRINTF("unknown parameter");
break;
}
break;
default:
EMBARC_PRINTF("unknown cause");
break;
}
}
static void dump_exception_info(uint32_t vector, uint32_t cause, uint32_t param)
{
/* Names are exactly as they appear in Designware ARCv2 ISA
* Programmer's reference manual for easy searching
*/
switch (vector) {
case EXC_NO_RESET:
EMBARC_PRINTF("Reset");
break;
case EXC_NO_MEM_ERR:
EMBARC_PRINTF("Memory Error");
break;
case EXC_NO_INS_ERR:
EMBARC_PRINTF("Instruction Error");
break;
case EXC_NO_MAC_CHK:
EMBARC_PRINTF("EV_MachineCheck: ");
dump_machine_check_exception(cause, param);
break;
case EXC_NO_TLB_MISS_I:
EMBARC_PRINTF("EV_TLBMissI");
break;
case EXC_NO_TLB_MISS_D:
EMBARC_PRINTF("EV_TLBMissD");
break;
case EXC_NO_PRO_VIO:
EMBARC_PRINTF("EV_ProtV: ");
dump_protv_exception(cause, param);
break;
case EXC_NO_PRI_VIO:
EMBARC_PRINTF("EV_PrivilegeV: ");
dump_privilege_exception(cause, param);
break;
case EXC_NO_SWI:
EMBARC_PRINTF("EV_SWI");
break;
case EXC_NO_TRAP:
EMBARC_PRINTF("EV_Trap");
break;
case EXC_NO_EXT:
EMBARC_PRINTF("EV_Extension");
break;
case EXC_NO_DIV_ZER0:
EMBARC_PRINTF("EV_DivZero");
break;
case EXC_NO_DC_ERR:
EMBARC_PRINTF("EV_DCError");
break;
case EXC_NO_MAL_ALIGN:
EMBARC_PRINTF("EV_Misaligned");
break;
case EXC_NO_VEC_UNIT:
EMBARC_PRINTF("EV_VecUnit");
break;
default:
EMBARC_PRINTF("unknown exception vector");
break;
}
EMBARC_PRINTF("\n");
}
#endif /* CONFIG_ARC_EXCEPTION_DEBUG */
/**
* @ingroup ARC_HAL_EXCEPTION_CPU
* @brief Install default cpu exception handler
* @param p_excinf Pointer to the exception frame
*/
static void exc_handler_default(void *p_excinf)
{
uint32_t excpt_cause_reg = 0;
uint32_t excpt_ret_reg = 0;
uint32_t exc_no = 0;
uint32_t exc_cause = 0;
uint32_t exc_param = 0;
excpt_cause_reg = arc_aux_read(AUX_ECR);
excpt_ret_reg = arc_aux_read(AUX_ERRET);
exc_no = (excpt_cause_reg >> 16) & 0xff;
exc_cause = (excpt_cause_reg >> 8) & 0xff;
exc_param = (excpt_cause_reg >> 0) & 0xff;
dbg_printf(DBG_LESS_INFO, "default cpu exception handler\r\n");
dbg_printf(DBG_LESS_INFO, "exc_no:%d, last sp:0x%08x, ecr:0x%08x, eret:0x%08x\r\n",
exc_no, p_excinf, excpt_cause_reg, excpt_ret_reg);
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
dump_exception_info(exc_no, exc_cause, exc_param);
#endif
#ifndef EMBARC_UNIT_TEST
arc_kflag(1);
#endif
}
/**
* @ingroup ARC_HAL_EXCEPTION_INTERRUPT
* @brief Register default interrupt handler
* @param p_excinf Information for interrupt handler
*/
static void int_handler_default(void *p_excinf)
{
uint32_t int_cause_reg = 0;
int_cause_reg = arc_aux_read(AUX_IRQ_CAUSE);
dbg_printf(DBG_LESS_INFO, "default interrupt handler\r\n");
dbg_printf(DBG_LESS_INFO, "last sp:0x%08x, icause:0x%08x\r\n", p_excinf, int_cause_reg);
arc_kflag(1);
}
/* Enforcement of 1024 byte alignment */
__attribute__ ((aligned(1024), section(".vector")))
/**
* @cond Doxygen_Suppress
*/
EXC_ENTRY_T exc_entry_table[NUM_EXC_ALL] = { [0] = exc_entry_reset,
[1 ... NUM_EXC_CPU - 1] = exc_entry_cpu,
[NUM_EXC_CPU ... NUM_EXC_ALL - 1] = exc_entry_int
};
/**
* @var EXC_HANDLER_T exc_int_handler_table
* @brief CPU exception and interrupt exception handler table
* called in exc_entry_default and exc_entry_int
*/
EXC_HANDLER_T exc_int_handler_table[NUM_EXC_ALL] = {
[0 ... NUM_EXC_CPU - 1] = exc_handler_default,
[NUM_EXC_CPU ... NUM_EXC_ALL - 1] = int_handler_default
};
/**
* @endcond
*/
typedef struct {
/* note: little endian */
uint32_t save_nr_gpr_pairs : 5; /** Indicates number of general-purpose register pairs saved, from 0 to 8/16 */
uint32_t res : 4; /** Reserved */
uint32_t save_blink : 1; /** Indicates whether to save and restore BLINK */
uint32_t save_lp_regs : 1; /** Indicates whether to save and restore loop registers (LP_COUNT, LP_START, LP_END) */
uint32_t save_u_to_u : 1; /** Indicates if user context is saved to user stack */
uint32_t res2 : 1; /** Reserved */
uint32_t save_idx_regs : 1; /** Indicates whether to save and restore code-density registers (EI_BASE, JLI_BASE, LDI_BASE) */
uint32_t res3 : 18; /** Reserved */
} AUX_IRQ_CTRL_FIELD_T;
typedef union {
AUX_IRQ_CTRL_FIELD_T bits;
uint32_t value;
} AUX_IRQ_CTRL_T;
extern uint8_t _f_stack[];
/**
* @ingroup ARC_HAL_EXCEPTION_INTERRUPT
* @brief Initialize the exception and interrupt handling
*/
void exc_int_init(void)
{
uint32_t i;
uint32_t status;
AUX_IRQ_CTRL_T ictrl;
ictrl.value = 0;
#ifndef ARC_FEATURE_RF16
ictrl.bits.save_nr_gpr_pairs = 6; /* r0 to r11 (r12 saved manually) */
#else
ictrl.bits.save_nr_gpr_pairs = 3; /* r0 to r3, r10, r11 */
#endif
ictrl.bits.save_blink = 1;
ictrl.bits.save_lp_regs = 1; /* LP_COUNT, LP_START, LP_END */
ictrl.bits.save_u_to_u = 0; /* user ctxt saved on kernel stack */
#if ARC_FEATURE_CODE_DENSITY
ictrl.bits.save_idx_regs = 1; /* JLI, LDI, EI */
#endif
status = arc_lock_save();
for (i = NUM_EXC_CPU; i < NUM_EXC_ALL; i++) {
/* interrupt level triggered, disabled, priority is the lowest */
arc_aux_write(AUX_IRQ_SELECT, i);
arc_aux_write(AUX_IRQ_ENABLE, 0);
arc_aux_write(AUX_IRQ_TRIGGER, 0);
#if defined(ARC_FEATURE_SEC_PRESENT)
arc_aux_write(AUX_IRQ_PRIORITY, (1 << AUX_IRQ_PRIORITY_BIT_S)|(INT_PRI_MAX - INT_PRI_MIN));
#else
arc_aux_write(AUX_IRQ_PRIORITY, INT_PRI_MAX - INT_PRI_MIN);
#endif
}
arc_aux_write(AUX_IRQ_CTRL, ictrl.value);
arc_unlock_restore(status);
/** ipm should be set after cpu unlock restore to avoid reset of the status32 value */
arc_int_ipm_set((INT_PRI_MAX - INT_PRI_MIN));
#if ARC_FEATURE_RGF_BANKED_REGS >= 16 && ARC_FEATURE_FIRQ == 1
#if _STACKSIZE < 512
#error "not enough stack size for irq and firq"
#endif
/* top 256 bytes of stack used as firq stack */
arc_firq_stack_set(_f_stack + 256);
#endif
}
/**
* @ingroup ARC_HAL_EXCEPTION_CPU
* @brief Install a CPU exception entry
* @param excno Exception number
* @param entry Exception entry to install
*/
int32_t exc_entry_install(const uint32_t excno, EXC_ENTRY_T entry)
{
uint32_t status;
EXC_ENTRY_T *table;
#if defined(ARC_FEATURE_SEC_PRESENT)
table = (EXC_ENTRY_T *)arc_aux_read(AUX_INT_VECT_BASE_S);
#else
table = (EXC_ENTRY_T *)arc_aux_read(AUX_INT_VECT_BASE);
#endif
if (excno < NUM_EXC_ALL && entry != NULL
&& table[excno] != entry) {
status = cpu_lock_save();
/* directly write to mem, as arc gets exception handler from mem not from cache */
/* FIXME, here maybe icache is dirty, need to be invalidated */
table[excno] = entry;
if (arc_aux_read(AUX_BCR_D_CACHE) > 0x2) {
/* dcache is available */
dcache_flush_line((uint32_t)&table[excno]);
}
if (arc_aux_read(AUX_BCR_D_CACHE) > 0x2) {
/* icache is available */
icache_invalidate_line((uint32_t)&table[excno]);
}
cpu_unlock_restore(status);
return 0;
}
return -1;
}
/**
* @ingroup ARC_HAL_EXCEPTION_CPU
* @brief Get the installed CPU exception entry
* @param excno Exception number
* @return The installed CPU exception entry
*/
EXC_ENTRY_T exc_entry_get(const uint32_t excno)
{
if (excno < NUM_EXC_ALL) {
return exc_entry_table[excno];
}
return NULL;
}
/**
* @ingroup ARC_HAL_EXCEPTION_CPU
* @brief Install an exception handler
* @param excno Exception number
* @param handler The installed CPU exception handler
*/
int32_t exc_handler_install(const uint32_t excno, EXC_HANDLER_T handler)
{
if (excno < NUM_EXC_ALL && handler != NULL) {
exc_int_handler_table[excno] = handler;
return 0;
}
return -1;
}
/**
* @ingroup ARC_HAL_EXCEPTION_CPU
* @brief Get the installed exception handler
* @param excno Exception number
* @return The installed exception handler or NULL
*/
EXC_HANDLER_T exc_handler_get(const uint32_t excno)
{
if (excno < NUM_EXC_ALL) {
return exc_int_handler_table[excno];
}
return NULL;
}
#ifndef EMBARC_OVERRIDE_ARC_INTERRUPT_MANAGEMENT
/**
* @brief Disable interrupt
*
* @param intno Interrupt number
*/
int32_t int_disable(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
arc_int_disable(intno);
return 0;
}
return -1;
}
/**
* @brief Enable interrupt
*
* @param intno Interrupt number
*/
int32_t int_enable(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
arc_int_enable(intno);
return 0;
}
return -1;
}
/**
* @brief Get interrupt enable state
*
* @param intno Interrupt number
* @return 0 disabled, 1 enabled, < 0 error
*/
int32_t int_enabled(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
arc_aux_write(AUX_IRQ_SELECT, intno);
return arc_aux_read(AUX_IRQ_ENABLE);
}
return -1;
}
/**
* @brief Get interrupt priority masking threshold
*
* @returns Interrupt priority masking threshold, negative num
*/
int32_t int_ipm_get(void)
{
return ((int32_t)arc_int_ipm_get() + INT_PRI_MIN);
}
/**
* @brief Set interrupt priority masking threshold
*
* @param intpri Interrupt priority masking threshold
*/
int32_t int_ipm_set(int32_t intpri)
{
if (intpri >= INT_PRI_MIN && intpri <= INT_PRI_MAX) {
arc_int_ipm_set(intpri - INT_PRI_MIN);
return 0;
}
return -1;
}
/**
* @brief Get current interrupt priority masking threshold
*
* @param intno Interrupt number
* @return < 0 interrupt priority, 0 error
*/
int32_t int_pri_get(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
return (int32_t)arc_int_pri_get(intno) + INT_PRI_MIN;
}
return 0;
}
/**
* @brief Set interrupt priority
*
* @param intno Interrupt number
* @param intpri Interrupt priority
* @return < 0 error, 0 ok
*/
int32_t int_pri_set(const uint32_t intno, int32_t intpri)
{
uint32_t status;
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
status = cpu_lock_save();
intpri = intpri - INT_PRI_MIN;
arc_int_pri_set(intno, (uint32_t)intpri);
cpu_unlock_restore(status);
return 0;
}
return -1;
}
/**
* @brief Set interrupt secure or not secure
* @param intno Interrupt number
* @param secure 0 for normal, > 0 for secure
* @return < 0 error, 0 ok
*/
int32_t int_secure_set(const uint32_t intno, uint32_t secure)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
arc_int_secure_set(intno, secure);
return 0;
}
return -1;
}
/**
* @brief Probe interrupt pending state
*
* @param intno Interrupt number
*
* @returns 1 pending, 0 no pending, -1 error
*/
int32_t int_probe(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
return arc_int_probe(intno);
}
return -1;
}
/**
* @brief Trigger interrupt through software
*
* @param intno Interrupt number
* @return 0 ok, -1 error
*/
int32_t int_sw_trigger(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
arc_int_sw_trigger(intno);
return 0;
}
return -1;
}
/**
* @brief Configure interrupt trigger mode
*
* @param intno Interrupt number
* @param level 0-level triggered, 1-pulse triggered
* @return 0 ok, -1 error
*/
int32_t int_level_config(const uint32_t intno, const uint32_t level)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
arc_int_level_config(intno, level);
return 0;
}
return -1;
}
/**
* \brief Get interrupt request mode
*
* @param intno Interrupt number
*/
int32_t int_level_get(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
return (int32_t)arc_int_level_get(intno);
}
return -1;
}
/**
* @brief lock cpu, disable interrupts
*/
void cpu_lock(void)
{
arc_lock();
}
/**
* @brief Unlock cpu to enable interrupts
*/
void cpu_unlock(void)
{
arc_unlock();
}
/**
* @brief Lock cpu and return status
*
* @returns CPU status
*/
uint32_t cpu_lock_save(void)
{
return arc_lock_save();
}
/**
* @brief Unlock cpu with the specific status
*
* @param status CPU status saved by cpu_lock_save
*/
void cpu_unlock_restore(const uint32_t status)
{
arc_unlock_restore(status);
}
/**
* @ingroup ARC_HAL_EXCEPTION_INTERRUPT
* @brief Install interrupt handler
* @param intno Interrupt number
* @param handler Interrupt handler
*/
int32_t int_handler_install(const uint32_t intno, INT_HANDLER_T handler)
{
/*!< @todo parameter check ? */
if (intno >= NUM_EXC_CPU) {
return exc_handler_install(intno, handler);
}
return -1;
}
/**
* @ingroup ARC_HAL_EXCEPTION_INTERRUPT
* @brief Get the installed interrupt handler
* @param intno Interrupt number
* @return The installed interrupt handler or NULL
*/
INT_HANDLER_T int_handler_get(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU) {
return exc_handler_get(intno);
}
return NULL;
}
#endif /* EMBARC_OVERRIDE_ARC_INTERRUPT_MANAGEMENT */
/**
* @brief Set the stack pointer for firq handling
*
* @param firq_sp stack pointer
*/
void arc_firq_stack_set(uint8_t *firq_sp)
{
uint32_t status;
if (firq_sp == NULL) {
return;
}
status = arc_lock_save();
Asm(
/* only ilink will not be banked, so use ilink as channel
* between 2 banks
*/
"mov %%ilink, %0 \n\t"
"lr %0, [%1] \n\t"
"or %0, %0, %2 \n\t"
"kflag %0 \n\t"
"mov %%sp, %%ilink \n\t"
/* switch back to bank0, use ilink to avoid the pollution of
* bank1's gp regs.
*/
"lr %%ilink, [%1] \n\t"
"and %%ilink, %%ilink, %3 \n\t"
"kflag %%ilink \n\t"
:
: "r" (firq_sp), "i" (AUX_STATUS32),
"i" (AUX_STATUS_RB(1)),
"i" (~AUX_STATUS_RB(7))
);
arc_unlock_restore(status);
}
/** @} end of group ARC_HAL_EXCEPTION_CPU */

View File

@@ -1,89 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "arc/arc_mp.h"
static volatile struct {
void (*fn)(uint32_t, void *);
void *arg;
} arc_cpu_init[ARC_FEATURE_MP_NUM_CPUS];
/*
* arc_cpu_wake_flag is used to sync up master core and slave cores
* Slave core will spin for arc_cpu_wake_flag until master core sets
* it to the core id of slave core. Then, slave core clears it to notify
* master core that it's waken
*
*/
volatile uint32_t arc_cpu_wake_flag;
volatile uint8_t *arc_cpu_sp;
/**
* @brief Start slave cpu
* master core call this function to start slave cpu
* @param cpu_num Slave cpu number
* @param stack The pointer to stack area of slave cpu
* @param sz Stack size
* @param fn Function that slave cpu execute
* @param arg Argument for slave cpu
*/
void arc_start_slave_cpu(uint32_t cpu_num, uint8_t *stack, uint32_t sz,
void (*fn)(uint32_t, void *), void *arg)
{
arc_cpu_init[cpu_num].fn = fn;
arc_cpu_init[cpu_num].arg = arg;
/* set the initial sp of target sp through arc_cpu_sp
* arc_cpu_wake_flag will protect arc_cpu_sp that
* only one slave cpu can read it per time
*/
arc_cpu_sp = stack + sz;
arc_cpu_wake_flag = cpu_num;
/* wait slave cpu to start */
while (arc_cpu_wake_flag != 0) {
;
}
}
/**
* @brief The C entry of slave cpu
*
* @param cpu_num Slave cpu id
*/
void arc_slave_start(uint32_t cpu_num)
{
void (*fn)(uint32_t, void *);
fn = arc_cpu_init[cpu_num].fn;
fn(cpu_num, arc_cpu_init[cpu_num].arg);
}

View File

@@ -1,198 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "arc/arc_mpu.h"
#define CALC_REGION_END_ADDR(start, size) \
(start + size - (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS))
/**
* @brief Enable the memory protection unit
*
*/
void arc_mpu_enable(void)
{
#if ARC_FEATURE_MPU_VERSION == 2
arc_aux_write(AUX_MPU_EN, arc_aux_read(AUX_MPU_EN) | AUX_MPU_EN_ENABLE);
#elif ARC_FEATURE_MPU_VERSION == 4
arc_mpu_default(0);
#endif
}
/**
* @brief Disable the memory protection unit
*
*/
void arc_mpu_disable(void)
{
#if ARC_FEATURE_MPU_VERSION == 2
arc_aux_write(AUX_MPU_EN, arc_aux_read(AUX_MPU_EN) & AUX_MPU_EN_DISABLE);
#elif ARC_FEATURE_MPU_VERSION == 4
arc_mpu_default(ARC_MPU_REGION_ALL_ATTR | AUX_MPU_ATTR_S | AUX_MPU_ATTR_SID(1));
#endif
}
/**
* @brief Configure the given mpu region
*
* @param index Region index to be configured
* @param base Base address for the region
* @param size Region size of the region to be configured
* @param region_attr Attribute value of mpu region
*/
void arc_mpu_region_config(uint32_t index, uint32_t base, uint32_t size, uint32_t region_attr)
{
if (index >= ARC_FEATURE_MPU_REGIONS) {
return;
}
region_attr &= AUX_MPU_ATTR_MASK;
/* ARC MPU version 2 and version 3 have different aux reg interface */
#if ARC_FEATURE_MPU_VERSION == 2
uint8_t bits = arc_find_msb(size) - 1;
if (bits < ARC_FEATURE_MPU_ALIGNMENT_BITS) {
bits = ARC_FEATURE_MPU_ALIGNMENT_BITS;
}
if ((1 << bits) < size) {
bits++;
}
if (size > 0) {
region_attr |= AUX_MPU_RDP_REGION_SIZE(bits);
base |= AUX_MPU_VALID_MASK;
} else {
base = 0;
}
arc_aux_write(2 * index + AUX_MPU_RDP0, region_attr);
arc_aux_write(2 * index + AUX_MPU_RDB0, base);
#elif ARC_FEATURE_MPU_VERSION == 4
if (size < (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS)) {
size = (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS);
}
if (region_attr) {
region_attr |= AUX_MPU_VALID_MASK;
}
arc_aux_write(AUX_MPU_INDEX, index);
arc_aux_write(AUX_MPU_RSTART, base);
arc_aux_write(AUX_MPU_REND, CALC_REGION_END_ADDR(base, size));
arc_aux_write(AUX_MPU_RPER, region_attr);
#endif
}
/**
* @brief Set default attribute of mpu region
*
* @param region_attr Attribute value
*/
void arc_mpu_default(uint32_t region_attr)
{
uint32_t val = arc_aux_read(AUX_MPU_EN) &
(~AUX_MPU_ATTR_MASK);
arc_aux_write(AUX_MPU_EN, (region_attr & AUX_MPU_ATTR_MASK) | val);
}
/**
* @brief Check whether [start, start+size] in the given mpu region
*
* @param index Region index
* @param start Start address of memory
* @param size Size of memory
* @return 1 in the given mpu region, 0 not in
*/
int32_t arc_mpu_in_region(uint32_t index, uint32_t start, uint32_t size)
{
#if ARC_FEATURE_MPU_VERSION == 2
uint32_t r_addr_start;
uint32_t r_addr_end;
uint32_t r_size_lshift;
r_addr_start = arc_aux_read(AUX_MPU_RDB0 + 2 * index) & (~AUX_MPU_VALID_MASK);
r_size_lshift = arc_aux_read(AUX_MPU_RDP0 + 2 * index) & AUX_MPU_ATTR_MASK;
r_size_lshift = (r_size_lshift & 0x3) | ((r_size_lshift >> 7) & 0x1C);
r_addr_end = r_addr_start + (1 << (r_size_lshift + 1));
if (start >= r_addr_start && (start + size) < r_addr_end) {
return 1;
}
#elif ARC_FEATURE_MPU_VERSION == 4
if ((index == arc_mpu_probe(start)) &&
(index == arc_mpu_probe(start + size))) {
return 1;
}
#endif
return 0;
}
/**
* @brief Probe whether the given address in mpu entries
*
* @param addr The given address
* @return -1 not in mpu entries, -2 mpu version error, >= 0 mpu entry number
*/
int32_t arc_mpu_probe(uint32_t addr)
{
#if ARC_FEATURE_MPU_VERSION == 2
uint32_t index;
uint32_t regions = ARC_FEATURE_MPU_REGIONS;
for (index = 0; index < regions; index++) {
if (arc_mpu_in_region(index, addr, 0)) {
return (int32_t)index;
}
}
return -1;
#elif ARC_FEATURE_MPU_VERSION == 4
uint32_t index;
arc_aux_write(AUX_MPU_PROBE, addr);
index = arc_aux_read(AUX_MPU_INDEX);
/* if no match or multiple regions match, return error */
if (index & (AUX_MPU_INDEX_DEFAULT | AUX_MPU_INDEX_MULT)) {
return -1;
} else {
return (int32_t)index;
}
#else
return -2;
#endif
}

View File

@@ -1,447 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_TIMER
* @brief Internal timer implementation
* @todo RTC support should be improved if RTC is enabled
*/
#include "arc/arc_timer.h"
#include "arc/arc_exception.h"
#define LPS_PREC 8
static volatile uint64_t gl_loops_per_jiffy = 1;
static volatile uint32_t gl_count = 1;
/**
* @brief Check whether the specific timer present
* @param no Timer number
* @return 1 present, 0 not present
*/
int32_t timer_present(const uint32_t no)
{
uint32_t bcr = arc_aux_read(AUX_BCR_TIMERS);
switch (no) {
case TIMER_0:
bcr = (bcr >> 8) & 1;
break;
case TIMER_1:
bcr = (bcr >> 9) & 1;
break;
case TIMER_RTC:
bcr = (bcr >> 10) & 1;
break;
default:
bcr = 0;
/* illegal argument so return false */
break;
}
return (int32_t)bcr;
}
/**
* @brief Start a timer
* @param no Timer number
* @param mode Timer mode
* @param val Timer limit value (not for RTC)
* @return 0 success, -1 failure
*/
int32_t timer_start(const uint32_t no, const uint32_t mode, const uint32_t val)
{
int32_t ercd = 0;
switch (no) {
case TIMER_0:
arc_aux_write(AUX_TIMER0_CTRL, 0);
arc_aux_write(AUX_TIMER0_LIMIT, val);
arc_aux_write(AUX_TIMER0_CTRL, mode);
arc_aux_write(AUX_TIMER0_CNT, 0);
break;
case TIMER_1:
arc_aux_write(AUX_TIMER1_CTRL, 0);
arc_aux_write(AUX_TIMER1_LIMIT, val);
arc_aux_write(AUX_TIMER1_CTRL, mode);
arc_aux_write(AUX_TIMER1_CNT, 0);
break;
case TIMER_RTC:
arc_aux_write(AUX_RTC_CTRL, mode);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Stop timer
*
* @param no Timer number
* @return 0 success, -1 failure
*/
int32_t timer_stop(const uint32_t no)
{
int32_t ercd = 0;
switch (no) {
case TIMER_0:
arc_aux_write(AUX_TIMER0_CTRL, 0);
arc_aux_write(AUX_TIMER0_LIMIT, 0);
arc_aux_write(AUX_TIMER0_CNT, 0);
break;
case TIMER_1:
arc_aux_write(AUX_TIMER1_CTRL, 0);
arc_aux_write(AUX_TIMER1_LIMIT, 0);
arc_aux_write(AUX_TIMER1_CNT, 0);
break;
case TIMER_RTC:
arc_aux_write(AUX_RTC_CTRL, TIMER_RTC_CLEAR);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Get timer current tick
*
* @param no Timer number
* @param val Timer current tick value
* @return 0 success, -1 failure
*/
int32_t timer_current(const uint32_t no, void *val)
{
int32_t ercd = 0;
switch (no) {
case TIMER_0:
*((uint32_t *)val) = arc_aux_read(AUX_TIMER0_CNT);
break;
case TIMER_1:
*((uint32_t *)val) = arc_aux_read(AUX_TIMER1_CNT);
break;
case TIMER_RTC:
*((uint64_t *)val) = arc_aux_read(AUX_RTC_LOW);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Clear the interrupt pending bit of timer
*
* @param no Timer number
* @return 0 success, -1 failure
*/
int32_t timer_int_clear(const uint32_t no)
{
int32_t ercd = 0;
switch (no) {
case TIMER_0:
arc_aux_write(AUX_TIMER0_CTRL,
arc_aux_read(AUX_TIMER0_CTRL) & (~TIMER_CTRL_IP));
break;
case TIMER_1:
arc_aux_write(AUX_TIMER1_CTRL,
arc_aux_read(AUX_TIMER1_CTRL) & (~TIMER_CTRL_IP));
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Initialize internal timer
*/
void arc_timer_init(void)
{
if (timer_present(TIMER_0)) {
timer_stop(TIMER_0);
}
if (timer_present(TIMER_1)) {
timer_stop(TIMER_1);
}
if (timer_present(TIMER_RTC)) {
timer_stop(TIMER_RTC);
}
}
#if defined(ARC_FEATURE_SEC_TIMER1_PRESENT) || defined(ARC_FEATURE_SEC_TIMER0_PRESENT)
/**
* @brief Check whether the specific secure timer present
* @param no Timer number
* @return 1 present, 0 not present
*/
int32_t secure_timer_present(const uint32_t no)
{
uint32_t bcr = arc_aux_read(AUX_BCR_TIMERS);
switch (no) {
case SECURE_TIMER_0:
bcr = (bcr >> 11) & 1;
break;
case SECURE_TIMER_1:
bcr = (bcr >> 12) & 1;
break;
default:
bcr = 0;
/* illegal argument so return false */
break;
}
return (int32_t)bcr;
}
/**
* @brief Start an secure timer
* @param no Timer number
* @param mode Timer mode
* @param val Timer limit value (not for RTC)
* @return 0 success, -1 failure
*/
int32_t secure_timer_start(const uint32_t no, const uint32_t mode, const uint32_t val)
{
int32_t ercd = 0;
switch (no) {
case SECURE_TIMER_0:
arc_aux_write(AUX_SECURE_TIMER0_CTRL, 0);
arc_aux_write(AUX_SECURE_TIMER0_LIMIT, val);
arc_aux_write(AUX_SECURE_TIMER0_CTRL, mode);
arc_aux_write(AUX_SECURE_TIMER0_CNT, 0);
break;
case SECURE_TIMER_1:
arc_aux_write(AUX_SECURE_TIMER1_CTRL, 0);
arc_aux_write(AUX_SECURE_TIMER1_LIMIT, val);
arc_aux_write(AUX_SECURE_TIMER1_CTRL, mode);
arc_aux_write(AUX_SECURE_TIMER1_CNT, 0);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Stop and clear a secure timer
*
* @param no Timer number
* @return 0 success, -1 failure
*/
int32_t secure_timer_stop(const uint32_t no)
{
int32_t ercd = 0;
switch (no) {
case SECURE_TIMER_0:
arc_aux_write(AUX_SECURE_TIMER0_CTRL, 0);
arc_aux_write(AUX_SECURE_TIMER0_LIMIT, 0);
arc_aux_write(AUX_SECURE_TIMER0_CNT, 0);
break;
case SECURE_TIMER_1:
arc_aux_write(AUX_SECURE_TIMER1_CTRL, 0);
arc_aux_write(AUX_SECURE_TIMER1_LIMIT, 0);
arc_aux_write(AUX_SECURE_TIMER1_CNT, 0);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Get secure timer current tick
*
* @param no Timer number
* @param val Timer value
* @return 0 success, -1 failure
*/
int32_t secure_timer_current(const uint32_t no, void *val)
{
int32_t ercd = 0;
switch (no) {
case SECURE_TIMER_0:
*((uint32_t *)val) = arc_aux_read(AUX_SECURE_TIMER0_CNT);
break;
case SECURE_TIMER_1:
*((uint32_t *)val) = arc_aux_read(AUX_SECURE_TIMER1_CNT);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Clear the interrupt pending bit of timer
*
* @param no Timer number
* @return 0 success, -1 failure
*/
int32_t secure_timer_int_clear(const uint32_t no)
{
int32_t ercd = 0;
switch (no) {
case SECURE_TIMER_0:
arc_aux_write(AUX_SECURE_TIMER0_CTRL,
arc_aux_read(AUX_SECURE_TIMER0_CTRL) & (~TIMER_CTRL_IP));
break;
case SECURE_TIMER_1:
arc_aux_write(AUX_SECURE_TIMER1_CTRL,
arc_aux_read(AUX_SECURE_TIMER1_CTRL) & (~TIMER_CTRL_IP));
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Initialize internal secure timer
*/
void secure_timer_init(void)
{
if (secure_timer_present(SECURE_TIMER_0)) {
secure_timer_stop(SECURE_TIMER_0);
}
if (secure_timer_present(SECURE_TIMER_1)) {
secure_timer_stop(SECURE_TIMER_1);
}
}
#endif /* ARC_FEATURE_SEC_TIMER1_PRESENT && ARC_FEATURE_SEC_TIMER0_PRESENT */
/**
* @brief Function for delaying execution for number of microseconds
*
* @param usecs Number of us
*/
void arc_delay_us(uint32_t usecs)
{
if (usecs == 0) {
return;
}
usecs = usecs * gl_loops_per_jiffy / gl_count;
__asm__ __volatile__ (
" .align 4 \n"
" mov %%lp_count, %0 \n"
" lp 1f \n"
" nop \n"
"1: \n"
:
: "r" (usecs)
: "lp_count");
}
/**
* @brief Get calibration values for a given cpu clock source
*
* @param cpu_clock board CPU clock source to calibrate
* @return loops_per_jiffy Calibration value
*/
uint64_t timer_calibrate_delay(uint32_t cpu_clock)
{
uint64_t loopbit;
int32_t lps_precision = LPS_PREC;
volatile uint64_t loops_per_jiffy;
uint32_t timer0_limit;
uint32_t status;
gl_loops_per_jiffy = 1;
gl_count = 1;
cpu_clock /= 1000;
status = cpu_lock_save();
timer0_limit = arc_aux_read(AUX_TIMER0_LIMIT);
arc_aux_write(AUX_TIMER0_LIMIT, 0xFFFFFFFF);
loops_per_jiffy = (1 << 4);
while ((loops_per_jiffy <<= 1) != 0) {
arc_aux_write(AUX_TIMER0_CNT, 0);
arc_delay_us(loops_per_jiffy);
if (arc_aux_read(AUX_TIMER0_CNT) > cpu_clock) {
break;
}
}
loops_per_jiffy >>= 1;
loopbit = loops_per_jiffy;
while (lps_precision-- && (loopbit >>= 1)) {
loops_per_jiffy |= loopbit;
arc_aux_write(AUX_TIMER0_CNT, 0);
arc_delay_us(loops_per_jiffy);
if (arc_aux_read(AUX_TIMER0_CNT) > cpu_clock) {
loops_per_jiffy &= ~loopbit;
}
}
gl_loops_per_jiffy = loops_per_jiffy;
gl_count = 1000;
arc_aux_write(AUX_TIMER0_CNT, 0);
arc_aux_write(AUX_TIMER0_LIMIT, timer0_limit);
cpu_unlock_restore(status);
return loops_per_jiffy;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#define __ASSEMBLY__
#include "arc/arc.h"
#include "arc/arc_asm_common.h"
.file "arc_utils.s"
/**
* @brief Go to user mode
*
* @param target Target address to run in user mode, 0 means next
* line of code
* @param sp Stack where the target address runs, 0 means using
* current stack
*/
.text
.global arc_goto_usermode
.align 4
arc_goto_usermode:
cmp r0, 0
mov.z r0, blink
cmp r1, 0
mov.nz sp, r1
#if defined(ARC_FEATURE_SEC_PRESENT)
sr (1 << AUX_ERSEC_STAT_BIT_ERM), [AUX_ERSEC_STAT]
sr sp, [AUX_SEC_U_SP]
#else
sr sp, [AUX_USER_SP]
#endif
lr r1, [AUX_STATUS32]
bset r1, r1, AUX_STATUS_BIT_U
sr r1, [AUX_ERSTATUS]
lr r1, [AUX_STATUS32]
bset r1, r1, AUX_STATUS_BIT_AE
kflag r1
sr r0, [AUX_ERRET]
rtie
/**
* @brief go to kernel mode
* this function uses trap exception to do switch from user mode to kernel mode,
* please install exc_entry_arc_goto_kernelmode for trap exception before call this
* function
* @param target, the target address to run in kernel mode, 0 means next line of code
* @param sp, the stack where the target address runs, 0 means using current stack
*/
.text
.global arc_goto_kernelmode
.global exc_entry_arc_goto_kernelmode
.align 4
arc_goto_kernelmode:
cmp r0, 0
mov.z r0, blink
cmp r1, 0
mov.z r1, sp
trap_s 0
.align 4
exc_entry_arc_goto_kernelmode:
mov sp, r1
sr r0, [AUX_ERRET]
lr r0, [AUX_ERSTATUS]
bclr r0, r0, AUX_STATUS_BIT_U
sr r0, [AUX_ERSTATUS]
rtie

View File

@@ -1,171 +0,0 @@
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
*
* 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
*
* 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.
*/
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_STARTUP
* @brief C++ support module for ARC
*/
#if defined(__GNU__)
#include "embarc_toolchain.h"
/* embARC's GNU C++ support takes reference from Zephyr (cpp_xxx.c) */
/**
* @brief
* The ctors section contains a list of function pointers that execute the
* C++ constructors of static global objects. These must be executed before
* the application's main() routine.
*
* NOTE: Not all compilers put those function pointers into the ctors section;
* some put them into the init_array section instead.
*/
/* What a constructor function pointer looks like */
typedef void (*CTOR_FUNC_PTR_T)(void);
/* Constructor function pointer list is generated by the linker script. */
extern CTOR_FUNC_PTR_T __CTOR_LIST__[];
extern CTOR_FUNC_PTR_T __CTOR_END__[];
/**
*
* @brief Invoke all C++ style global object constructors
*
* This routine is invoked before the execution of the
* application's main().
*/
void arc_gnu_do_global_ctors_aux(void)
{
uint32_t num_ctors;
num_ctors = (uint32_t)__CTOR_LIST__[0];
while (num_ctors >= 1) {
__CTOR_LIST__[num_ctors--]();
}
}
typedef void (*DTOR_FUNC_PTR_T)(void);
extern DTOR_FUNC_PTR_T __DTOR_LIST__[];
extern DTOR_FUNC_PTR_T __DTOR_END__[];
/**
*
* @brief Invoke all C++ style global object destructors
*
* This routine is invoked after the execution of the
* application's main().
*/
void arc_gnu_do_global_dtors_aux(void)
{
uint32_t nDtors;
uint32_t i;
nDtors = (uint32_t)__DTOR_LIST__[0];
i = 1;
while (i <= nDtors) {
__DTOR_LIST__[i++]();
}
}
void *__dso_handle = 0;
/**
* @brief Register destructor for a global object
*
* @param destructor the global object destructor function
* @param objptr global object pointer
* @param dso Dynamic Shared Object handle for shared libraries
*
* Function does nothing at the moment, assuming the global objects
* do not need to be deleted
*
* @return N/A
*/
int32_t __cxa_atexit(void (*destructor)(void *), void *objptr, void *dso)
{
return 0;
}
typedef void (*FUNC_PTR_T)(void);
extern FUNC_PTR_T __init_array_start[0];
extern FUNC_PTR_T __init_array_end[0];
/**
* @brief Execute initialization routines referenced in .init_array section
*
* @return N/A
*/
void arc_gnu_do_init_array_aux(void)
{
for (FUNC_PTR_T *func = __init_array_start;
func < __init_array_end;
func++) {
(*func)();
}
}
/**
* @brief Stub for pure virtual functions
*
* This routine is needed for linking C++ code that uses pure virtual
* functions.
*
* @return N/A
*/
void __cxa_pure_virtual(void)
{
while (1) {
;
}
}
#endif

View File

@@ -1,233 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_STARTUP
* @brief Assembly part of startup process
*/
/**
* @addtogroup ARC_HAL_STARTUP
* @{
*/
/** @cond STARTUP_ASM */
#define __ASSEMBLY__
#include "arc/arc.h"
#include "arc/arc_asm_common.h"
.file "arc_startup.s"
.weak _f_sdata /* start of small data, defined in link script */
.weak init_hardware_hook /* app hardware init hook */
.extern board_main
.extern exc_entry_table
/* initial vector table */
.section .init_vector, "a"
.long exc_entry_reset
.section .init_bootstrap, "ax"
.global exc_entry_reset
.global _start
.align 4
_start:
exc_entry_reset:
_arc_reset_stage1:
kflag STATUS32_RESET_VALUE
/* STAGE 1 */
/* necessary hardware should be done first to speed up initialization
1. system clk
2. mem controller must be initialized before any access to external
mem.
3. others
*/
_arc_cache_init_start:
lr r0, [AUX_BCR_D_CACHE]
cmp r0, 2
/* invalidate dcache */
jle _arc_icache_init
mov r0, 1
sr r0, [AUX_DC_IVDC]
sr r0, [AUX_DC_CTRL]
_arc_icache_init:
lr r0, [AUX_BCR_I_CACHE]
cmp r0, 2
jle _arc_cache_init_end
/* invalidate icache */
mov r0, 1
sr r0, [AUX_IC_IVIC]
nop_s
nop_s
nop_s
sr r0, [AUX_IC_CTRL]
_arc_cache_init_end:
mov r0, init_hardware_hook
cmp r0, 0
jlne [r0]
/* STAGE 2: init necessary registers */
_arc_reset_stage2:
mov r0, 0
/* interrupt related init */
sr r0, [AUX_IRQ_ACT]
sr r0, [AUX_IRQ_CTRL]
sr r0, [AUX_IRQ_HINT]
/* use the new vector table to replace the old one */
#if defined(ARC_FEATURE_SEC_PRESENT)
sr exc_entry_table, [AUX_INT_VECT_BASE_S]
#else
sr exc_entry_table, [AUX_INT_VECT_BASE]
#endif
mov gp, _f_sdata /* init small-data base register */
mov fp, 0 /* init fp register */
#if ARC_FEATURE_MP_NUM_CPUS > 1
GET_CORE_ID r0
breq r0, 0, _master_core_startup
_slave_core_wait:
ld r1, [arc_cpu_wake_flag]
brne r0, r1, _slave_core_wait
ld sp, [arc_cpu_sp]
/* signal master core that slave core runs */
st 0, [arc_cpu_wake_flag]
j arc_slave_start
_master_core_startup:
#endif
mov sp, _e_stack /* init stack pointer */
_arc_reset_stage3:
_s3_copy_text:
mov r0, _f_text
mov r1, _load_addr_text
cmp r0, r1
/* if load addr == run addr, no need to copy */
jeq _s3_copy_rodata
mov r3, _e_text
_s3_copy_text_loop:
ld.ab r2, [r1, 4]
st.ab r2, [r0, 4]
cmp r0, r3
jlt _s3_copy_text_loop
_s3_copy_rodata:
mov r0, _f_rodata
mov r1, _load_addr_rodata
cmp r0, r1
/* if load addr == run addr, no need to copy */
jeq _s3_copy_data
mov r3, _e_rodata
_s3_copy_rodata_loop:
ld.ab r2, [r1, 4]
st.ab r2, [r0, 4]
cmp r0, r3
jlt _s3_copy_rodata_loop
_s3_copy_data:
mov r0, _f_data
mov r1, _load_addr_data
cmp r0, r1
jeq _s3_clear_bss
/* if load addr == run addr, no need to copy */
mov r3, _e_data
_s3_copy_data_loop:
ld.ab r2, [r1, 4]
st.ab r2, [r0, 4]
cmp r0, r3
jlt _s3_copy_data_loop
_s3_clear_bss:
mov r0, _f_bss
mov r1, _e_bss
cmp r0, r1
jge _arc_reset_call_main
mov r2, 0
_s3_clear_bss_loop:
st.ab r2, [r0, 4]
cmp r0, r1
jlt _s3_clear_bss_loop
/* STAGE 3: go to next level initialization */
_arc_reset_call_main:
jl board_main /* board-level main */
b _exit_loop
.global _exit_loop
.global _exit_halt
.align 4
_exit_halt:
_exit_loop:
flag AUX_STATUS_MASK_HALT
nop
nop
nop
b _exit_loop
#if defined(__MW__)
.global arc_mwdt_init, arc_mwdt_fini
.section ".init",text
arc_mwdt_init:
.cfa_bf arc_mwdt_init
push %blink
.cfa_push {%blink}
.section ".init$999999", text, 1, 2, check_text_align=0
pop %blink
.cfa_pop {%blink}
j [%blink]
.cfa_ef
.section ".fini", text
arc_mwdt_fini:
.cfa_bf _fini
push %blink
.cfa_push {%blink}
.section ".fini$999999", text, 1, 2, check_text_align=0
pop %blink
.cfa_pop {%blink}
j [%blink]
.cfa_ef
#endif
/** @endcond */
/** }@*/

View File

@@ -1,259 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC.h"
#include "embARC_debug.h"
#define MAX_SYS_COUNTER_VALUE (0xffffffff)
#ifndef BOARD_SYS_TIMER_HZ
#define BOARD_SYS_TIMER_HZ (1000)
#endif
#ifndef EMBARC_BANNER_TYPE
#define EMBARC_BANNER_TYPE 1
#endif
static const char *embarc_banner =
#if EMBARC_BANNER_TYPE == 1
"----------------------------------------------------------- \r\n\
____ _ ____ \r\n\
| _ \\ _____ _____ _ __ ___ __| | __ ) _ _ \r\n\
| |_) / _ \\ \\ /\\ / / _ \\ '__/ _ \\/ _` | _ \\| | | | \r\n\
| __/ (_) \\ V V / __/ | | __/ (_| | |_) | |_| | \r\n\
|_| \\___/ \\_/\\_/ \\___|_| \\___|\\__,_|____/ \\__, | \r\n\
|___/ \r\n\
_ _ ____ ____ \r\n\
___ _ __ ___ | |__ / \\ | _ \\ / ___| \r\n\
/ _ \\ '_ ` _ \\| '_ \\ / _ \\ | |_) | | \r\n\
| __/ | | | | | |_) / ___ \\| _ <| |___ \r\n\
\\___|_| |_| |_|_.__/_/ \\_\\_| \\_\\\\____| \r\n\
------------------------------------------------------------ \r\n\
";
#else
"-----------------------------------------------------------------------------------------------\r\n\
_/_/_/ _/ _/_/_/ \r\n\
_/ _/ _/_/ _/ _/ _/ _/_/ _/ _/_/ _/_/ _/_/_/ _/ _/ _/ _/ \r\n\
_/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/ _/_/_/_/ _/ _/ _/_/_/ _/ _/ \r\n\
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \r\n\
_/ _/_/ _/ _/ _/_/_/ _/ _/_/_/ _/_/_/ _/_/_/ _/_/_/ \r\n\
_/ \r\n\
_/_/ \r\n\
_/ _/_/ _/_/_/ _/_/_/ \r\n\
_/_/ _/_/_/ _/_/ _/_/_/ _/ _/ _/ _/ _/ \r\n\
_/_/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/_/ _/ \r\n\
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \r\n\
_/_/_/ _/ _/ _/ _/_/_/ _/ _/ _/ _/ _/_/_/ \r\n\
------------------------------------------------------------------------------------------------\r\n\
";
#endif
/** board timer interrupt reset count */
static uint32_t cyc_hz_count = (BOARD_CPU_CLOCK / BOARD_SYS_TIMER_HZ);
/** board timer counter in timer interrupt */
static volatile uint64_t gl_sys_hz_cnt = 0;
/** board 1ms counter */
static volatile uint32_t gl_ms_cnt = 0;
#define HZ_COUNT_CONV(precision, base) ((precision) / (base))
/**
* @brief Board bare-metal timer interrupt.
* Interrupt frequency is based on the defined @ref BOARD_SYS_TIMER_HZ
*/
static void board_timer_isr(void *ptr)
{
timer_int_clear(BOARD_SYS_TIMER_ID);
board_timer_update(BOARD_SYS_TIMER_HZ);
}
/**
* @brief Initialise bare-metal board timer and interrupt
* @details
* This function is called in @ref board_init, and
* it initializes the 1-MS timer interrupt for bare-metal mode
*/
static void board_timer_init(void)
{
if (timer_present(BOARD_SYS_TIMER_ID)) {
int_disable(BOARD_SYS_TIMER_INTNO); /* disable first then enable */
int_handler_install(BOARD_SYS_TIMER_INTNO, board_timer_isr);
timer_start(BOARD_SYS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cyc_hz_count); /* start 1ms timer interrupt */
int_enable(BOARD_SYS_TIMER_INTNO);
}
}
static void platform_print_banner(void)
{
EMBARC_PRINTF("%s\r\n", embarc_banner);
EMBARC_PRINTF("embARC Build Time: %s, %s\r\n", __DATE__, __TIME__);
#if defined(__GNU__)
EMBARC_PRINTF("Compiler Version: ARC GNU, %s\r\n", __VERSION__);
#else
EMBARC_PRINTF("Compiler Version: Metaware, %s\r\n\r\n", __VERSION__);
#endif
}
EMBARC_WEAK void platform_main(void)
{
#ifdef LIB_CONSOLE
xprintf_setup();
#endif
platform_print_banner();
arc_goto_main(0, NULL);
}
EMBARC_WEAK void board_main(void)
{
#if defined(__MW__)
/* Metaware toolchain C++ init */
arc_mwdt_init();
#elif defined(__GNU__)
/* ARC GNU toolchain C++ init */
arc_gnu_do_global_ctors_aux();
arc_gnu_do_init_array_aux();
#endif
/* init core level interrupt & exception management */
exc_int_init();
/* init cache */
arc_cache_init();
/* necessary board level init */
board_init();
/* Initialise bare-metal board timer and interrupt */
board_timer_init();
/* platform (e.g RTOS, baremetal)level init */
platform_main();
#if defined(__MW__)
arc_mwdt_fini();
#elif defined(__GNU__)
arc_gnu_do_global_dtors_aux();
#endif
}
/**
* @brief Update timer counter and other MS period operation
* in cycling interrupt and must be called periodically.
* @param precision interrupt-period precision in Hz
*/
void board_timer_update(uint32_t precision)
{
static uint32_t sys_hz_update = 0;
static uint32_t sys_ms_update = 0;
uint32_t hz_conv = 0;
/** count sys hz */
hz_conv = HZ_COUNT_CONV(precision, BOARD_SYS_TIMER_HZ);
sys_hz_update++;
if (sys_hz_update >= hz_conv) {
sys_hz_update = 0;
gl_sys_hz_cnt++;
}
/** count ms */
hz_conv = HZ_COUNT_CONV(precision, BOARD_SYS_TIMER_MS_HZ);
sys_ms_update++;
if (sys_ms_update >= hz_conv) {
sys_ms_update = 0;
gl_ms_cnt++;
}
}
/**
* @brief Get current timer's counter value in ticks
* @retval Ticks count in 64 bit format
*/
uint64_t board_get_hwticks(void)
{
uint32_t sub_ticks;
uint64_t total_ticks;
timer_current(TIMER_0, &sub_ticks);
total_ticks = (uint64_t)GET_CUR_MS() * (BOARD_CPU_CLOCK / BOARD_SYS_TIMER_HZ);
total_ticks += (uint64_t)sub_ticks;
return total_ticks;
}
/**
* @brief Get current passed us since timer init
* @retval us Count in 64 bit format
*/
uint64_t board_get_cur_us(void)
{
uint32_t sub_us;
uint64_t total_us;
timer_current(TIMER_0, &sub_us);
sub_us = ((uint64_t)sub_us * 1000000) / BOARD_CPU_CLOCK;
total_us = ((uint64_t)GET_CUR_MS()) * 1000 + (uint64_t)sub_us;
return total_us;
}
/**
* @brief Get current passed ms since timer init
* @retval ms Count in 32 bit format
*/
uint32_t board_get_cur_ms(void)
{
return gl_ms_cnt;
}
/**
* @brief Get board timer counter in timer interrupt
* @retval Count in 64 bit format
*/
uint64_t board_get_cur_syshz(void)
{
return gl_sys_hz_cnt;
}
/**
* @brief Function for delaying execution for number of milliseconds
* @details
* This function needs a 1-MS timer interrupt to work.
* For bare-metal, it is implemented in this file.
* @param ms Delay in milliseconds
*/
void board_delay_ms(uint32_t ms)
{
uint64_t start_us, us_delayed;
us_delayed = ((uint64_t)ms * 1000);
start_us = board_get_cur_us();
while ((board_get_cur_us() - start_us) < us_delayed) {
;
}
}

View File

@@ -1,106 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
*
* @file
* @ingroup BOARD_COMMON
* @brief Common board definitions used with all boards
* @details
* - This header file will contain board related settings for different boards.
* - Each board configurations are put in its own header file, like emsk/emsk.h
* - If you want to change the configuration, you need to go to related header file, e.g.
* if you want to change EMSK board settings, you need to go to emsk/emsk.h
*/
/**
* @addtogroup BOARD_COMMON
* @{
*/
#ifndef H_BOARD
#define H_BOARD
/**
* @todo add comments and documents to describe the macros
* @note the following macros must use the same name, because
* they are used by middleware and other applications
*/
/** here is a sample of EMSK board resource definitions */
#ifdef BOARD_EMSK
#include "emsk/emsk.h"
#endif /* BOARD_EMSK */
/** you can add your board configuration as BOARD_EMSK defined up */
/** nsim related definition */
#ifdef BOARD_NSIM
#include "nsim.h"
#endif /* BOARD_NSIM */
#ifdef BOARD_AXS
#include "axs/axs.h"
#endif /* BOARD_AXS */
#ifdef BOARD_HSDK
#include "hsdk/hsdk.h"
#endif /* BOARD_HSDK */
#ifdef BOARD_IOTDK
#include "iotdk/iotdk.h"
#endif /* BOARD_IOTDK */
#ifdef BOARD_EMSDP
#include "emsdp/emsdp.h"
#endif /* BOARD_EMDK */
#ifdef __cplusplus
extern "C" {
#endif
extern void board_init(void);
extern void board_timer_update(uint32_t precision);
extern void board_delay_ms(uint32_t ms);
extern uint64_t board_get_hwticks(void);
extern uint64_t board_get_cur_us(void);
extern uint64_t board_get_cur_syshz(void);
extern uint32_t board_get_cur_ms(void);
extern void platform_main(void);
extern void board_main(void);
#ifdef __cplusplus
}
#endif
#define GET_CUR_SYSHZ() bord_get_cur_syshz()
#define GET_CUR_MS() board_get_cur_ms()
#define GET_CUR_US() board_get_cur_us()
#define GET_CUR_HWTICKS() board_get_hwticks()
#endif /* H_BOARD */
/** @} end of group BOARD_COMMON */

View File

@@ -1,539 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "device/designware/dw_gpio.h"
/** check expressions used in DesignWare GPIO driver implementation */
#define DW_GPIO_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
/** valid check of uart info object */
#define VALID_CHK_GPIO_INFO_OBJECT(gpioinfo_obj_ptr) { \
DW_GPIO_CHECK_EXP((gpioinfo_obj_ptr) != NULL, E_OBJ); \
DW_GPIO_CHECK_EXP(((gpioinfo_obj_ptr)->gpio_ctrl) != NULL, E_OBJ); \
}
#endif
/**
* @defgroup DEVICE_DW_GPIO_STATIC DesignWare GPIO Driver Static Functions
* @ingroup DEVICE_DW_GPIO
* @brief Static or inline functions, variables for DesignWare GPIO handle GPIO operations,
* only used in this file.
* @{
*/
/**
* @fn uint32_t dw_gpio_read_ext(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_read_ext(DW_GPIO_PORT_PTR port)
{
return port->regs->EXT_PORTS[port->no];
}
/**
* @fn uint32_t dw_gpio_read_dir(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_read_dir(DW_GPIO_PORT_PTR port)
{
return port->regs->SWPORTS[port->no].DDR;
}
/**
* @fn uint32_t dw_gpio_read_dr(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_read_dr(DW_GPIO_PORT_PTR port)
{
return port->regs->SWPORTS[port->no].DR;
}
/**
* @fn uint32_t dw_gpio_read_mthd(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_read_mthd(DW_GPIO_PORT_PTR port)
{
return port->regs->INTEN;
}
/**
* @fn void dw_gpio_int_enable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_enable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->INTEN |= bit_mask;
}
/**
* @fn void dw_gpio_int_disable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_disable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->INTEN &= (~bit_mask);
}
/**
* @fn void dw_gpio_int_mask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_mask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->INTMASK |= bit_mask;
}
/**
* @fn void dw_gpio_int_unmask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_unmask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->INTMASK &= (~bit_mask);
}
/**
* @fn uint32_t dw_gpio_int_read_level(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_int_read_level(DW_GPIO_PORT_PTR port)
{
return port->regs->INTTYPE_LEVEL;
}
/**
* @fn uint32_t dw_gpio_int_read_polarity(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_int_read_polarity(DW_GPIO_PORT_PTR port)
{
return port->regs->INT_POLARITY;
}
/**
* @fn uint32_t dw_gpio_int_read_debounce(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_int_read_debounce(DW_GPIO_PORT_PTR port)
{
return port->regs->DEBOUNCE;
}
/**
* @fn uint32_t dw_gpio_int_read_status(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_int_read_status(DW_GPIO_PORT_PTR port)
{
return port->regs->INTSTATUS;
}
/**
* @fn void dw_gpio_int_clear(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_clear(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->PORTA_EOI = bit_mask;
}
static void dw_gpio_int_write_level(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_level)
{
uint32_t reg_val;
reg_val = port->regs->INTTYPE_LEVEL;
reg_val &= (~bit_mask);
bit_level &= bit_mask;
reg_val |= bit_level;
port->regs->INTTYPE_LEVEL = reg_val;
}
static void dw_gpio_int_write_polarity(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_polarity)
{
uint32_t reg_val;
reg_val = port->regs->INT_POLARITY;
reg_val &= (~bit_mask);
bit_polarity &= bit_mask;
reg_val |= bit_polarity;
port->regs->INT_POLARITY = reg_val;
}
static void dw_gpio_int_write_debounce(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_debounce)
{
uint32_t reg_val;
reg_val = port->regs->DEBOUNCE;
reg_val &= (~bit_mask);
bit_debounce &= bit_mask;
reg_val |= bit_debounce;
port->regs->DEBOUNCE = reg_val;
}
static void dw_gpio_set_int_cfg(DW_GPIO_PORT_PTR port, DEV_GPIO_INT_CFG *int_cfg)
{
dw_gpio_int_write_level(port, int_cfg->int_bit_mask, int_cfg->int_bit_type);
dw_gpio_int_write_polarity(port, int_cfg->int_bit_mask, int_cfg->int_bit_polarity);
dw_gpio_int_write_debounce(port, int_cfg->int_bit_mask, int_cfg->int_bit_debounce);
}
static void dw_gpio_get_int_cfg(DW_GPIO_PORT_PTR port, DEV_GPIO_INT_CFG *int_cfg)
{
int_cfg->int_bit_type = dw_gpio_int_read_level(port) & int_cfg->int_bit_mask;
int_cfg->int_bit_polarity = dw_gpio_int_read_polarity(port) & int_cfg->int_bit_mask;
int_cfg->int_bit_debounce = dw_gpio_int_read_debounce(port) & int_cfg->int_bit_mask;
}
static void dw_gpio_write_dr(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t val)
{
uint32_t temp_reg;
temp_reg = port->regs->SWPORTS[port->no].DR;
temp_reg &= ~bit_mask;
val &= bit_mask;
temp_reg |= val;
port->regs->SWPORTS[port->no].DR = temp_reg;
}
static void dw_gpio_toggle_dr(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
uint32_t temp_reg1, temp_reg2;
temp_reg1 = port->regs->SWPORTS[port->no].DR;
// save unmasked bits value
temp_reg2 = temp_reg1 & (~bit_mask);
// toggle masked bits value
temp_reg1 = (~temp_reg1) & bit_mask;
// combine both masked and unmasked bits
temp_reg1 |= temp_reg2;
port->regs->SWPORTS[port->no].DR = temp_reg1;
}
static void dw_gpio_write_dir(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t val)
{
uint32_t temp_reg;
temp_reg = port->regs->SWPORTS[port->no].DDR;
temp_reg &= ~bit_mask;
val &= bit_mask;
temp_reg |= val;
port->regs->SWPORTS[port->no].DDR = temp_reg;
}
static uint32_t dw_gpio_read_val(DW_GPIO_PORT_PTR port)
{
uint32_t val;
val = dw_gpio_read_ext(port) & (~dw_gpio_read_dir(port));
val |= dw_gpio_read_dr(port) & dw_gpio_read_dir(port);
return val;
}
/** @} end of group DEVICE_DW_GPIO_STATIC */
/* interface for DEV_GPIO */
/** Open designware gpio device with specified io direction configuration */
int32_t dw_gpio_open(DEV_GPIO *gpio_obj, uint32_t dir)
{
int32_t ercd = E_OK;
DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
/* START ERROR CHECK */
VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
port_info_ptr->opn_cnt++;
if (port_info_ptr->opn_cnt > 1) { /* opened before */
if (dir == port_info_ptr->direction) { /* direction is the same */
return E_OK;
} else { /* open with different direction */
return E_OPNED;
}
}
dw_gpio_write_dir(port, port->valid_bit_mask, dir);
if (port->no == DW_GPIO_PORT_A) {
dw_gpio_int_clear(port, DW_GPIO_MASK_ALL);
dw_gpio_int_disable(port, DW_GPIO_MASK_ALL);
dw_gpio_int_unmask(port, DW_GPIO_MASK_ALL);
/* install gpio interrupt handler */
if (port->intno != DW_GPIO_INVALID_INTNO) { // Handle Bit ISR 1-1 map to vector table
int_handler_install(port->intno, port->int_handler);
int_disable(port->intno);
}
/** Set int type, int polarity and debounce configuration to default settings of device gpio */
dw_gpio_set_int_cfg(port, (DEV_GPIO_INT_CFG *)(&gpio_int_cfg_default));
port_info_ptr->method = dw_gpio_read_mthd(port);
} else {
port_info_ptr->method = DEV_GPIO_BITS_MTHD_DEFAULT;
}
dw_gpio_write_dr(port, port->valid_bit_mask, 0);
port_info_ptr->direction = dir;
port_info_ptr->extra = NULL;
port_info_ptr->bitofs = 0;
error_exit:
return ercd;
}
/** Close designware gpio device */
int32_t dw_gpio_close(DEV_GPIO *gpio_obj)
{
int32_t ercd = E_OK;
DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
/* START ERROR CHECK */
VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_OK);
port_info_ptr->opn_cnt--;
port_info_ptr->bitofs = 0;
if (port_info_ptr->opn_cnt == 0) {
dw_gpio_write_dr(port, port->valid_bit_mask, 0);
dw_gpio_write_dir(port, port->valid_bit_mask, 0);
if (port->no == DW_GPIO_PORT_A) {
dw_gpio_int_clear(port, DW_GPIO_MASK_ALL);
dw_gpio_int_disable(port, DW_GPIO_MASK_ALL);
if (port->intno != DW_GPIO_INVALID_INTNO) {
int_disable(port->intno);
}
}
port_info_ptr->direction = 0;
port_info_ptr->method = 0;
port_info_ptr->extra = NULL;
} else {
ercd = E_OPNED;
}
error_exit:
return ercd;
}
/** Read designware gpio device value */
int32_t dw_gpio_read(DEV_GPIO *gpio_obj, uint32_t *val, uint32_t mask)
{
int32_t ercd = E_OK;
DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
/* START ERROR CHECK */
VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
DW_GPIO_CHECK_EXP(val != NULL, E_PAR);
// *val = dw_gpio_read_ext(port) & mask;
*val = dw_gpio_read_val(port) & mask;
error_exit:
return ercd;
}
/** Write designware gpio device value */
int32_t dw_gpio_write(DEV_GPIO *gpio_obj, uint32_t val, uint32_t mask)
{
int32_t ercd = E_OK;
DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
/* START ERROR CHECK */
VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
dw_gpio_write_dr(port, mask, val);
error_exit:
return ercd;
}
/** Control designware gpio device */
int32_t dw_gpio_control(DEV_GPIO *gpio_obj, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
/* START ERROR CHECK */
VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
uint32_t val32; /** to receive unsigned int value */
if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_INPUT) {
val32 = (uint32_t)param;
dw_gpio_write_dir(port, val32, DW_GPIO_INPUT_ALL);
port_info_ptr->direction = dw_gpio_read_dir(port);
} else if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_OUTPUT) {
val32 = (uint32_t)param;
dw_gpio_write_dir(port, val32, DW_GPIO_OUTPUT_ALL);
port_info_ptr->direction = dw_gpio_read_dir(port);
} else if (ctrl_cmd == GPIO_CMD_GET_BIT_DIR) {
DW_GPIO_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
port_info_ptr->direction = dw_gpio_read_dir(port);
*((int32_t *)param) = port_info_ptr->direction;
} else if (ctrl_cmd == GPIO_CMD_TOGGLE_BITS) {
val32 = (uint32_t)param;
// Only mask the output bits
val32 &= port_info_ptr->direction;
dw_gpio_toggle_dr(port, val32);
} else {
DW_GPIO_CHECK_EXP(port->no == DW_GPIO_PORT_A, E_NOSPT);
/* output pin cannot be used as interrupt */
DEV_GPIO_INT_CFG *gpio_int_cfg;
DEV_GPIO_BIT_ISR *port_bit_isr;
switch (ctrl_cmd) {
case GPIO_CMD_SET_BIT_INT_CFG:
DW_GPIO_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
gpio_int_cfg = (DEV_GPIO_INT_CFG *)param;
dw_gpio_set_int_cfg(port, gpio_int_cfg);
break;
case GPIO_CMD_GET_BIT_INT_CFG:
DW_GPIO_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
gpio_int_cfg = (DEV_GPIO_INT_CFG *)param;
/** read configuration, each bit stands for different configuration */
dw_gpio_get_int_cfg(port, gpio_int_cfg);
break;
case GPIO_CMD_SET_BIT_ISR:
DW_GPIO_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
port_bit_isr = (DEV_GPIO_BIT_ISR *)param;
if (port_bit_isr->int_bit_ofs < port->gpio_bit_isr->int_bit_max_cnt) {
port->gpio_bit_isr->int_bit_handler_ptr[port_bit_isr->int_bit_ofs] = port_bit_isr->int_bit_handler;
} else {
ercd = E_PAR;
}
break;
case GPIO_CMD_GET_BIT_ISR:
DW_GPIO_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
port_bit_isr = (DEV_GPIO_BIT_ISR *)param;
if (port_bit_isr->int_bit_ofs < port->gpio_bit_isr->int_bit_max_cnt) {
port_bit_isr->int_bit_handler = port->gpio_bit_isr->int_bit_handler_ptr[port_bit_isr->int_bit_ofs];
} else {
ercd = E_PAR;
}
break;
case GPIO_CMD_ENA_BIT_INT:
val32 = (uint32_t)param;
dw_gpio_int_enable(port, val32);
port_info_ptr->method = dw_gpio_read_mthd(port);
if (port_info_ptr->method) {
if (port->intno != DW_GPIO_INVALID_INTNO) {
int_enable(port->intno);
}
}
break;
case GPIO_CMD_DIS_BIT_INT:
val32 = (uint32_t)param;
dw_gpio_int_disable(port, val32);
port_info_ptr->method = dw_gpio_read_mthd(port);
if (port_info_ptr->method == 0) {
if (port->intno != DW_GPIO_INVALID_INTNO) {
int_disable(port->intno);
}
}
break;
case GPIO_CMD_GET_BIT_MTHD:
DW_GPIO_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
port_info_ptr->method = dw_gpio_read_mthd(port);
*((int32_t *)param) = port_info_ptr->method;
break;
default:
ercd = E_NOSPT;
break;
}
}
error_exit:
return ercd;
}
/** designware gpio interrupt process */
int32_t dw_gpio_isr_handler(DEV_GPIO *gpio_obj, void *ptr)
{
int32_t ercd = E_OK;
DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
/* START ERROR CHECK */
VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
DW_GPIO_CHECK_EXP(port->no == DW_GPIO_PORT_A, E_NOSPT);
uint32_t i, gpio_bit_isr_state;
uint32_t max_int_bit_count = 0;
/** read interrupt status */
gpio_bit_isr_state = dw_gpio_int_read_status(port);
if (port->gpio_bit_isr) {
max_int_bit_count = (port->gpio_bit_isr->int_bit_max_cnt);
} else {
/* this code cannot never be reached */
/* coverity[dead_error_line] */
dw_gpio_int_clear(port, gpio_bit_isr_state);
}
for (i = 0; i < max_int_bit_count; i++) {
if (gpio_bit_isr_state & (1 << i)) {
/* this bit interrupt enabled */
port_info_ptr->bitofs = i;
if (port->gpio_bit_isr->int_bit_handler_ptr[i]) {
port->gpio_bit_isr->int_bit_handler_ptr[i](gpio_obj);
}
dw_gpio_int_clear(port, (1 << i)); /** clear this bit interrupt */
}
}
error_exit:
return ercd;
}

View File

@@ -1,400 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "device/designware/dw_pwm_timer.h"
/** check expressions used in DesignWare PWM_TIMER driver implementation */
#define DW_PWM_TIMER_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
/** valid check of uart info object */
#define VALID_CHK_PWM_TIMER_INFO_OBJECT(pwm_timerinfo_obj_ptr) { \
DW_PWM_TIMER_CHECK_EXP((pwm_timerinfo_obj_ptr) != NULL, E_OBJ); \
DW_PWM_TIMER_CHECK_EXP(((pwm_timerinfo_obj_ptr)->pwm_timer_ctrl) != NULL, E_OBJ); \
}
#endif
/**
* @fn uint32_t dw_pwm_timer_int_read_status(DW_PWM_TIMER_CTRL_PTR port)
*/
Inline uint32_t dw_pwm_timer_int_read_status(DW_PWM_TIMER_CTRL_PTR port)
{
return port->regs->PWM_TIMERS_INT_STATUS;
}
/**
* @fn void dw_pwm_timer_timer_enable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
*/
Inline void dw_pwm_timer_timer_enable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
port->regs->CTRL[ch].CONTROL_REG |= 0x03;
}
/**
* @fn void dw_pwm_timer_timer_disable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
*/
Inline void dw_pwm_timer_timer_disable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
port->regs->CTRL[ch].CONTROL_REG &= (~0x03);
}
/**
* @fn void dw_pwm_timer_pwm_enable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
*/
Inline void dw_pwm_timer_pwm_enable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
port->regs->CTRL[ch].CONTROL_REG |= 0x08;
}
/**
* @fn void dw_pwm_timer_pwm_disable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
*/
Inline void dw_pwm_timer_pwm_disable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
port->regs->CTRL[ch].CONTROL_REG &= (~0x08);
}
/**
* @fn void dw_pwm_timer_count_set(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch, uint16_t val)
*/
Inline void dw_pwm_timer_count_set(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch, uint16_t val)
{
port->regs->CTRL[ch].LOAD_COUNT = val;
}
/**
* @fn uint16_t dw_pwm_timer_count_get(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch)
*/
Inline uint16_t dw_pwm_timer_count_get(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch)
{
return port->regs->CTRL[ch].LOAD_COUNT;
}
/**
* @fn void dw_pwm_timer_count2_set(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch, uint16_t val)
*/
Inline void dw_pwm_timer_count2_set(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch, uint16_t val)
{
port->regs->LOAD_COUNT2[ch] = val;
}
/**
* @fn uint16_t dw_pwm_timer_count2_get(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch)
*/
Inline uint16_t dw_pwm_timer_count2_get(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch)
{
return port->regs->LOAD_COUNT2[ch];
}
static void dw_pwm_timer_int_clear_all(DW_PWM_TIMER_CTRL_PTR port)
{
int32_t reg_val;
reg_val = port->regs->PWM_TIMERS_EOI;
}
static void dw_pwm_timer_int_clear(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
int32_t reg_val;
reg_val = port->regs->CTRL[ch].EOI;
}
/* interface for DEV_PWM_TIMER */
/** Open designware pwm_timer device */
int32_t dw_pwm_timer_open(DEV_PWM_TIMER *pwm_timer_obj)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
port_info_ptr->opn_cnt++;
if (port_info_ptr->opn_cnt > 1) { /* opened before */
return E_OPNED;
}
if (port->intno != DW_PWM_TIMER_INVALID_INTNO) {
for (uint8_t i = 0; i < port->ch_num; i++) {
dw_pwm_timer_timer_disable(port, i);
dw_pwm_timer_pwm_disable(port, i);
int_disable(port->intno + i);
int_handler_install(port->intno + i, port->int_handler);
}
}
error_exit:
return ercd;
}
/** Close designware pwm_timer device */
int32_t dw_pwm_timer_close(DEV_PWM_TIMER *pwm_timer_obj)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
DW_PWM_TIMER_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_OK);
port_info_ptr->opn_cnt--;
if (port_info_ptr->opn_cnt == 0) {
if (port->intno != DW_PWM_TIMER_INVALID_INTNO) {
for (uint8_t i = 0; i < port->ch_num; i++) {
dw_pwm_timer_timer_disable(port, i);
dw_pwm_timer_pwm_disable(port, i);
int_disable(port->intno + i);
}
}
} else {
ercd = E_OPNED;
}
error_exit:
return ercd;
}
/** Read designware pwm_timer device value */
int32_t dw_pwm_timer_read(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t *mode, uint32_t *freq, uint32_t *dc)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
DW_PWM_TIMER_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
DW_PWM_TIMER_CHECK_EXP((ch >= 0) && (ch < port->ch_num), E_PAR);
int32_t count_low = dw_pwm_timer_count_get(port, ch);
int32_t count_high = dw_pwm_timer_count2_get(port, ch);
*mode = port->mode[ch];
if (*mode == DEV_PWM_TIMER_MODE_TIMER) {
*dc = 100;
if (count_low != 0) {
*freq = port->clock / (count_low * 2);
} else {
*freq = 0;
}
} else if (*mode == DEV_PWM_TIMER_MODE_PWM) {
if (count_low == 0 && count_high == 0) {
*dc = 0;
*freq = 0;
} else {
*dc = (count_high * 100) / (count_high + count_low);
*freq = port->clock / (count_high + count_low);
}
} else {
*dc = 0;
*freq = 0;
}
error_exit:
return ercd;
}
/** Write designware pwm_timer device value */
int32_t dw_pwm_timer_write(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t mode, uint32_t freq, uint32_t dc)
{
int32_t ercd = E_OK;
int32_t count, count_high;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
DW_PWM_TIMER_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
DW_PWM_TIMER_CHECK_EXP((ch >= 0) && (ch < port->ch_num), E_PAR);
DW_PWM_TIMER_CHECK_EXP((dc >= 0) && (dc <= 100), E_PAR);
if (mode == DEV_PWM_TIMER_MODE_TIMER) {
DW_PWM_TIMER_CHECK_EXP(freq > 0, E_PAR);
port->mode[ch] = mode;
count = port->clock / freq;
dw_pwm_timer_count_set(port, ch, count / 2);
dw_pwm_timer_count2_set(port, ch, 0);
dw_pwm_timer_timer_enable(port, ch);
dw_pwm_timer_pwm_disable(port, ch);
int_enable(port->intno + ch);
} else if (mode == DEV_PWM_TIMER_MODE_PWM) {
DW_PWM_TIMER_CHECK_EXP(freq > 0, E_PAR);
port->mode[ch] = mode;
count = port->clock / freq;
count_high = (count * dc) / 100;
dw_pwm_timer_count_set(port, ch, count - count_high);
dw_pwm_timer_count2_set(port, ch, count_high);
dw_pwm_timer_timer_enable(port, ch);
dw_pwm_timer_pwm_enable(port, ch);
int_disable(port->intno + ch);
} else if (mode == DEV_PWM_TIMER_MODE_CLOSE) {
port->mode[ch] = mode;
dw_pwm_timer_count_set(port, ch, 0);
dw_pwm_timer_count2_set(port, ch, 0);
dw_pwm_timer_timer_disable(port, ch);
dw_pwm_timer_pwm_disable(port, ch);
int_disable(port->intno + ch);
}
error_exit:
return ercd;
}
/** Control designware pwm_timer device */
int32_t dw_pwm_timer_control(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t ctrl_cmd, void *par)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
DW_PWM_TIMER_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
DW_PWM_TIMER_CHECK_EXP((ch >= 0) && (ch < port->ch_num), E_PAR);
DEV_PWM_TIMER_CFG *cfg_ptr;
switch (ctrl_cmd) {
case PWM_TIMER_CMD_SET_CFG:
cfg_ptr = (DEV_PWM_TIMER_CFG *) par;
dw_pwm_timer_count_set(port, ch, cfg_ptr->count_low);
dw_pwm_timer_count2_set(port, ch, cfg_ptr->count_high);
if (cfg_ptr->isr_hander != NULL) {
port->ch_isr->int_ch_handler_ptr[ch] = cfg_ptr->isr_hander;
}
if (cfg_ptr->mode == DEV_PWM_TIMER_MODE_TIMER) {
port->mode[ch] = cfg_ptr->mode;
dw_pwm_timer_timer_enable(port, ch);
int_enable(port->intno + ch);
} else if (cfg_ptr->mode == DEV_PWM_TIMER_MODE_PWM) {
port->mode[ch] = cfg_ptr->mode;
dw_pwm_timer_timer_enable(port, ch);
dw_pwm_timer_pwm_enable(port, ch);
} else if (cfg_ptr->mode == DEV_PWM_TIMER_MODE_CLOSE) {
port->mode[ch] = cfg_ptr->mode;
dw_pwm_timer_timer_disable(port, ch);
dw_pwm_timer_pwm_disable(port, ch);
}
break;
case PWM_TIMER_CMD_GET_CFG:
cfg_ptr = (DEV_PWM_TIMER_CFG *) par;
cfg_ptr->count_low = dw_pwm_timer_count_get(port, ch);
cfg_ptr->count_high = dw_pwm_timer_count2_get(port, ch);
if (cfg_ptr->isr_hander != NULL) {
cfg_ptr->isr_hander = port->ch_isr->int_ch_handler_ptr[ch];
}
cfg_ptr->mode = port->mode[ch];
break;
case PWM_TIMER_CMD_DIS_CH:
dw_pwm_timer_timer_disable(port, ch);
break;
case PWM_TIMER_CMD_ENA_CH:
dw_pwm_timer_timer_enable(port, ch);
break;
case PWM_TIMER_CMD_DIS_ISR:
int_disable(port->intno + ch);
break;
case PWM_TIMER_CMD_ENA_ISR:
int_enable(port->intno + ch);
break;
case PWM_TIMER_CMD_SET_ISR:
DW_PWM_TIMER_CHECK_EXP((par != NULL) && CHECK_ALIGN_4BYTES(par), E_PAR);
port->ch_isr->int_ch_handler_ptr[ch] = (DEV_PWM_TIMER_HANDLER)par;
break;
case PWM_TIMER_CMD_GET_ISR:
DW_PWM_TIMER_CHECK_EXP((par != NULL) && CHECK_ALIGN_4BYTES(par), E_PAR);
par = (void *)(port->ch_isr->int_ch_handler_ptr[ch]);
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
/** designware pwm_timer interrupt process */
int32_t dw_pwm_timer_isr_handler(DEV_PWM_TIMER *pwm_timer_obj, void *ptr)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
uint32_t i, pwm_timer_bit_isr_state;
uint32_t max_int_bit_count = 0;
/** read interrupt status */
pwm_timer_bit_isr_state = dw_pwm_timer_int_read_status(port);
if (port->ch_isr) {
max_int_bit_count = (port->ch_isr->int_ch_max_cnt);
} else {
dw_pwm_timer_int_clear_all(port);
}
for (i = 0; i < max_int_bit_count; i++) {
if (pwm_timer_bit_isr_state & (1 << i)) {
/* this bit interrupt enabled */
if (port->ch_isr->int_ch_handler_ptr[i]) {
port->ch_isr->int_ch_handler_ptr[i](pwm_timer_obj);
}
dw_pwm_timer_int_clear(port, i); /** clear this bit interrupt */
}
}
error_exit:
return ercd;
}

View File

@@ -1,594 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "board.h"
#include "device/designware/dw_sdio_hal.h"
#include "device/designware/dw_sdio.h"
#include "embARC_debug.h"
#define min(a, b) (((a) < (b)) ? (a) : (b))
/**
* @fn void dw_sdio_enable_card_threshold(DW_SDIO_CTRL_PTR sdio, uint32_t threshold)
*/
Inline void dw_sdio_enable_card_threshold(DW_SDIO_CTRL_PTR sdio, uint32_t threshold)
{
/* according to datasheet, write threshold is only applicable for HS400 mode */
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_CARD_THR_CTRL);
reg |= 0x1;
dw_sdio_reg_write(sdio, DWSDIO_REG_CARD_THR_CTRL, reg);
}
/**
* @fn void dw_sdio_block_size_set(DW_SDIO_CTRL_PTR sdio, uint32_t bytes, uint32_t blksz)
*/
Inline void dw_sdio_block_size_set(DW_SDIO_CTRL_PTR sdio, uint32_t bytes, uint32_t blksz)
{
dw_sdio_reg_write(sdio, DWSDIO_REG_BYTCNT, bytes);
dw_sdio_reg_write(sdio, DWSDIO_REG_BLKSIZ, blksz);
}
/**
* @fn void dw_sdio_fifo_read_poll(DW_SDIO_CTRL_PTR sdio, uint32_t *buf, uint32_t size)
*/
Inline void dw_sdio_fifo_read_poll(DW_SDIO_CTRL_PTR sdio, uint32_t *buf, uint32_t size)
{
uint32_t len;
uint32_t i;
while (size) {
do {
len = dw_sdio_reg_read(sdio, DWSDIO_REG_STATUS);
} while (len & DWSDIO_STATUS_FIFO_EMPTY);
len = (len & DWSDIO_STATUS_MASK_FIFO) >> DWSDIO_STATUS_BIT_FIFO;
len = min(size, len);
for (i = 0; i < len; i++) {
*buf++ = dw_sdio_reg_read(sdio, DWSDIO_REG_DATA);
}
size = size > len ? (size - len) : 0;
}
}
/**
* @fn void dw_sdio_clk_enable(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_clk_enable(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_CLKENA);
reg |= (1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_CLKENA, reg);
}
/**
* @fn dw_sdio_clk_disable(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_clk_disable(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_CLKENA);
reg &= ~(1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_CLKENA, reg);
}
/**
* @fn void dw_sdio_fifo_write_poll(DW_SDIO_CTRL_PTR sdio, uint32_t *buf, uint32_t size)
*/
Inline void dw_sdio_fifo_write_poll(DW_SDIO_CTRL_PTR sdio, uint32_t *buf, uint32_t size)
{
uint32_t len;
uint32_t i;
uint32_t fifo_depth = sdio->fifo_depth;
while (size) {
do {
len = dw_sdio_reg_read(sdio, DWSDIO_REG_STATUS);
} while (len & DWSDIO_STATUS_FIFO_FULL);
len = fifo_depth - ((len & DWSDIO_STATUS_MASK_FIFO) >> DWSDIO_STATUS_BIT_FIFO);
len = min(size, len);
for (i = 0; i < len; i++) {
dw_sdio_reg_write(sdio, DWSDIO_REG_DATA, *buf++);
}
size = size > len ? (size - len) : 0;
}
}
/**
* @fn void dw_sdio_power_on(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_power_on(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
dw_sdio_reg_write(sdio, DWSDIO_REG_PWREN, (1 << card_number));
}
/**
* @fn void dw_sdio_power_off(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_power_off(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
uint32_t reg = dw_sdio_reg_read(sdio, DWSDIO_REG_PWREN);
reg &= ~(1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_PWREN, reg);
}
/**
* @fn void dw_sdio_reset(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_reset(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_RST_N);
reg &= ~(1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_RST_N, reg);
reg |= (1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_RST_N, reg);
}
/**
* @fn void dw_sdio_bus_type_set(DW_SDIO_CTRL_PTR sdio, uint32_t card_number, uint32_t width)
*/
Inline void dw_sdio_bus_type_set(DW_SDIO_CTRL_PTR sdio, uint32_t card_number, uint32_t width)
{
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_CTYPE);
reg &= ~((1 << card_number) | (1 << (card_number + 16)));
switch (width) {
case 1: break;
case 4: reg |= (1 << card_number); break;
case 8: reg |= (1 << (card_number + 16)); break;
default: break;
}
dw_sdio_reg_write(sdio, DWSDIO_REG_CTYPE, reg);
}
/**
* @fn void dw_sdio_ref_clk_set(DW_SDIO_CTRL_PTR sdio, uint32_t ref_clk)
*/
Inline void dw_sdio_ref_clk_set(DW_SDIO_CTRL_PTR sdio, uint32_t ref_clk)
{
/* 0: 25 Mhz, 1: 50 Mhz, 2: 100 Mhz */
uint32_t reg;
if (ref_clk == 50000000) {
ref_clk = 1;
} else if (ref_clk == 100000000) {
ref_clk = 2;
} else {
ref_clk = 0;
}
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_UHS_REG_EXT);
reg &= ~(DWSDIO_UHS_REG_EXT_MASK_REFCLK);
reg |= (ref_clk << DWSDIO_UHS_REG_EXT_BIT_REFCLK);
dw_sdio_reg_write(sdio, DWSDIO_REG_UHS_REG_EXT, reg);
}
static int32_t dw_sdio_bus_freq_set(DW_SDIO_CTRL_PTR sdio, uint32_t card_number, uint32_t freq)
{
uint32_t clk;
uint32_t div;
uint32_t status;
int32_t timeout = 10000;
clk = sdio->ref_clk;
if (freq == clk) {
div = 0;
} else {
div = DIV_ROUND_UP(clk, 2 * freq);
}
dw_sdio_clk_disable(sdio, card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_CLKSRC, 0);
dw_sdio_reg_write(sdio, DWSDIO_REG_CLKDIV, div);
dw_sdio_reg_write(sdio, DWSDIO_REG_CMD, DWSDIO_CMD_PRV_DAT_WAIT |
DWSDIO_CMD_UPD_CLK | DWSDIO_CMD_START | DWSDIO_CMD_USE_HOLD_REG);
do {
status = dw_sdio_reg_read(sdio, DWSDIO_REG_CMD);
if (timeout-- < 0) {
DBG("%s: Timeout!\n", __func__);
return E_TMOUT;
}
} while (status & DWSDIO_CMD_START);
dw_sdio_clk_enable(sdio, card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_CMD, DWSDIO_CMD_PRV_DAT_WAIT |
DWSDIO_CMD_UPD_CLK | DWSDIO_CMD_START | DWSDIO_CMD_USE_HOLD_REG);
timeout = 10000;
do {
status = dw_sdio_reg_read(sdio, DWSDIO_REG_CMD);
if (timeout-- < 0) {
DBG("%s: Timeout!\n", __func__);
return E_TMOUT;
}
} while (status & DWSDIO_CMD_START);
return E_OK;
}
static int32_t dw_sdio_reset_wait(DW_SDIO_CTRL_PTR sdio, uint32_t reset_val)
{
uint32_t try = 1000;
uint32_t ctrl;
dw_sdio_reg_write(sdio, DWSDIO_REG_CTRL, reset_val);
while (try--) {
ctrl = dw_sdio_reg_read(sdio, DWSDIO_REG_CTRL);
if (!(ctrl & DWSDIO_CTRL_RESET_ALL)) {
return E_SYS;
}
}
return E_OK;
}
static int32_t dw_sdio_cmd_set(DW_SDIO_CTRL_PTR sdio, SDIO_CMD_PTR cmd, SDIO_DATA_PTR data)
{
uint32_t reg = 0;
dw_sdio_reg_write(sdio, DWSDIO_REG_CMDARG, cmd->arg);
if (data) {
reg |= DWSDIO_CMD_DATA_EXP;
if (data->flags & SDIO_DATA_WRITE) {
reg |= DWSDIO_CMD_RW;
}
}
if ((cmd->resp_type & SDIO_RSP_136) && (cmd->resp_type & SDIO_RSP_BUSY)) {
return -1;
}
/* to fix */
if (cmd->cmdidx == 12) {
reg |= DWSDIO_CMD_ABORT_STOP;
} else {
reg |= DWSDIO_CMD_PRV_DAT_WAIT;
}
if (cmd->resp_type & SDIO_RSP_PRESENT) {
reg |= DWSDIO_CMD_RESP_EXP;
if (cmd->resp_type & SDIO_RSP_136) {
reg |= DWSDIO_CMD_RESP_LENGTH;
}
}
if (cmd->resp_type & SDIO_RSP_CRC) {
reg |= DWSDIO_CMD_CHECK_CRC;
}
reg |= (cmd->cmdidx | (cmd->card << DWSDIO_CMD_BIT_CARD_NO) | DWSDIO_CMD_START
| DWSDIO_CMD_USE_HOLD_REG);
DBG("Sending CMD%d to card %d \r\n", cmd->cmdidx, cmd->card);
dw_sdio_reg_write(sdio, DWSDIO_REG_CMD, reg);
return 0;
}
static int32_t dw_sdio_data_transfer_poll(DW_SDIO_CTRL_PTR sdio, SDIO_DATA_PTR data)
{
uint32_t size;
uint32_t status;
uint32_t timeout = 1000;
uint32_t start = GET_CUR_MS();
size = data->blksz * data->blkcnt / 4;
for (;;) {
status = dw_sdio_reg_read(sdio, DWSDIO_REG_RINTSTS);
if (status & (DWSDIO_INT_DATA_ERR | DWSDIO_INT_DATA_TMO)) {
DBG("%s:, data transfer error!\r\n", __func__);
return E_SYS;
}
if (status & DWSDIO_INT_DTO) {
return E_OK;
}
if (data->flags == SDIO_DATA_READ && (status & DWSDIO_INT_RXDR) && size) {
dw_sdio_fifo_read_poll(sdio, (uint32_t *)data->in, size);
size = 0;
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, DWSDIO_INT_RXDR);
} else if (data->flags == SDIO_DATA_WRITE && (status & DWSDIO_INT_TXDR) && size) {
dw_sdio_fifo_write_poll(sdio, (uint32_t *)data->out, size);
size = 0;
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, DWSDIO_INT_TXDR);
}
if ((GET_CUR_MS() - start) > timeout) {
DBG("%s: timeout on data transfer\r\n", __func__);
return E_TMOUT;
}
}
}
void dw_sdio_isr(DEV_SDIO *sdio_obj, void *ptr)
{
uint32_t int_status;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
int_status = dw_sdio_reg_read(sdio, DWSDIO_REG_MINTSTS);
if (int_status & DWSDIO_INT_CAD) {
DBG("SDIO card detected\r\n");
}
if (int_status & DWSDIO_INT_RE) {
DBG("SDIO response error\r\n");
}
if (int_status & DWSDIO_INT_CD) {
DBG("SDIO cmd done\r\n");
}
if (int_status & DWSDIO_INT_TXDR) {
DBG("SDIO tx data request\r\n");
}
if (int_status & DWSDIO_INT_RXDR) {
DBG("SDIO rx data request\r\n");
}
/* clear interrupt */
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, int_status);
/* \todo dma based interrupt */
}
int32_t dw_sdio_cmd_poll(DEV_SDIO *sdio_obj, SDIO_CMD_PTR cmd, SDIO_DATA_PTR data)
{
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
uint32_t start = GET_CUR_MS();
uint32_t timeout = 500;
uint32_t retry = 100000;
uint32_t mask;
uint32_t i;
while (dw_sdio_reg_read(sdio, DWSDIO_REG_STATUS) & DWSDIO_STATUS_DATA_BUSY) {
if ((GET_CUR_MS() - start) > timeout) {
DBG("%s: timeout on data busy\r\n", __func__);
return E_TMOUT;
}
}
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, DWSDIO_INT_ALL);
if (data) {
dw_sdio_enable_card_threshold(sdio, 1);
dw_sdio_block_size_set(sdio, data->blksz * data->blkcnt, data->blksz);
dw_sdio_reset_wait(sdio, DWSDIO_CTRL_RESET_FIFO);
}
if (dw_sdio_cmd_set(sdio, cmd, data) < 0) {
return E_SYS;
}
for (i = 0; i < retry; i++) {
mask = dw_sdio_reg_read(sdio, DWSDIO_REG_RINTSTS);
if (mask & DWSDIO_INT_CD) {
if (!data) {
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, mask);
}
break;
}
}
if (i == retry) {
DBG("%s: Timeout.\n", __func__);
return E_TMOUT;
}
if (mask & DWSDIO_INT_RTO) {
/*
* Timeout here is not necessarily fatal. (e)MMC cards
* will splat here when they receive CMD55 as they do
* not support this command and that is exactly the way
* to tell them apart from SD cards. Thus, this output
* below shall be debug(). eMMC cards also do not favor
* CMD8, please keep that in mind.
*/
DBG("%s: Response Timeout:%x.\r\n", __func__, mask);
return E_TMOUT;
} else if (mask & DWSDIO_INT_RE) {
DBG("%s: Response Error:%x.\r\n", __func__, mask);
return E_SYS;
}
if (cmd->resp_type & SDIO_RSP_PRESENT) {
if (cmd->resp_type & SDIO_RSP_136) {
cmd->resp[0] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP3);
cmd->resp[1] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP2);
cmd->resp[2] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP1);
cmd->resp[3] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP0);
} else {
cmd->resp[0] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP0);
}
}
if (data) {
return dw_sdio_data_transfer_poll(sdio, data);
}
return E_OK;
}
int32_t dw_sdio_open(DEV_SDIO *sdio_obj, uint32_t card_number)
{
uint32_t fifo_depth;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
if (sdio_info_ptr->opn_cnt > 0) {
dw_sdio_power_on(sdio, card_number);
dw_sdio_reset(sdio, card_number);
dw_sdio_bus_freq_set(sdio, card_number, DWSDIO_ENUMERATION_FREQ);
sdio_info_ptr->opn_cnt++;
return E_OPNED;
}
sdio_info_ptr->opn_cnt++;
dw_sdio_reset_wait(sdio, DWSDIO_CTRL_RESET_ALL);
dw_sdio_ref_clk_set(sdio, sdio->ref_clk);
dw_sdio_power_on(sdio, card_number);
dw_sdio_reset(sdio, card_number);
dw_sdio_bus_type_set(sdio, card_number, 1);
dw_sdio_bus_freq_set(sdio, card_number, DWSDIO_ENUMERATION_FREQ);
if (sdio->fifo_depth == 0) {
fifo_depth = dw_sdio_reg_read(sdio, DWSDIO_REG_FIFOTH);
fifo_depth = ((fifo_depth & DWSDIO_FIFOTH_MASK_RX_WMARK) >>
DWSDIO_FIFOTH_BIT_RX_WMARK) + 1;
sdio->fifo_depth = fifo_depth;
}
fifo_depth = DWSDIO_FIFOTH_M_SIZE(0x2) | DWSDIO_FIFOTH_RX_WMASK(sdio->fifo_depth / 2 - 1) |
DWSDIO_FIFOTH_TX_WMASK(sdio->fifo_depth / 2);
dw_sdio_reg_write(sdio, DWSDIO_REG_FIFOTH, fifo_depth);
return E_OK;
}
int32_t dw_sdio_close(DEV_SDIO *sdio_obj, uint32_t card_number)
{
int32_t ret = E_OK;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
sdio_info_ptr->opn_cnt--;
dw_sdio_power_off(sdio, card_number);
if (sdio_info_ptr->opn_cnt == 0) {
dw_sdio_reset_wait(sdio, DWSDIO_CTRL_RESET_ALL);
} else {
ret = E_OPNED;
}
return ret;
}
int32_t dw_sdio_cd(DEV_SDIO *sdio_obj, uint32_t card_number)
{
uint32_t val;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
/* the card detect depends on the specific PCB lay out.
* Some use 1 (CD pin to VDD) to indicate card detect.
* Some use 0 (CD pin to GNU) to indicate card detect.
*/
#ifdef DWSDIO_CARD_DETECT_HIGH_LEVEL
val = dw_sdio_reg_read(sdio, DWSDIO_REG_CDETECT);
#else
val = ~dw_sdio_reg_read(sdio, DWSDIO_REG_CDETECT);
#endif
if ((val & (1 << card_number)) == (1 << card_number)) {
return 1; /* the specific card detected */
}
return 0;
}
int32_t dw_sdio_wp(DEV_SDIO *sdio_obj, uint32_t card_number)
{
uint32_t val;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
val = dw_sdio_reg_read(sdio, DWSDIO_REG_WRTPRT);
if ((val & (1 << card_number)) == (1 << card_number)) {
return 1; /* the specific card is write-protect */
}
return 0;
}
int32_t dw_sdio_control(DEV_SDIO *sdio_obj, SDIO_CTRL_CMD_PTR ctrl_cmd, void *param)
{
int32_t ret = E_OK;
uint32_t cmd, card;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
cmd = ctrl_cmd->cmd;
card = ctrl_cmd->card;
switch (cmd) {
case SDIO_CMD_SET_BUS_WIDTH:
dw_sdio_bus_type_set(sdio, card, (uint32_t)param);
break;
case SDIO_CMD_SET_BUS_FREQ:
dw_sdio_bus_freq_set(sdio, card, (uint32_t)param);
break;
/* \todo add more cmds */
default:
ret = E_PAR;
}
return ret;
}

View File

@@ -1,364 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "string.h"
#include "device/designware/dw_nist_trng.h"
#ifdef TRNG_VERSION_NIST
#define DBG_LESS
#include "embARC_debug.h"
#define DW_TRNG_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
/** valid check of trng info object */
#define VALID_CHK_TRNG_INFO_OBJECT(trnginfo_obj_ptr) { \
DW_TRNG_CHECK_EXP((trnginfo_obj_ptr) != NULL, E_OBJ); \
DW_TRNG_CHECK_EXP(((trnginfo_obj_ptr)->trng_ctrl) != NULL, E_OBJ); \
}
#endif
#define DW_TRNG_CMD_NOP (0x0)
#define DW_TRNG_CMD_GEN_NOISE (0x1)
#define DW_TRNG_CMD_GEN_NONCE (0x2)
#define DW_TRNG_CMD_CREATE_STATE (0x3)
#define DW_TRNG_CMD_RENEW_STATE (0x4)
#define DW_TRNG_CMD_REFRESH_ADDIN (0x5)
#define DW_TRNG_CMD_GEN_RANDOM (0x6)
#define DW_TRNG_CMD_ADVANCE_STATE (0x7)
#define DW_TRNG_CMD_RUN_KAT (0x8)
#define DW_TRNG_CMD_ZEROIZE (0xF)
/**
* @fn dw_trng_unmask_reg_interrupt(DW_TRNG_REG_PTR trng_reg, uint32_t mask)
* @brief Enable designware trng bit interrupt with mask
*/
Inline void dw_trng_unmask_reg_interrupt(DW_TRNG_REG_PTR trng_reg, uint32_t mask)
{
trng_reg->IE |= mask;
}
/**
* @fn void dw_trng_mask_reg_interrupt(DW_TRNG_REG_PTR trng_reg, uint32_t mask)
* @brief Disable designware trng bit interrupt with mask
*/
Inline void dw_trng_mask_reg_interrupt(DW_TRNG_REG_PTR trng_reg, uint32_t mask)
{
trng_reg->IE &= ~mask;
}
/**
* @fn void dw_trng_wait_till_idle(DW_TRNG_REG_PTR trng_reg)
*/
Inline void dw_trng_wait_till_idle(DW_TRNG_REG_PTR trng_reg)
{
while (trng_reg->stat.busy) {
;
}
}
static int32_t dw_trng_cmd(DEV_TRNG_INFO_PTR trng_info_ptr, uint32_t cmd)
{
int32_t ercd = E_OK;
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dw_trng_wait_till_idle(trng_reg_ptr);
switch (cmd) {
case DW_TRNG_CMD_NOP:
case DW_TRNG_CMD_GEN_NOISE:
case DW_TRNG_CMD_GEN_NONCE:
case DW_TRNG_CMD_CREATE_STATE:
case DW_TRNG_CMD_RENEW_STATE:
case DW_TRNG_CMD_REFRESH_ADDIN:
case DW_TRNG_CMD_GEN_RANDOM:
case DW_TRNG_CMD_ADVANCE_STATE:
case DW_TRNG_CMD_RUN_KAT:
case DW_TRNG_CMD_ZEROIZE:
trng_reg_ptr->CTRL |= cmd; break;
default:
ercd = E_PAR; break;
}
return ercd;
}
static void dw_trng_enable_sys_interrupt(DEV_TRNG_INFO_PTR trng_info_ptr)
{
DW_TRNG_CTRL_PTR trng_ctrl_ptr = (DW_TRNG_CTRL_PTR)(trng_info_ptr->trng_ctrl);
trng_ctrl_ptr->int_status |= DW_TRNG_GINT_ENABLE;
if (trng_ctrl_ptr->intno != DW_TRNG_INVALID_INTNO) {
int_handler_install(trng_ctrl_ptr->intno, trng_ctrl_ptr->dw_trng_int_handler);
int_enable(trng_ctrl_ptr->intno);
}
}
static void dw_trng_disable_sys_interrupt(DEV_TRNG_INFO_PTR trng_info_ptr)
{
DW_TRNG_CTRL_PTR trng_ctrl_ptr = (DW_TRNG_CTRL_PTR)(trng_info_ptr->trng_ctrl);
if (trng_ctrl_ptr->intno != DW_TRNG_INVALID_INTNO) {
int_disable(trng_ctrl_ptr->intno);
}
trng_ctrl_ptr->int_status = DW_TRNG_GINT_DISABLE;
}
static int32_t dw_trng_zeroize(DEV_TRNG_INFO_PTR trng_info_ptr)
{
int32_t ercd = E_OK;
// DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
// DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dw_trng_enable_sys_interrupt(trng_info_ptr);
ercd = dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_ZEROIZE);
return ercd;
}
static int32_t dw_trng_reseed(DEV_TRNG_INFO_PTR trng_info_ptr, uint32_t *nonce_buf)
{
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
if (nonce_buf != NULL) {// Nonce Reseed cmd, need to be run 2~3 time with new nonce depending on chosen security algorithm
uint8_t i;
volatile uint32_t *npa_data_ptr = &(trng_reg_ptr->NPA_DATA0);
dw_trng_wait_till_idle(trng_reg_ptr);
for (i = 0; i < 16; i++) {
npa_data_ptr[i] = nonce_buf[i];
}
dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_GEN_NONCE);
} else {// Random Reseed cmd
dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_GEN_NOISE);
}
return E_OK;
}
static void dw_trng_get_rand(DW_TRNG_REG_PTR trng_reg_ptr, uint32_t *data) // read from rand0~3
{
if (data != NULL) {
data[0] = trng_reg_ptr->RAND0;
data[1] = trng_reg_ptr->RAND1;
data[2] = trng_reg_ptr->RAND2;
data[3] = trng_reg_ptr->RAND3;
} else {
dbg_printf(DBG_LESS_INFO, "\r\n!DW_TRNG meet invalid memory error: LAST_CMD=0x%x\r\n", trng_reg_ptr->stat.last_cmd);
}
}
static void dw_iic_mst_int_read(DEV_TRNG_PTR trng_obj)
{
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
DEV_BUFFER *buf_ptr = &(trng_info_ptr->out_buf);
uint32_t *p_buf = (uint32_t *)buf_ptr->buf;
if (p_buf != NULL && buf_ptr->len >= buf_ptr->ofs + 4) {// check if buffer has enough space (needs 4 uint32_t per read)
dw_trng_get_rand(trng_reg_ptr, p_buf);
buf_ptr->ofs += 4;
}
if (trng_info_ptr->trng_cbs.out_cb) {
trng_info_ptr->trng_cbs.out_cb(trng_info_ptr);
}
}
int32_t dw_trng_open(DEV_TRNG_PTR trng_obj) // reseed with internal random seed generator
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
trng_reg_ptr->smode.secure_en = 1;// enable mission mode (secure)
/**
* trng interrupt related init
*/
dw_trng_disable_sys_interrupt(trng_info_ptr);
dw_trng_unmask_reg_interrupt(trng_reg_ptr, DW_TRNG_INT_ALL);
dw_trng_zeroize(trng_info_ptr);
// can do a KAT test here to ensure DRBGs are running correctly, need to zeroize afterwards
dw_trng_reseed(trng_info_ptr, NULL);
ercd = dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_CREATE_STATE);
error_exit:
return ercd;
}
int32_t dw_trng_close(DEV_TRNG_PTR trng_obj)
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dw_trng_mask_reg_interrupt(trng_reg_ptr, DW_TRNG_INT_ALL);
dw_trng_disable_sys_interrupt(trng_info_ptr);
// clean/release in buffer and out buffer
memset(&(trng_info_ptr->in_buf), 0, sizeof(DEV_BUFFER));
memset(&(trng_info_ptr->out_buf), 0, sizeof(DEV_BUFFER));
memset(&(trng_info_ptr->trng_cbs), 0, sizeof(DEV_TRNG_CBS));
// Do a zeroize for security
dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_ZEROIZE);
while (!trng_reg_ptr->istat.zeroized) {
; // wait until secure data cleaned
}
trng_reg_ptr->istat.zeroized = 1;
error_exit:
return E_OK;
}
int32_t dw_trng_control(DEV_TRNG_PTR trng_obj, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
// uint32_t val32; /** to receive unsigned int value */
switch (ctrl_cmd) {
case TRNG_CMD_SET_RAND_RESEED_AUTO:
ercd = dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_RENEW_STATE);
break;
case TRNG_CMD_SET_RAND_RESEED_NONCE:
ercd = dw_trng_reseed(trng_info_ptr, param);
break;
case TRNG_CMD_SET_IN_CB:
DW_TRNG_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
trng_info_ptr->trng_cbs.in_cb = param;
break;
case TRNG_CMD_SET_OUT_CB:
DW_TRNG_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
trng_info_ptr->trng_cbs.out_cb = param;
break;
case TRNG_CMD_SET_ERR_CB:
DW_TRNG_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
trng_info_ptr->trng_cbs.err_cb = param;
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
int32_t dw_trng_read(DEV_TRNG_PTR trng_obj, uint32_t *data_buf)
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_GEN_RANDOM);
if (data_buf != NULL) {
dw_trng_wait_till_idle(trng_reg_ptr);
dw_trng_get_rand(trng_reg_ptr, data_buf);
}
error_exit:
return ercd;
}
void dw_trng_isr(DEV_TRNG_PTR trng_obj, void *ptr)
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &(trng_obj->trng_info);
/* START ERROR CHECK */
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
/* END OF ERROR CHECK */
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dbg_printf(DBG_MORE_INFO, "dw_trng_isr ");
if (trng_reg_ptr->alarms.illegal_cmd_seq) {
dbg_printf(DBG_LESS_INFO, "\r\n!DW_TRNG meet illegal_cmd_seq error: LAST_CMD=0x%x\r\n", trng_reg_ptr->stat.last_cmd);
dw_trng_disable_sys_interrupt(trng_info_ptr);
trng_reg_ptr->alarms.illegal_cmd_seq = 1;// Write 1 to clear bit
if (trng_info_ptr->trng_cbs.err_cb) {
trng_info_ptr->trng_cbs.err_cb(trng_info_ptr);
}
}
if (trng_reg_ptr->istat.zeroized) { // zeroize operations can interrupt other operations
trng_reg_ptr->istat.zeroized = 1; // Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "zeroized");
}
if (trng_reg_ptr->istat.noise_rdy) {
trng_reg_ptr->istat.noise_rdy = 1;// Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "noise_rdy");
}
if (trng_reg_ptr->istat.done) {
trng_reg_ptr->istat.done = 1;// Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "done");
if (trng_reg_ptr->stat.last_cmd == DW_TRNG_CMD_GEN_RANDOM) {
dbg_printf(DBG_MORE_INFO, " --- GEN RANDOM done");
trng_info_ptr->byte_generated += 4;// TODO: once too many bytes have been generated, prompt to reseed
dw_iic_mst_int_read(trng_obj);
}
}
if (trng_reg_ptr->istat.alarms) {
trng_reg_ptr->istat.alarms = 1;// Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "alarms");
}
if (trng_reg_ptr->istat.kat_completed) {
trng_reg_ptr->istat.kat_completed = 1;// Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "kat_completed");
}
dbg_printf(DBG_MORE_INFO, " #\r\n");
error_exit:
return;
}
#endif /* TRNG_VERSION_NIST */

View File

@@ -1,226 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "device/designware/dw_trng.h"
#ifndef TRNG_VERSION_NIST
#define DW_TRNG_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
#define DW_TRNG_MODE_R256 0x08
#define DW_TRNG_MODE_R256_OFFSET 3
#define DW_TRNG_ISTAT_RAND_RDY 0x01
#define DW_TRNG_ISTAT_RAND_RDY_OFFSET 0
#define DW_TRNG_ISTAT_SEED_DONE 0x02
#define DW_TRNG_ISTAT_SEED_DONE_OFFSET 1
#define DW_TRNG_ISTAT_AGE_ALARM 0x04
#define DW_TRNG_ISTAT_AGE_ALARM_OFFSET 2
#define DW_TRNG_ISTAT_RQST_ALARM 0x08
#define DW_TRNG_ISTAT_RQST_ALARM_OFFSET 3
#define DW_TRNG_ISTAT_LFSR_LOCKUP 0x10
#define DW_TRNG_ISTAT_LFSR_LOCKUP_OFFSET 4
#define DW_TRNG_CMD_GEN 1
#define DW_TRNG_CMD_RESEED 2
#define DW_TRNG_CMD_NONCE 3
static int32_t dw_trng_cmd(DW_TRNG_REG_PTR trng_reg, uint32_t cmd)
{
int32_t ercd = E_OK;
switch (cmd) {
case DW_TRNG_CMD_GEN:
trng_reg->CTRL |= cmd;
break;
case DW_TRNG_CMD_RESEED:
trng_reg->CTRL |= cmd;
break;
case DW_TRNG_CMD_NONCE:
trng_reg->CTRL |= cmd;
break;
default:
ercd = E_PAR; break;
}
return ercd;
}
inline static int32_t dw_trng_get_mode(DW_TRNG_REG_PTR trng_reg)
{
return (trng_reg->MODE & DW_TRNG_MODE_R256) >> 3;
}
inline static void dw_trng_set_mode(DW_TRNG_REG_PTR trng_reg, uint32_t r256)
{
if (r256) {
trng_reg->MODE |= DW_TRNG_MODE_R256;
} else {
trng_reg->MODE &= ~DW_TRNG_MODE_R256;
}
}
inline static int32_t dw_trng_get_istat_rand_rdy(DW_TRNG_REG_PTR trng_reg)
{
return (trng_reg->ISTAT & DW_TRNG_ISTAT_RAND_RDY) >> DW_TRNG_ISTAT_RAND_RDY_OFFSET;
}
inline static void dw_trng_clear_istat_rand_rdy(DW_TRNG_REG_PTR trng_reg)
{
trng_reg->ISTAT = DW_TRNG_ISTAT_RAND_RDY;// write 1 to clear register bits
}
inline static int32_t dw_trng_get_istat_seed_done(DW_TRNG_REG_PTR trng_reg)
{
return (trng_reg->ISTAT & DW_TRNG_ISTAT_SEED_DONE) >> DW_TRNG_ISTAT_SEED_DONE_OFFSET;
}
inline static void dw_trng_clear_istat_seed_done(DW_TRNG_REG_PTR trng_reg)
{
trng_reg->ISTAT = DW_TRNG_ISTAT_SEED_DONE;// write 1 to clear register bits
}
static void dw_trng_get_rand(DW_TRNG_REG_PTR trng_reg, uint32_t *data) // read from rand0~3 or rand0~7
{
data[0] = trng_reg->RAND0;
data[1] = trng_reg->RAND1;
data[2] = trng_reg->RAND2;
data[3] = trng_reg->RAND3;
// if(dw_trng_get_mode(trng_reg) == 1 )
data[4] = trng_reg->RAND4;
data[5] = trng_reg->RAND5;
data[6] = trng_reg->RAND6;
data[7] = trng_reg->RAND7;
return;
}
static void dw_trng_get_stat(DW_TRNG_REG_PTR trng_reg, uint32_t *stat)
{
*stat = trng_reg->STAT;
return;
}
static int32_t dw_trng_reseed(DW_TRNG_REG_PTR trng_reg, uint32_t *nonce_buf)
{
if (nonce_buf != NULL) {// Nonce Reseed cmd
dw_trng_cmd(trng_reg, DW_TRNG_CMD_NONCE);
// TODO
} else {// Random Reseed cmd
dw_trng_cmd(trng_reg, DW_TRNG_CMD_RESEED);
while (!dw_trng_get_istat_seed_done(trng_reg)) {
// do nothing, wait until reseed is ready
}
dw_trng_clear_istat_seed_done(trng_reg);// clear ISTAT.RAND_RDY bit to acknowledge
}
return E_OK;
}
int32_t dw_trng_open(DEV_TRNG_PTR trng_obj) // reseed with internal random seed generator
{
int32_t ercd = E_OK;
DEV_TRNG_INFO_PTR ptrng_info = &trng_obj->trng_info;
DW_TRNG_CTRL_PTR dw_trng_ctrl_ptr = ptrng_info->trng_ctrl;
DW_TRNG_REG_PTR ptrng = (DW_TRNG_REG_PTR) dw_trng_ctrl_ptr->dw_trng_regs;
dw_trng_reseed(ptrng, NULL);
error_exit:
return ercd;
}
int32_t dw_trng_close(DEV_TRNG_PTR trng_obj) // do nothing
{
return E_OK;
}
int32_t dw_trng_control(DEV_TRNG_PTR trng_obj, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
DEV_TRNG_INFO_PTR ptrng_info = &trng_obj->trng_info;
DW_TRNG_CTRL_PTR dw_trng_ctrl_ptr = ptrng_info->trng_ctrl;
DW_TRNG_REG_PTR ptrng = (DW_TRNG_REG_PTR) dw_trng_ctrl_ptr->dw_trng_regs;
// uint32_t val32; /** to receive unsigned int value */
switch (ctrl_cmd) {
case TRNG_CMD_SET_RAND_128_BIT_OUTPUT:
dw_trng_set_mode(ptrng, 0);
break;
case TRNG_CMD_SET_RAND_256_BIT_OUTPUT:
dw_trng_set_mode(ptrng, 1);
break;
case TRNG_CMD_SET_RAND_RESEED_AUTO:
dw_trng_reseed(ptrng, NULL);
break;
case TRNG_CMD_SET_RAND_RESEED_NONCE:
if (param == NULL) {
ercd = E_PAR;
break;
}
dw_trng_reseed(ptrng, param);
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
int32_t dw_trng_read(DEV_TRNG_PTR trng_obj, uint32_t *data_buf)
{
int32_t ercd = E_OK;
DEV_TRNG_INFO_PTR ptrng_info = &trng_obj->trng_info;
DW_TRNG_CTRL_PTR dw_trng_ctrl_ptr = ptrng_info->trng_ctrl;
DW_TRNG_REG_PTR ptrng = (DW_TRNG_REG_PTR) dw_trng_ctrl_ptr->dw_trng_regs;
dw_trng_cmd(ptrng, DW_TRNG_CMD_GEN);
while (!dw_trng_get_istat_rand_rdy(ptrng)) {
// do nothing, wait until random numbers are ready
}
dw_trng_clear_istat_rand_rdy(ptrng);// clear ISTAT.RAND_RDY bit to acknowledge
dw_trng_get_rand(ptrng, data_buf);
error_exit:
return ercd;
}
void dw_trng_isr(DEV_TRNG_PTR trng_obj, void *ptr)
{
// polling mode, isr not implemented
}
#endif /* TRNG_VERSION_NIST */

View File

@@ -1,958 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include <string.h>
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "device/designware/dw_uart_hal.h"
#include "device/designware/dw_uart.h"
/**
* DesignWare UART driver macros used in uart driver
*/
/** check expressions used in DesignWare UART driver implementation */
#define DW_UART_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
/** valid check of uart info object */
#define VALID_CHK_UART_INFO_OBJECT(uartinfo_obj_ptr) { \
DW_UART_CHECK_EXP((uartinfo_obj_ptr) != NULL, E_OBJ); \
DW_UART_CHECK_EXP(((uartinfo_obj_ptr)->uart_ctrl) != NULL, E_OBJ); \
}
#endif
/** convert DesignWare baudrate to divisor */
#define DW_UART_BAUD2DIV(perifreq, baud) ((perifreq) / ((baud) * 16))
/**
* DesignWare UART interrupt callback routines select macros definitions
*/
#define DW_UART_RDY_SND (1U) /*!< ready to send callback */
#define DW_UART_RDY_RCV (2U) /*!< ready to receive callback */
/**
* @defgroup DEVICE_DW_UART_STATIC DesignWare UART Driver Static Functions
* @ingroup DEVICE_DW_UART
* @brief Static or inline functions, variables for DesignWare UART handle UART operations,
* only used in this file.
* @{
*/
const uint8_t dw_uart_databits[] = { \
DW_UART_LCR_WORD_LEN5, DW_UART_LCR_WORD_LEN6, \
DW_UART_LCR_WORD_LEN7, DW_UART_LCR_WORD_LEN8
};
const uint8_t dw_uart_parity[] = {
DW_UART_LCR_PARITY_NONE, DW_UART_LCR_PARITY_ODD,
DW_UART_LCR_PARITY_EVEN, DW_UART_LCR_PARITY_MASK,
DW_UART_LCR_PARITY_SPACE
};
const uint8_t dw_uart_stopbits[] = {
DW_UART_LCR_1_STOP_BIT, DW_UART_LCR_1D5_STOP_BIT,
DW_UART_LCR_2_STOP_BIT
};
/**
* @fn int32_t dw_uart_putready(DW_UART_REG *uart_reg_ptr)
* @brief Test whether uart is ready to send, 1 ready, 0 not ready
*/
Inline int32_t dw_uart_putready(DW_UART_REG *uart_reg_ptr)
{
if (uart_reg_ptr->CPR & DW_UART_CPR_FIFO_STAT) {
return ((uart_reg_ptr->USR & DW_UART_USR_TFNF) != 0);
} else {
return ((uart_reg_ptr->LSR & DW_UART_LSR_TXD_EMPTY) != 0);
}
}
/**
* @fn int32_t dw_uart_getready(DW_UART_REG *uart_reg_ptr)
* @brief Test whether uart is ready to receive, 1 ready, 0 not ready
*/
Inline int32_t dw_uart_getready(DW_UART_REG *uart_reg_ptr)
{
if (uart_reg_ptr->CPR & DW_UART_CPR_FIFO_STAT) {
return ((uart_reg_ptr->USR & DW_UART_USR_RFNE) != 0);
} else {
return ((uart_reg_ptr->LSR & DW_UART_LSR_DR) != 0);
}
}
/**
* @fn void dw_uart_putchar(DW_UART_REG *uart_reg_ptr, char chr)
* @brief Write char to uart send fifo
*/
Inline void dw_uart_putchar(DW_UART_REG *uart_reg_ptr, char chr)
{
uart_reg_ptr->DATA = chr;
}
/**
* @fn int32_t dw_uart_getchar(DW_UART_REG *uart_reg_ptr)
* @brief Read data from uart receive fifo, return data received
*/
Inline int32_t dw_uart_getchar(DW_UART_REG *uart_reg_ptr)
{
return (int32_t)uart_reg_ptr->DATA;
}
/**
* @fn int32_t dw_uart_snd_chr(DW_UART_REG *uart_reg_ptr, char chr)
* @brief Send char through designware uart when available,
* mostly used in interrupt method, non-blocked function
* @param[in] uart_reg_ptr Uart register structure pointer
* @param[in] chr char to sent
* @retval E_OK Send successfully without any issues
* @retval E_OBJ Device object is not ready to send data
*/
Inline int32_t dw_uart_snd_chr(DW_UART_REG *uart_reg_ptr, char chr)
{
if (dw_uart_putready(uart_reg_ptr)) {
dw_uart_putchar(uart_reg_ptr, chr);
return E_OK;
}
return E_OBJ;
}
/**
* @fn int32_t dw_uart_rcv_chr(DW_UART_REG *uart_reg_ptr)
* @brief Receive one char through designware uart,
* mostly used in interrupt routine, non-blocked function
* @param[in] uart_reg_ptr Uart register structure pointer
* @return Data received
*/
Inline int32_t dw_uart_rcv_chr(DW_UART_REG *uart_reg_ptr)
{
return dw_uart_getchar(uart_reg_ptr);
}
/**
* @fn void dw_uart_psnd_chr(DW_UART_REG *uart_reg_ptr, char chr)
* @brief Send char through designware uart in poll method, blocked function
* @param[in] uart_reg_ptr Uart register structure pointer
* @param[in] chr Char to sent
*/
Inline void dw_uart_psnd_chr(DW_UART_REG *uart_reg_ptr, char chr)
{
/** wait until uart is ready to send */
while (!dw_uart_putready(uart_reg_ptr)) {
; /* blocked */
}
/** send char */
dw_uart_putchar(uart_reg_ptr, chr);
}
/**
* @fn int32_t dw_uart_prcv_chr(DW_UART_REG *uart_reg_ptr)
* @brief Receive one char through designware uart in poll method, blocked function
* @param[in] uart_reg_ptr Uart register structure pointer
* @return Data received
*/
Inline int32_t dw_uart_prcv_chr(DW_UART_REG *uart_reg_ptr)
{
/** wait until uart is ready to receive */
while (!dw_uart_getready(uart_reg_ptr)) {
; /* blocked */
}
/** receive data */
return dw_uart_getchar(uart_reg_ptr);
}
/**
* @brief Set designware uart DPS value
* @param uart_reg_ptr Uart register structure pointer
* @param dps Data bits/parity bit/stop bits parameter
* @retval 0 Set ok
* @retval !0 Set failed
*/
static int32_t dw_uart_set_dps(DW_UART_REG *uart_reg_ptr, UART_DPS_FORMAT *dps)
{
uint32_t dps_value = 0;
/* data bits check */
if ((dps->databits < 5) || (dps->databits > 8)) {
return -1;
}
/* stop bits check */
if (dps->stopbits > UART_STPBITS_TWO) {
return -1;
}
/* parity bit type check */
if (dps->parity > UART_PARITY_SPACE) {
return -1;
}
dps_value |= (uint32_t)dw_uart_databits[dps->databits - 5];
dps_value |= (uint32_t)dw_uart_stopbits[dps->stopbits];
dps_value |= (uint32_t)dw_uart_parity[dps->parity];
/* clear dps bits */
uart_reg_ptr->LCR &= (~DW_UART_LCR_DPS_MASK);
/* set dps bits */
uart_reg_ptr->LCR |= dps_value;
return 0;
}
/**
* @brief Set designware uart baudrate
* @param uart_reg_ptr Uart register structure pointer
* @param baud_divisor Uart baudrate divisor
*/
static void dw_uart_set_baud(DW_UART_REG *uart_reg_ptr, uint32_t baud_divisor)
{
/* enable uart baudrate update */
uart_reg_ptr->LCR |= DW_UART_LCR_DLAB;
/**
* setting uart baudrate registers
*/
uart_reg_ptr->DATA = baud_divisor & 0xff; /*!< DLL */
uart_reg_ptr->IER = (baud_divisor >> 8) & 0xff; /*!< DLH */
/** disable DLAB */
uart_reg_ptr->LCR &= ~(DW_UART_LCR_DLAB);
}
/**
* @fn void dw_uart_software_reset(DW_UART_REG *uart_reg_ptr)
* @brief Do uart software reset
* @param uart_reg_ptr Uart register structure pointer
*/
Inline void dw_uart_software_reset(DW_UART_REG *uart_reg_ptr)
{
uart_reg_ptr->SRR = DW_UART_SRR_UR | DW_UART_SRR_RFR | DW_UART_SRR_XFR;
while (uart_reg_ptr->USR & DW_UART_USR_BUSY) {
; /* wait until software reset completed */
}
}
/**
* @brief Set designware uart baudrate
* @param uart_reg_ptr Uart register structure pointer
* @param hwfc Uart hardware flow control type
* @note Need to set corresponding pin functions
*/
static void dw_uart_set_hwfc(DW_UART_REG *uart_reg_ptr, UART_HW_FLOW_CONTROL hwfc)
{
if (hwfc == UART_FC_NONE) {
uart_reg_ptr->MCR &= ~(DW_UART_MCR_AFCE | DW_UART_MCR_RTS);
}
if ((hwfc == UART_FC_RTS) || (hwfc == UART_FC_BOTH)) {
uart_reg_ptr->MCR |= (DW_UART_MCR_AFCE | DW_UART_MCR_RTS);
}
if ((hwfc == UART_FC_CTS) || (hwfc == UART_FC_BOTH)) {
uart_reg_ptr->MCR |= (DW_UART_MCR_AFCE);
}
}
/**
* @fn void dw_spi_disable(DW_SPI_REG *spi_reg_ptr)
*/
Inline void dw_uart_set_break(DW_UART_REG *uart_reg_ptr)
{
uart_reg_ptr->LCR |= DW_UART_LCR_BREAK;
}
/**
* @fn void dw_uart_clr_break(DW_UART_REG *uart_reg_ptr)
*/
Inline void dw_uart_clr_break(DW_UART_REG *uart_reg_ptr)
{
uart_reg_ptr->LCR &= ~DW_UART_LCR_BREAK;
}
/**
* @brief Initialise designware uart with selected baud rate
* @param[in] uart_reg_ptr Uart register structure pointer
* @param[in] baud_divisor Baud rate
* @param[in] dps Uart databits/parity/stopbits
* @param[in] hwfc Uart flow control method
*/
static void dw_uart_init(DW_UART_REG *uart_reg_ptr, uint32_t baud_divisor, UART_DPS_FORMAT *dps, UART_HW_FLOW_CONTROL hwfc)
{
dw_uart_software_reset(uart_reg_ptr);
dw_uart_set_hwfc(uart_reg_ptr, hwfc);
dw_uart_set_dps(uart_reg_ptr, dps);
dw_uart_set_baud(uart_reg_ptr, baud_divisor);
uart_reg_ptr->IIR = 0x1; /** enable uart fifo (FCR IIR is the same) */
uart_reg_ptr->IER = 0x0; /** disable all uart interrupt */
}
/**
* @brief Set designware uart baud rate
* @param uart_info_ptr Uart information structure pointer
*/
static void dw_uart_flush_output(DEV_UART_INFO *uart_info_ptr)
{
uint32_t i;
char *p_charbuf;
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
if (uart_info_ptr->tx_buf.buf != NULL) {
p_charbuf = (char *)(uart_info_ptr->tx_buf.buf);
for (i = uart_info_ptr->tx_buf.ofs; i < uart_info_ptr->tx_buf.len; i++) {
dw_uart_psnd_chr(uart_reg_ptr, p_charbuf[i]);
}
/* clear transmit buffer */
uart_info_ptr->tx_buf.buf = NULL;
uart_info_ptr->tx_buf.len = 0;
uart_info_ptr->tx_buf.ofs = 0;
}
if (uart_reg_ptr->CPR & DW_UART_CPR_FIFO_STAT) {
/* wait until transmit fifo is empty */
while ((uart_reg_ptr->USR & DW_UART_USR_TFE) == 0) {
;
}
}
while (uart_reg_ptr->USR & DW_UART_USR_BUSY) {
;
}
}
/**
* @brief Disable designware uart send or receive interrupt
* @param[in] uart_info_ptr Uart information structure pointer
* @param[in] cbrtn Control code of callback routine
*/
static void dw_uart_dis_cbr(DEV_UART_INFO *uart_info_ptr, uint32_t cbrtn)
{
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
switch (cbrtn) {
case DW_UART_RDY_SND:
uart_reg_ptr->IER &= ~DW_UART_IER_XMIT_EMPTY;
uart_ctrl_ptr->int_status &= ~DW_UART_TXINT_ENABLE;
break;
case DW_UART_RDY_RCV:
uart_reg_ptr->IER &= ~DW_UART_IER_DATA_AVAIL;
uart_ctrl_ptr->int_status &= ~DW_UART_RXINT_ENABLE;
break;
default:
break;
}
if (uart_ctrl_ptr->int_status & DW_UART_GINT_ENABLE) {
if ((uart_ctrl_ptr->int_status & (DW_UART_RXINT_ENABLE | DW_UART_TXINT_ENABLE)) == 0) {
if (uart_ctrl_ptr->intno != DW_UART_INVALID_INTNO) {
int_disable(uart_ctrl_ptr->intno);
}
uart_ctrl_ptr->int_status &= ~DW_UART_GINT_ENABLE;
}
}
}
/**
* @brief Enable DesignWare UART send or receive interrupt
* @param[in] uart_info_ptr Uart information structure pointer
* @param[in] cbrtn Control code of callback routine
*/
static void dw_uart_ena_cbr(DEV_UART_INFO *uart_info_ptr, uint32_t cbrtn)
{
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
switch (cbrtn) {
case DW_UART_RDY_SND:
uart_ctrl_ptr->int_status |= DW_UART_TXINT_ENABLE;
uart_reg_ptr->IER |= DW_UART_IER_XMIT_EMPTY;
break;
case DW_UART_RDY_RCV:
uart_ctrl_ptr->int_status |= DW_UART_RXINT_ENABLE;
uart_reg_ptr->IER |= DW_UART_IER_DATA_AVAIL;
break;
default:
break;
}
if ((uart_ctrl_ptr->int_status & DW_UART_GINT_ENABLE) == 0) {
if (uart_ctrl_ptr->int_status & (DW_UART_RXINT_ENABLE | DW_UART_TXINT_ENABLE)) {
uart_ctrl_ptr->int_status |= DW_UART_GINT_ENABLE;
if (uart_ctrl_ptr->intno != DW_UART_INVALID_INTNO) {
int_enable(uart_ctrl_ptr->intno);
}
}
}
}
/**
* @brief Disable designware uart interrupt
* @param uart_info_ptr Uart information structure pointer
*/
static void dw_uart_disable_interrupt(DEV_UART_INFO *uart_info_ptr)
{
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
/** disable uart send&receive interrupt after disable uart interrupt */
dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
/* disable uart interrupt */
if (uart_ctrl_ptr->intno != DW_UART_INVALID_INTNO) {
int_disable(uart_ctrl_ptr->intno);
}
uart_ctrl_ptr->int_status &= ~(DW_UART_GINT_ENABLE | DW_UART_TXINT_ENABLE | DW_UART_RXINT_ENABLE);
}
/** enable designware uart */
static void dw_uart_enable_device(DEV_UART_INFO *uart_info_ptr)
{
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
if ((uart_info_ptr->status & DEV_ENABLED) == 0) {
dw_uart_set_baud(uart_reg_ptr, uart_info_ptr->baudrate);
uart_info_ptr->status |= DEV_ENABLED;
}
}
/** disable designware uart */
static void dw_uart_disable_device(DEV_UART_INFO *uart_info_ptr)
{
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
if ((uart_info_ptr->status & DEV_ENABLED) == DEV_ENABLED) {
dw_uart_set_baud(uart_reg_ptr, 0);
uart_info_ptr->status &= ~DEV_ENABLED;
}
}
/** abort current interrupt transmit transfer */
static void dw_uart_abort_tx(DEV_UART *uart_obj)
{
DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
if (uart_ctrl_ptr->int_status & DW_UART_TXINT_ENABLE) {
dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
uart_info_ptr->status |= DEV_IN_TX_ABRT;
if (uart_info_ptr->uart_cbs.tx_cb != NULL) {
uart_info_ptr->uart_cbs.tx_cb(uart_obj);
}
uart_info_ptr->status &= ~(DEV_IN_TX_ABRT);
}
}
/** abort current interrupt receive transfer */
static void dw_uart_abort_rx(DEV_UART *uart_obj)
{
DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
if (uart_ctrl_ptr->int_status & DW_UART_RXINT_ENABLE) {
dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
uart_info_ptr->status |= DEV_IN_RX_ABRT;
if (uart_info_ptr->uart_cbs.rx_cb != NULL) {
uart_info_ptr->uart_cbs.rx_cb(uart_obj);
}
uart_info_ptr->status &= ~(DEV_IN_RX_ABRT);
}
}
/** Get available transmit fifo count */
static int32_t dw_uart_get_txavail(DW_UART_CTRL *uart_ctrl_ptr)
{
int32_t tx_avail = 0;
DW_UART_REG *uart_reg_ptr = (DW_UART_REG *)(uart_ctrl_ptr->dw_uart_regbase);
if (uart_ctrl_ptr->tx_fifo_len <= 1) {
if (dw_uart_putready(uart_reg_ptr) == 1) {
tx_avail = 1;
} else {
tx_avail = 0;
}
} else {
tx_avail = uart_ctrl_ptr->tx_fifo_len - uart_reg_ptr->TFL;
}
return tx_avail;
}
/** Get available receive fifo count */
static int32_t dw_uart_get_rxavail(DW_UART_CTRL *uart_ctrl_ptr)
{
int32_t rx_avail = 0;
DW_UART_REG *uart_reg_ptr = (DW_UART_REG *)(uart_ctrl_ptr->dw_uart_regbase);
if (uart_ctrl_ptr->rx_fifo_len <= 1) {
if (dw_uart_getready(uart_reg_ptr) == 1) {
rx_avail = 1;
} else {
rx_avail = 0;
}
} else {
rx_avail = uart_reg_ptr->RFL;
}
return rx_avail;
}
/** @} end of group DEVICE_DW_UART_STATIC */
/**
* @brief Open a designware uart device
* @param[in] uart_obj Uart object structure pointer
* @param[in] baud Baud rate
* @retval E_OK Open successfully without any issues
* @retval E_OPNED If device was opened before with different baudrate, then return E_OPNED
* @retval E_OBJ Device object is not valid
* @retval E_PAR Parameter is not valid
* @retval E_NOSPT Open settings are not supported
*/
int32_t dw_uart_open(DEV_UART *uart_obj, uint32_t baud)
{
int32_t ercd = E_OK;
DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
/* START ERROR CHECK */
VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
DW_UART_CHECK_EXP(baud > 0, E_PAR);
/* END OF ERROR CHECK */
uart_info_ptr->opn_cnt++;
if (uart_info_ptr->opn_cnt > 1) { /* opened before */
if (baud == uart_info_ptr->baudrate) { /* baudrate is the same */
return E_OK;
} else { /* open with different baudrate */
return E_OPNED;
}
}
int32_t baud_divisor = 0;
uint32_t uart_cpr;
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
uart_cpr = uart_reg_ptr->CPR;
/* Get FIFO Length */
if (uart_cpr & DW_UART_CPR_FIFO_STAT) {
uart_ctrl_ptr->tx_fifo_len = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4;
uart_ctrl_ptr->rx_fifo_len = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4;
} else {
uart_ctrl_ptr->tx_fifo_len = 0;
uart_ctrl_ptr->rx_fifo_len = 0;
}
/** init uart */
uart_info_ptr->baudrate = baud;
baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, baud);
UART_DPS_FORMAT_DEFAULT(uart_info_ptr->dps_format);
uart_info_ptr->hwfc = UART_FC_DEFAULT;
dw_uart_init(uart_reg_ptr, baud_divisor, &(uart_info_ptr->dps_format), uart_info_ptr->hwfc);
uart_info_ptr->status = DEV_ENABLED;
uart_info_ptr->extra = NULL;
/**
* uart interrupt related init
*/
dw_uart_disable_interrupt(uart_info_ptr);
/** install uart interrupt into system */
if (uart_ctrl_ptr->intno != DW_UART_INVALID_INTNO) {
int_handler_install(uart_ctrl_ptr->intno, uart_ctrl_ptr->dw_uart_int_handler);
}
memset(&(uart_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER));
memset(&(uart_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER));
memset(&(uart_info_ptr->uart_cbs), 0, sizeof(DEV_UART_CBS));
error_exit:
return ercd;
}
/**
* @brief Close a DesignWare UART device
* @param[in] uart_obj Uart object structure pointer
* @retval E_OK Open successfully without any issues
* @retval E_OPNED Device is still opened, the device opn_cnt decreased by 1
* @retval E_OBJ Device object is not valid
*/
int32_t dw_uart_close(DEV_UART *uart_obj)
{
int32_t ercd = E_OK;
DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
/* START ERROR CHECK */
VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_OK);
/* END OF ERROR CHECK */
uart_info_ptr->opn_cnt--;
if (uart_info_ptr->opn_cnt == 0) {
dw_uart_disable_interrupt(uart_info_ptr);
dw_uart_abort_tx(uart_obj);
dw_uart_abort_rx(uart_obj);
dw_uart_flush_output(uart_info_ptr);
memset(&(uart_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER));
memset(&(uart_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER));
memset(&(uart_info_ptr->uart_cbs), 0, sizeof(DEV_UART_CBS));
dw_uart_disable_device(uart_info_ptr);
uart_info_ptr->status = 0;
uart_info_ptr->extra = NULL;
} else {
ercd = E_OPNED;
}
error_exit:
return ercd;
}
/**
* @brief Control uart by ctrl command
* @param[in] uart_obj Uart object structure pointer
* @param[in] ctrl_cmd @ref DEVICE_HAL_UART_CTRLCMD "control command", to change or get some thing related to uart
* @param[in,out] param Parameters used to control uart or return something
* @retval E_OK Control device successfully
* @retval E_CLSED Device is not opened
* @retval E_DIS Device is disabled
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid for current control command
* @retval E_SYS Control device failed, due to hardware issues
* @retval E_CTX Control device failed, due to different reasons like in transfer state
* @retval E_NOSPT Control command is not supported or not valid
*/
int32_t dw_uart_control(DEV_UART *uart_obj, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
/* START ERROR CHECK */
VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
/* END OF ERROR CHECK */
uint32_t val32; /** to receive unsigned int value */
int32_t baud_divisor = 0;
DEV_BUFFER *devbuf;
UART_DPS_FORMAT *dps_ptr;
UART_HW_FLOW_CONTROL hwfc_local;
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
/* check whether current device is disabled */
if ((uart_info_ptr->status & DEV_ENABLED) == 0) {
/** When device is disabled,
* only UART_CMD_ENA_DEV, UART_CMD_DIS_DEV, UART_CMD_GET_STATUS
* are available, other commands will return E_SYS
*/
if ((ctrl_cmd != UART_CMD_ENA_DEV) && \
(ctrl_cmd != UART_CMD_DIS_DEV) && \
(ctrl_cmd != UART_CMD_GET_STATUS)) {
return E_SYS;
}
}
switch (ctrl_cmd) {
case UART_CMD_SET_BAUD:
val32 = (uint32_t)param;
DW_UART_CHECK_EXP(val32 > 0, E_PAR);
if (val32 != uart_info_ptr->baudrate) {
baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, val32);
dw_uart_set_baud(uart_reg_ptr, baud_divisor);
uart_info_ptr->baudrate = val32;
}
break;
case UART_CMD_GET_STATUS:
DW_UART_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = uart_info_ptr->status;
break;
case UART_CMD_ENA_DEV:
dw_uart_enable_device(uart_info_ptr);
break;
case UART_CMD_DIS_DEV:
dw_uart_disable_device(uart_info_ptr);
break;
case UART_CMD_FLUSH_OUTPUT:
dw_uart_flush_output(uart_info_ptr);
break;
case UART_CMD_GET_RXAVAIL:
DW_UART_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = dw_uart_get_rxavail(uart_ctrl_ptr);
break;
case UART_CMD_GET_TXAVAIL:
DW_UART_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = dw_uart_get_txavail(uart_ctrl_ptr);
break;
case UART_CMD_BREAK_SET:
dw_uart_set_break(uart_reg_ptr);
break;
case UART_CMD_BREAK_CLR:
dw_uart_clr_break(uart_reg_ptr);
break;
case UART_CMD_SET_DPS_FORMAT:
DW_UART_CHECK_EXP(param != NULL, E_PAR);
dps_ptr = (UART_DPS_FORMAT *)param;
if (dw_uart_set_dps(uart_reg_ptr, dps_ptr) == 0) {
uart_info_ptr->dps_format = *dps_ptr;
} else {
ercd = E_PAR;
}
break;
case UART_CMD_SET_HWFC:
hwfc_local = (UART_HW_FLOW_CONTROL)param;
DW_UART_CHECK_EXP(((hwfc_local >= UART_FC_NONE) && (hwfc_local <= UART_FC_BOTH)), E_PAR);
dw_uart_set_hwfc(uart_reg_ptr, hwfc_local);
uart_info_ptr->hwfc = hwfc_local;
break;
case UART_CMD_SET_TXCB:
DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
uart_info_ptr->uart_cbs.tx_cb = param;
break;
case UART_CMD_SET_RXCB:
DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
uart_info_ptr->uart_cbs.rx_cb = param;
break;
case UART_CMD_SET_ERRCB:
DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
uart_info_ptr->uart_cbs.err_cb = param;
break;
case UART_CMD_ABORT_TX:
dw_uart_abort_tx(uart_obj);
break;
case UART_CMD_ABORT_RX:
dw_uart_abort_rx(uart_obj);
break;
case UART_CMD_SET_TXINT:
val32 = (uint32_t)param;
if (val32 == 0) {
dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
} else {
dw_uart_ena_cbr(uart_info_ptr, DW_UART_RDY_SND);
}
break;
case UART_CMD_SET_RXINT:
val32 = (uint32_t)param;
if (val32 == 0) {
dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
} else {
dw_uart_ena_cbr(uart_info_ptr, DW_UART_RDY_RCV);
}
break;
case UART_CMD_SET_TXINT_BUF:
DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
if (param != NULL) {
devbuf = (DEV_BUFFER *)param;
uart_info_ptr->tx_buf = *devbuf;
uart_info_ptr->tx_buf.ofs = 0;
} else {
uart_info_ptr->tx_buf.buf = NULL;
uart_info_ptr->tx_buf.len = 0;
uart_info_ptr->tx_buf.ofs = 0;
}
break;
case UART_CMD_SET_RXINT_BUF:
DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
if (param != NULL) {
devbuf = (DEV_BUFFER *)param;
uart_info_ptr->rx_buf = *devbuf;
uart_info_ptr->rx_buf.ofs = 0;
} else {
uart_info_ptr->rx_buf.buf = NULL;
uart_info_ptr->rx_buf.len = 0;
uart_info_ptr->rx_buf.ofs = 0;
}
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
/**
* @brief Send data through DesignWare UART
* @param[in] uart_obj Uart object structure pointer
* @param[in] data Data to send (data must be char type)
* @param[in] len Data length to send
* @retval > 0 Byte count that was successfully sent for poll method
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid for current control command
* @retval E_SYS Can't write data to hardware due to hardware issues
*/
int32_t dw_uart_write(DEV_UART *uart_obj, const void *data, uint32_t len)
{
int32_t ercd = E_OK;
DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
/* START ERROR CHECK */
VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
DW_UART_CHECK_EXP(uart_info_ptr->status & DEV_ENABLED, E_SYS);
DW_UART_CHECK_EXP(data != NULL, E_PAR);
DW_UART_CHECK_EXP(len > 0, E_PAR);
/* END OF ERROR CHECK */
int32_t i = 0;
const char *p_charbuf = (const char *)data;
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
while (i < len) {
dw_uart_psnd_chr(uart_reg_ptr, p_charbuf[i++]);
}
ercd = i;
error_exit:
return ercd;
}
/**
* @brief Read data through DesignWare UART
* @param[in] uart_obj Uart object structure pointer
* @param[out] data Data that need to read (data must be char type)
* @param[in] len Data count to read
* @retval > 0 Byte count that was successfully sent for poll method
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid for current control command
* @retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled
*/
int32_t dw_uart_read(DEV_UART *uart_obj, void *data, uint32_t len)
{
int32_t ercd = E_OK;
DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
/* START ERROR CHECK */
VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
DW_UART_CHECK_EXP(uart_info_ptr->status & DEV_ENABLED, E_SYS);
DW_UART_CHECK_EXP(data != NULL, E_PAR);
DW_UART_CHECK_EXP(len > 0, E_PAR);
/* END OF ERROR CHECK */
int32_t i = 0;
char *p_charbuf = (char *)data;
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
while (i < len) {
p_charbuf[i++] = dw_uart_prcv_chr(uart_reg_ptr);
}
ercd = i;
error_exit:
return ercd;
}
/**
* @brief DesignWare UART interrupt processing routine
* @param[in] uart_obj Uart object structure pointer
* @param[in] ptr Extra information
*/
void dw_uart_isr(DEV_UART *uart_obj, void *ptr)
{
int32_t ercd = E_OK;
DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
/* START ERROR CHECK */
VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
/* END OF ERROR CHECK */
uint32_t uart_int_status; /** uart interrupt status */
volatile uint32_t temp; /** read error status to clear interrupt */
DEV_BUFFER *buf_ptr;
char *p_charbuf;
DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
/** get uart interrupt status */
uart_int_status = (uart_reg_ptr->IIR) & DW_UART_IIR_INT_ID_MASK;
switch (uart_int_status) {
case DW_UART_IIR_MDM_STATUS:
temp = (volatile uint32_t)(uart_reg_ptr->MSR);
break;
case DW_UART_IIR_LINE_STATUS:
if (uart_info_ptr->uart_cbs.err_cb) {
uart_info_ptr->uart_cbs.err_cb(uart_info_ptr);
}
temp = (volatile uint32_t)(uart_reg_ptr->LSR);
break;
case DW_UART_IIR_XMIT_EMPTY:
buf_ptr = &(uart_info_ptr->tx_buf);
p_charbuf = (char *)buf_ptr->buf;
if (p_charbuf != NULL) {
while (dw_uart_putready(uart_reg_ptr)) {
dw_uart_putchar(uart_reg_ptr, p_charbuf[buf_ptr->ofs]);
buf_ptr->ofs++;
if (buf_ptr->ofs >= buf_ptr->len) {
dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
if (uart_info_ptr->uart_cbs.tx_cb) {
uart_info_ptr->uart_cbs.tx_cb(uart_obj);
}
/* clear the send buffer pointer */
memset(buf_ptr, 0, sizeof(DEV_BUFFER));
break;
}
}
} else {
if (uart_info_ptr->uart_cbs.tx_cb) {
uart_info_ptr->uart_cbs.tx_cb(uart_obj);
}
}
break;
case DW_UART_IIR_RX_TIMEOUT:
temp = dw_uart_getchar(uart_reg_ptr);
break;
case DW_UART_IIR_DATA_AVAIL:
buf_ptr = &(uart_info_ptr->rx_buf);
p_charbuf = (char *)buf_ptr->buf;
if (p_charbuf != NULL) {
while (dw_uart_getready(uart_reg_ptr)) {
p_charbuf[buf_ptr->ofs] = (char)dw_uart_getchar(uart_reg_ptr);
buf_ptr->ofs++;
if (buf_ptr->ofs >= buf_ptr->len) {
dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
if (uart_info_ptr->uart_cbs.rx_cb) {
uart_info_ptr->uart_cbs.rx_cb(uart_obj);
}
/* clear the send buffer pointer */
memset(buf_ptr, 0, sizeof(DEV_BUFFER));
break;
}
}
} else {
if (uart_info_ptr->uart_cbs.rx_cb) {
uart_info_ptr->uart_cbs.rx_cb(uart_obj);
}
}
break;
default:
temp = (volatile uint32_t)(uart_reg_ptr->USR);
break;
}
error_exit:
return;
}

View File

@@ -1,91 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-2.1.13
* ========================================================================== */
#include <stdint.h>
#include "device/subsystem/creg_master.h"
#include "io_config.h"
#include "apexextensions.h"
/* determine whether there is at least a single CREG master instance */
#ifdef IO_CREG_MST0_PRESENT
#define CREG_MASTER_DEV_PRESENT
#endif
#ifdef IO_CREG_MST1_PRESENT
#define CREG_MASTER_DEV_PRESENT
#endif
#ifdef IO_CREG_MST2_PRESENT
#define CREG_MASTER_DEV_PRESENT
#endif
#ifdef IO_CREG_MST3_PRESENT
#define CREG_MASTER_DEV_PRESENT
#endif
#ifdef CREG_MASTER_DEV_PRESENT
/* Addresses of CREG master instances */
static const uint32_t creg_masters[4] = {
#ifdef IO_CREG_MST0_PRESENT
AR_IO_CREG_MST0_CTRL,
#else
0,
#endif
#ifdef IO_CREG_MST1_PRESENT
AR_IO_CREG_MST1_CTRL,
#else
0,
#endif
#ifdef IO_CREG_MST2_PRESENT
AR_IO_CREG_MST2_CTRL,
#else
0,
#endif
#ifdef IO_CREG_MST3_PRESENT
AR_IO_CREG_MST3_CTRL,
#else
0,
#endif
};
#define CREG_WRITE(x) _sr((unsigned)(x), (unsigned)creg_masters[dev_id])
#define CREG_READ( ) _lr((unsigned)creg_masters[dev_id])
void io_creg_master_read(uint32_t dev_id, uint32_t *reg_val)
{
*reg_val = CREG_READ();
}
void io_creg_master_write(uint32_t dev_id, uint32_t reg_val)
{
CREG_WRITE(reg_val);
}
#endif

View File

@@ -1,85 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-2.1.13
* ========================================================================== */
#include <stdint.h>
#include "device/subsystem/creg_slave.h"
#include "io_config.h"
#include "apexextensions.h"
/* determine whether there is at least a single CREG master instance */
#ifdef IO_CREG_SLV0_PRESENT
#define CREG_SLAVE_DEV_PRESENT
#endif
#ifdef IO_CREG_SLV1_PRESENT
#define CREG_SLAVE_DEV_PRESENT
#endif
#ifdef IO_CREG_SLV2_PRESENT
#define CREG_SLAVE_DEV_PRESENT
#endif
#ifdef IO_CREG_SLV3_PRESENT
#define CREG_SLAVE_DEV_PRESENT
#endif
#ifdef CREG_SLAVE_DEV_PRESENT
/* Addresses of CREG slave instances */
static const uint32_t creg_slaves[4] = {
#ifdef IO_CREG_SLV0_PRESENT
AR_IO_CREG_SLV0_OBSR,
#else
0,
#endif
#ifdef IO_CREG_SLV1_PRESENT
AR_IO_CREG_SLV1_OBSR,
#else
0,
#endif
#ifdef IO_CREG_SLV2_PRESENT
AR_IO_CREG_SLV2_OBSR,
#else
0,
#endif
#ifdef IO_CREG_SLV3_PRESENT
AR_IO_CREG_SLV3_OBSR
#else
0,
#endif
};
#define CREG_READ( ) _lr((unsigned)creg_slaves[dev_id])
void io_creg_slave_read(uint32_t dev_id, uint32_t *reg_val)
{
*reg_val = CREG_READ();
}
#endif

View File

@@ -1,417 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "device/subsystem/gpio.h"
#include "io_config.h"
#include "apexextensions.h"
/* EIA GPIO device registers */
#define SWPORTA_DR (0x00) /* GPIO Port A Data Register */
#define SWPORTA_DDR (0x04) /* GPIO Port A Data Direction Register */
#define INTEN (0x30) /* GPIO Interrupt Enable Register */
#define INTMASK (0x34) /* GPIO Interrupt Mask Register */
#define INTTYPE_LEVEL (0x38) /* GPIO Interrupt Type Register */
#define INT_POLARITY (0x3c) /* GPIO Interrupt Polarity Register */
#define INTSTATUS (0x44) /* GPIO Interrupt Status Register */
#define DEBOUNCE (0x48) /* GPIO Debounce Enable Register */
#define PORTA_EOI (0x4c) /* GPIO Port A Clear Interrupt Register */
#define EXT_PORTA (0x50) /* GPIO External Port A Register */
#define LS_SYNC (0x60) /* GPIO Level-Sensitive Sync Enable Register */
#define INT_BOTHEDGE (0x68) /* GPIO Both Edge Register */
#define CLKEN (0x80) /* GPIO Clock Enable Register */
typedef _Interrupt void (*ISR) ();
/* Private data structure maintained by the driver. */
typedef struct gpio_info_struct {
uint32_t reg_base; /* base address of device register set */
/* Callbacks */
IO_CB_FUNC rx_cb;
uint8_t opened;
uint8_t instID;
/* Interrupt numbers and handlers */
uint8_t vector; /* GPIO ISR vector */
ISR isr; /* GPIO ISR */
/* Config option */
uint8_t enableDebounce;
} gpio_info_t, *gpio_info_pt;
#ifdef IO_GPIO0_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO1_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO2_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO3_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_8B0_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_8B1_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_8B2_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_8B3_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_4B0_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_4B1_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_4B2_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_4B3_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef GPIO_DEV_PRESENT
#define GPIO_32_MAX_CNT (4)
#define GPIO_8B_MAX_CNT (4)
#define GPIO_4B_MAX_CNT (4)
#define GPIO_MAX_CNT ((GPIO_32_MAX_CNT) + (GPIO_8B_MAX_CNT) + (GPIO_4B_MAX_CNT))
static void gpio_ISR_proc(uint32_t dev_id);
#ifdef IO_GPIO0_PRESENT
static _Interrupt void gpio0_ISR()
{
gpio_ISR_proc(0);
}
#endif
#ifdef IO_GPIO1_PRESENT
static _Interrupt void gpio1_ISR()
{
gpio_ISR_proc(1);
}
#endif
#ifdef IO_GPIO2_PRESENT
static _Interrupt void gpio2_ISR()
{
gpio_ISR_proc(2);
}
#endif
#ifdef IO_GPIO3_PRESENT
static _Interrupt void gpio3_ISR()
{
gpio_ISR_proc(3);
}
#endif
#ifdef IO_GPIO_8B0_PRESENT
static _Interrupt void gpio_8B_0_ISR()
{
gpio_ISR_proc(0 + GPIO_32_MAX_CNT);
}
#endif
#ifdef IO_GPIO_8B1_PRESENT
static _Interrupt void gpio_8B_1_ISR()
{
gpio_ISR_proc(1 + GPIO_32_MAX_CNT);
}
#endif
#ifdef IO_GPIO_8B2_PRESENT
static _Interrupt void gpio_8B_2_ISR()
{
gpio_ISR_proc(2 + GPIO_32_MAX_CNT);
}
#endif
#ifdef IO_GPIO_8B3_PRESENT
static _Interrupt void gpio_8B_3_ISR()
{
gpio_ISR_proc(3 + GPIO_32_MAX_CNT);
}
#endif
#ifdef IO_GPIO_4B0_PRESENT
static _Interrupt void gpio_4B_0_ISR()
{
gpio_ISR_proc(0 + GPIO_32_MAX_CNT + GPIO_8B_MAX_CNT);
}
#endif
#ifdef IO_GPIO_4B1_PRESENT
static _Interrupt void gpio_4B_1_ISR()
{
gpio_ISR_proc(1 + GPIO_32_MAX_CNT + GPIO_8B_MAX_CNT);
}
#endif
#ifdef IO_GPIO_4B2_PRESENT
static _Interrupt void gpio_4B_2_ISR()
{
gpio_ISR_proc(2 + GPIO_32_MAX_CNT + GPIO_8B_MAX_CNT);
}
#endif
#ifdef IO_GPIO_4B3_PRESENT
static _Interrupt void gpio_4B_3_ISR()
{
gpio_ISR_proc(3 + GPIO_32_MAX_CNT + GPIO_8B_MAX_CNT);
}
#endif
/* GPIO devices private data structures */
static gpio_info_pt gpio_handles[GPIO_MAX_CNT] = { 0 };
static gpio_info_t gpio_devs[] = {
#ifdef IO_GPIO0_PRESENT
{ .instID = IO_GPIO_DEV_ID(0, 32),
.reg_base = AR_IO_GPIO0_SWPORTA_DR,
.vector = IO_GPIO0_INT_INTR_FLAG,
.isr = gpio0_ISR,
.enableDebounce = IO_GPIO0_DEBOUNCE },
#endif
#ifdef IO_GPIO1_PRESENT
{ .instID = IO_GPIO_DEV_ID(1, 32),
.reg_base = AR_IO_GPIO1_SWPORTA_DR,
.vector = IO_GPIO1_INT_INTR_FLAG,
.isr = gpio1_ISR,
.enableDebounce = IO_GPIO1_DEBOUNCE },
#endif
#ifdef IO_GPIO2_PRESENT
{ .instID = IO_GPIO_DEV_ID(2, 32),
.reg_base = AR_IO_GPIO2_SWPORTA_DR,
.vector = IO_GPIO2_INT_INTR_FLAG,
.isr = gpio2_ISR,
.enableDebounce = IO_GPIO2_DEBOUNCE },
#endif
#ifdef IO_GPIO3_PRESENT
{ .instID = IO_GPIO_DEV_ID(3, 32),
.reg_base = AR_IO_GPIO3_SWPORTA_DR,
.vector = IO_GPIO3_INT_INTR_FLAG,
.isr = gpio3_ISR,
.enableDebounce = IO_GPIO3_DEBOUNCE },
#endif
#ifdef IO_GPIO_8B0_PRESENT
{ .instID = IO_GPIO_DEV_ID(0, 8),
.reg_base = AR_IO_GPIO_8B0_SWPORTA_DR,
.vector = IO_GPIO_8B0_INT_INTR_FLAG,
.isr = gpio_8B_0_ISR,
.enableDebounce = IO_GPIO_8B0_DEBOUNCE },
#endif
#ifdef IO_GPIO_8B1_PRESENT
{ .instID = IO_GPIO_DEV_ID(1, 8),
.reg_base = AR_IO_GPIO_8B1_SWPORTA_DR,
.vector = IO_GPIO_8B1_INT_INTR_FLAG,
.isr = gpio_8B_1_ISR,
.enableDebounce = IO_GPIO_8B1_DEBOUNCE },
#endif
#ifdef IO_GPIO_8B2_PRESENT
{ .instID = IO_GPIO_DEV_ID(2, 8),
.reg_base = AR_IO_GPIO_8B2_SWPORTA_DR,
.vector = IO_GPIO_8B2_INT_INTR_FLAG,
.isr = gpio_8B_2_ISR,
.enableDebounce = IO_GPIO_8B2_DEBOUNCE },
#endif
#ifdef IO_GPIO_8B3_PRESENT
{ .instID = IO_GPIO_DEV_ID(3, 8),
.reg_base = AR_IO_GPIO_8B3_SWPORTA_DR,
.vector = IO_GPIO_8B3_INT_INTR_FLAG,
.isr = gpio_8B_3_ISR,
.enableDebounce = IO_GPIO_8B3_DEBOUNCE },
#endif
#ifdef IO_GPIO_4B0_PRESENT
{ .instID = IO_GPIO_DEV_ID(0, 4),
.reg_base = AR_IO_GPIO_4B0_SWPORTA_DR,
.vector = IO_GPIO_4B0_INT_INTR_FLAG,
.isr = gpio_4B_0_ISR,
.enableDebounce = IO_GPIO_4B0_DEBOUNCE },
#endif
#ifdef IO_GPIO_4B1_PRESENT
{ .instID = IO_GPIO_DEV_ID(1, 4),
.reg_base = AR_IO_GPIO_4B1_SWPORTA_DR,
.vector = IO_GPIO_4B1_INT_INTR_FLAG,
.isr = gpio_4B_1_ISR,
.enableDebounce = IO_GPIO_4B1_DEBOUNCE },
#endif
#ifdef IO_GPIO_4B2_PRESENT
{ .instID = IO_GPIO_DEV_ID(2, 4),
.reg_base = AR_IO_GPIO_4B2_SWPORTA_DR,
.vector = IO_GPIO_4B2_INT_INTR_FLAG,
.isr = gpio_4B_2_ISR,
.enableDebounce = IO_GPIO_4B2_DEBOUNCE },
#endif
#ifdef IO_GPIO_4B3_PRESENT
{ .instID = IO_GPIO_DEV_ID(3, 4),
.reg_base = AR_IO_GPIO_4B3_SWPORTA_DR,
.vector = IO_GPIO_4B3_INT_INTR_FLAG,
.isr = gpio_4B_3_ISR,
.enableDebounce = IO_GPIO_4B3_DEBOUNCE },
#endif
{ .instID = GPIO_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
uint32_t io_gpio_open(uint32_t dev_id)
{
uint32_t h = 0;
gpio_info_pt dev;
h = 0;
while ((gpio_devs[h].instID != dev_id)
&& (gpio_devs[h].instID != GPIO_MAX_CNT)) {
h++;
}
if ((gpio_devs[h].instID == GPIO_MAX_CNT) || (0 != gpio_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
gpio_handles[dev_id] = &gpio_devs[h];
dev = gpio_handles[dev_id];
dev->opened = 1;
/* enable the clock and enable synchronization */
REG_WRITE(CLKEN, 0x1);
REG_WRITE(LS_SYNC, 0x1);
_setvecti(dev->vector, dev->isr);
return 0;
}
void io_gpio_close(uint32_t dev_id)
{
gpio_info_pt dev = gpio_handles[dev_id];
REG_WRITE(INTEN, 0x0);
REG_WRITE(LS_SYNC, 0x0);
REG_WRITE(CLKEN, 0x0);
_setvecti(dev->vector, NULL);
dev->rx_cb = NULL;
dev->opened = 0;
gpio_handles[dev_id] = 0;
}
void io_gpio_read(uint32_t dev_id, uint32_t *data)
{
gpio_info_pt dev = gpio_handles[dev_id];
*data = REG_READ(EXT_PORTA);
}
void io_gpio_write(uint32_t dev_id, uint32_t data)
{
gpio_info_pt dev = gpio_handles[dev_id];
REG_WRITE(SWPORTA_DR, data);
}
void io_gpio_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
gpio_info_pt dev = gpio_handles[dev_id];
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_GPIO_SET_DIRECTION:
REG_WRITE(SWPORTA_DDR, *((uint32_t *) arg));
break;
case IO_GPIO_SET_INT_ENABLE:
REG_WRITE(INTEN, *((uint32_t *) arg));
break;
case IO_GPIO_GET_INT_ENABLE:
*((uint32_t *) arg) = REG_READ(INTEN);
break;
case IO_GPIO_SET_INT_MASK:
REG_WRITE(INTMASK, *((uint32_t *) arg));
break;
case IO_GPIO_GET_INT_MASK:
*((uint32_t *) arg) = REG_READ(INTMASK);
break;
case IO_GPIO_SET_INT_TYPE:
REG_WRITE(INTTYPE_LEVEL, *((uint32_t *) arg));
break;
case IO_GPIO_SET_INT_POLARITY:
REG_WRITE(INT_POLARITY, *((uint32_t *) arg));
break;
case IO_GPIO_SET_INT_BOTHEDGE:
REG_WRITE(INT_BOTHEDGE, *((uint32_t *) arg));
break;
case IO_GPIO_SET_DEBOUNCE:
if (dev->enableDebounce == 1) {
REG_WRITE(DEBOUNCE, *((uint32_t *) arg));
}
break;
case IO_GPIO_GET_DIRECTION:
*((uint32_t *) arg) = REG_READ(SWPORTA_DDR);
break;
case IO_GPIO_GET_GPO:
*((uint32_t *) arg) = REG_READ(SWPORTA_DR);
break;
default:
break;
}
}
static void gpio_ISR_proc(uint32_t dev_id)
{
gpio_info_pt dev = gpio_handles[dev_id];
uint32_t status = REG_READ(INTSTATUS);
if (!status) {
return; /* Spurious interrupts. */
}
if (_Usually(NULL != dev->rx_cb)) {
dev->rx_cb(status);
}
REG_WRITE(PORTA_EOI, status); /* clear status register. */
}
#endif

View File

@@ -1,210 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/* the wrapper of subsystem gpio driver */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "device/subsystem/gpio.h"
#include "device/subsystem/ss_gpio.h"
int32_t ss_gpio_open(SS_GPIO_DEV_CONTEXT *ctx, uint32_t dir)
{
DEV_GPIO_INFO *info = ctx->info;
int32_t ret = E_OK;
io_cb_t cb;
info->opn_cnt++;
if (info->opn_cnt > 1) { /* opened before */
if (dir == info->direction) { /* direction is the same */
return E_OK;
} else { /* open with different direction */
return E_OPNED;
}
}
if (io_gpio_open(ctx->dev_id)) {
return E_SYS;
}
info->direction = dir;
info->method = 0;
ctx->int_bit_type = 0;
ctx->int_bit_polarity = 0;
ctx->int_bit_debounce = 0;
cb.cb = (IO_CB_FUNC)ctx->int_cb;
io_gpio_ioctl(ctx->dev_id, IO_SET_CB_RX, &cb);
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_ENABLE, &info->method);
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_DIRECTION, &info->direction);
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_POLARITY, &ctx->int_bit_polarity);
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_DEBOUNCE, &ctx->int_bit_debounce);
int_enable(ctx->intno);
return ret;
}
int32_t ss_gpio_close(SS_GPIO_DEV_CONTEXT *ctx)
{
DEV_GPIO_INFO *info = ctx->info;
info->opn_cnt--;
if (info->opn_cnt == 0) {
io_gpio_close(ctx->dev_id);
int_disable(ctx->intno);
} else {
return E_OPNED;
}
return E_OK;
}
int32_t ss_gpio_control(SS_GPIO_DEV_CONTEXT *ctx, uint32_t ctrl_cmd, void *param)
{
int32_t ret = E_OK;
DEV_GPIO_INFO *info = ctx->info;
DEV_GPIO_INT_CFG *cfg = (DEV_GPIO_INT_CFG *)param;
DEV_GPIO_BIT_ISR *isr = (DEV_GPIO_BIT_ISR *)param;
uint32_t mask;
switch (ctrl_cmd) {
case GPIO_CMD_SET_BIT_DIR_INPUT:
case GPIO_CMD_SET_BIT_DIR_OUTPUT:
if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_OUTPUT) {
info->direction |= ((uint32_t)param);
} else {
info->direction &= ~((uint32_t)param);
}
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_DIRECTION, &(info->direction));
break;
case GPIO_CMD_GET_BIT_DIR:
*((uint32_t *) param) = info->direction;
break;
case GPIO_CMD_ENA_BIT_INT:
case GPIO_CMD_DIS_BIT_INT:
if (ctrl_cmd == GPIO_CMD_ENA_BIT_INT) {
info->method |= ((uint32_t)param);
} else {
info->method &= ~((uint32_t)param);
}
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_ENABLE, &(info->method));
if (info->method) {
int_enable(ctx->intno);
} else {
int_disable(ctx->intno);
}
break;
case GPIO_CMD_GET_BIT_MTHD:
io_gpio_ioctl(ctx->dev_id, IO_GPIO_GET_INT_ENABLE, &(info->method));
*((uint32_t *) param) = info->method;
break;
case GPIO_CMD_SET_BIT_INT_CFG:
mask = cfg->int_bit_mask;
ctx->int_bit_type &= ~(mask);
ctx->int_bit_type |= cfg->int_bit_type;
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_TYPE, &ctx->int_bit_type);
ctx->int_bit_polarity &= ~(mask);
ctx->int_bit_polarity |= cfg->int_bit_polarity;
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_POLARITY, &ctx->int_bit_polarity);
cfg->int_bit_debounce &= mask;
ctx->int_bit_debounce &= ~(mask);
ctx->int_bit_debounce |= cfg->int_bit_debounce;
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_DEBOUNCE, &ctx->int_bit_debounce);
break;
case GPIO_CMD_GET_BIT_INT_CFG:
cfg->int_bit_type = ctx->int_bit_type & cfg->int_bit_mask;
cfg->int_bit_polarity = ctx->int_bit_polarity & cfg->int_bit_mask;
cfg->int_bit_debounce = ctx->int_bit_debounce & cfg->int_bit_mask;
break;
case GPIO_CMD_SET_BIT_ISR:
if (isr->int_bit_ofs < ctx->width) {
ctx->handlers[isr->int_bit_ofs] = isr->int_bit_handler;
} else {
ret = E_PAR;
}
break;
case GPIO_CMD_GET_BIT_ISR:
if (isr->int_bit_ofs < ctx->width) {
isr->int_bit_handler = ctx->handlers[isr->int_bit_ofs];
} else {
ret = E_PAR;
}
break;
default:
ret = E_NOSPT;
break;
}
return ret;
}
int32_t ss_gpio_write(SS_GPIO_DEV_CONTEXT *ctx, uint32_t val, uint32_t mask)
{
uint32_t temp_val;
io_gpio_read(ctx->dev_id, &temp_val);
temp_val &= (~mask);
val &= mask;
io_gpio_write(ctx->dev_id, temp_val | val);
return 0;
}
int32_t ss_gpio_read(SS_GPIO_DEV_CONTEXT *ctx, uint32_t *val, uint32_t mask)
{
uint32_t raw;
io_gpio_read(ctx->dev_id, &raw);
*val = raw & mask;
return 0;
}
void ss_gpio_int_cb(SS_GPIO_DEV_CONTEXT *ctx, void *param)
{
DEV_GPIO_INFO *info = ctx->info;
uint32_t i;
for (i = 0; i < ctx->width; i++) {
if ((uint32_t)param & (1 << i) && ctx->handlers[i]) {
ctx->handlers[i](info);
}
}
}

View File

@@ -1,522 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include "device/subsystem/i2s_rx_master.h"
#include "io_config.h"
#include "apexextensions.h"
/* I2S Rx Master device registers */
#define I2S_IER 0x000
#define I2S_IRER 0x004
#define I2S_CER 0x00c
#define I2S_CCR 0x010
#define I2S_RXFFR 0x014
#define I2S_LRBR0 0x020
#define I2S_RRBR0 0x024
#define I2S_RER0 0x028
#define I2S_RCR0 0x030 // Receive configuration register
#define I2S_ISR0 0x038 // Interrupt status register
#define I2S_IMR0 0x03c // Interrupt mask register
#define I2S_ROR0 0x040
#define I2S_RFCR0 0x048
#define I2S_RFF0 0x050
#define I2S_RXDMA 0x1c0
/* I2S Rx Master device specific macros */
#define I2S_RX_MASTER_DMA_CTRL (0xa0000077) /* am=b10, i=b1, dw/inc=b011, dtt=b10, r=b1, op=b11 */
#define I2S_RX_MASTER_DMA_CTRL_SIZE_POS (8)
#define I2S_RX_MASTER_DMA_CTRL_XFER_POS (21)
#define DMA_NONE (0xff)
typedef _Interrupt void (*ISR) ();
typedef struct i2s_rx_master_info_struct {
/* I2S Rx master configuration settings */
const uint32_t reg_base; // base address of device register set
const uint8_t instID; // module instance ID
const uint16_t fifo_size; // FIFO depth
const uint16_t dmachanid; // DMA channel ID
/* I2S data buffer related fields */
uint32_t xfr_len; // number of samples transferred in current buffer
uint32_t xfr_started; // transfer started flag
uint32_t *buffer[2]; // two pointers to the user' buffers
uint32_t *bufsize[2]; // two sizes of user buffers
volatile uint32_t usr_cnt; // user' buffer access counter (incremented from read service)
volatile uint32_t sys_cnt; // system' buffer access counter (incremented from ISR)
#ifdef __Xdmac
_Uncached uint32_t *dmadescriptor; // pointer to the DMA descriptor location
#endif
/* User' callbacks */
IO_CB_FUNC rx_cb; // user' RX completion callback
IO_CB_FUNC err_cb; // user' error callback
/* Interrupt numbers and handlers */
const uint8_t rx_vector; // RX interrupt vector number
const uint8_t err_vector; // RX Error inetrrupt vector number
ISR rx_isr; // I2S data available interrupt handler
ISR err_isr; // I2S FIFO overrun interrupt handler
} i2s_rx_master_info_t, *i2s_rx_master_info_pt;
#ifdef IO_I2S_RX_MST0_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_RX_MST1_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_RX_MST2_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_RX_MST3_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_RX_MST4_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef I2S_RX_MASTER_DEV_PRESENT
#define I2S_RX_MASTER_MAX_CNT (4)
static void i2s_rx_master_rx_ISR_proc(uint32_t dev_id);
static void i2s_rx_master_err_ISR_proc(uint32_t dev_id);
#ifdef IO_I2S_RX_MST0_PRESENT
static _Interrupt void i2s_rx_master0_rx_ISR()
{
i2s_rx_master_rx_ISR_proc(0);
}
static _Interrupt void i2s_rx_master0_err_ISR()
{
i2s_rx_master_err_ISR_proc(0);
}
#endif
#ifdef IO_I2S_RX_MST1_PRESENT
static _Interrupt void i2s_rx_master1_rx_ISR()
{
i2s_rx_master_rx_ISR_proc(1);
}
static _Interrupt void i2s_rx_master1_err_ISR()
{
i2s_rx_master_err_ISR_proc(1);
}
#endif
#ifdef IO_I2S_RX_MST2_PRESENT
static _Interrupt void i2s_rx_master2_rx_ISR()
{
i2s_rx_master_rx_ISR_proc(2);
}
static _Interrupt void i2s_rx_master2_err_ISR()
{
i2s_rx_master_err_ISR_proc(2);
}
#endif
#ifdef IO_I2S_RX_MST3_PRESENT
static _Interrupt void i2s_rx_master3_rx_ISR()
{
i2s_rx_master_rx_ISR_proc(3);
}
static _Interrupt void i2s_rx_master3_err_ISR()
{
i2s_rx_master_err_ISR_proc(3);
}
#endif
/* I2S RX Master devices private data structures */
static i2s_rx_master_info_pt i2s_rx_master_handles[I2S_RX_MASTER_MAX_CNT] =
{ 0 };
#ifdef __Xdmac
static __attribute__ ((aligned(32)))
_Uncached uint32_t i2s_rx_master_dma_descriptors[8 *
I2S_RX_MASTER_MAX_CNT];
#endif
static i2s_rx_master_info_t i2s_rx_master_devs[] = {
#ifdef IO_I2S_RX_MST0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_I2S_RX_MST0_IER,
.rx_vector = IO_I2S_RX_MST0_INT_RX_AVAIL,
.err_vector = IO_I2S_RX_MST0_INT_ERR,
.rx_isr = i2s_rx_master0_rx_ISR,
.err_isr = i2s_rx_master0_err_ISR,
#ifdef IO_I2S_RX_MST0_DMA
.dmachanid = IO_I2S_RX_MST0_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_RX_MST0_FS },
#endif
#ifdef IO_I2S_RX_MST1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_I2S_RX_MST1_IER,
.rx_vector = IO_I2S_RX_MST1_INT_RX_AVAIL,
.err_vector = IO_I2S_RX_MST1_INT_ERR,
.rx_isr = i2s_rx_master1_rx_ISR,
.err_isr = i2s_rx_master1_err_ISR,
#ifdef IO_I2S_RX_MST1_DMA
.dmachanid = IO_I2S_RX_MST1_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_RX_MST1_FS },
#endif
#ifdef IO_I2S_RX_MST2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_I2S_RX_MST2_IER,
.rx_vector = IO_I2S_RX_MST2_INT_RX_AVAIL,
.err_vector = IO_I2S_RX_MST2_INT_ERR,
.rx_isr = i2s_rx_master2_rx_ISR,
.err_isr = i2s_rx_master2_err_ISR,
#ifdef IO_I2S_RX_MST2_DMA
.dmachanid = IO_I2S_RX_MST2_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_RX_MST2_FS },
#endif
#ifdef IO_I2S_RX_MST3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_I2S_RX_MST3_IER,
.rx_vector = IO_I2S_RX_MST3_INT_RX_AVAIL,
.err_vector = IO_I2S_RX_MST3_INT_ERR,
.rx_isr = i2s_rx_master3_rx_ISR,
.err_isr = i2s_rx_master3_err_ISR,
#ifdef IO_I2S_RX_MST3_DMA
.dmachanid = IO_I2S_RX_MST3_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_RX_MST3_FS },
#endif
{ .instID = I2S_RX_MASTER_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((uint32_t)((x)), (uint32_t)(dev->reg_base + reg))
#define REG_READ(reg) _lr((uint32_t)(dev->reg_base + (reg)))
/* API functions */
uint32_t io_i2s_rx_master_open(uint32_t dev_id)
{
i2s_rx_master_info_pt dev;
uint32_t h = 0;
/* check device descriptor availability */
while ((i2s_rx_master_devs[h].instID != dev_id)
&& (i2s_rx_master_devs[h].instID != I2S_RX_MASTER_MAX_CNT)) {
h++;
}
if ((i2s_rx_master_devs[h].instID == I2S_RX_MASTER_MAX_CNT) || (0 != i2s_rx_master_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
i2s_rx_master_handles[dev_id] = &i2s_rx_master_devs[h];
dev = i2s_rx_master_handles[dev_id];
/* initialize driver internal variables */
dev->xfr_started = 0; // clear transfer started flag
dev->xfr_len = 0; // clear transfer length
dev->usr_cnt = dev->sys_cnt = 0; // reset buffer access counters
#ifdef __Xdmac
/* initialize DMA descriptors */
dev->dmadescriptor = &i2s_rx_master_dma_descriptors[8 * h];
if (dev->dmachanid != DMA_NONE) {
dev->dmadescriptor[0] = dev->dmadescriptor[4] = 0;
dev->dmadescriptor[1] = dev->dmadescriptor[5] =
dev->reg_base + I2S_RXDMA;
dev->dmadescriptor[2] = dev->dmadescriptor[6] = 0;
dev->dmadescriptor[3] = (uint32_t) &(dev->dmadescriptor[4]);
dev->dmadescriptor[7] = (uint32_t) &(dev->dmadescriptor[0]);
/* assign DMA interrupt handlers */
_setvecti(dev->err_vector, dev->err_isr);
_setvecti(DMAC_INT_BASE + dev->dmachanid, dev->rx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmachanid, dev->err_isr);
} else {
#endif
/* assign non DMA interrupt handlers */
_setvecti(dev->rx_vector, dev->rx_isr);
_setvecti(dev->err_vector, dev->err_isr);
#ifdef __Xdmac
}
#endif
REG_WRITE(I2S_IER, 0x01); // I2S: enable device
return (0);
}
void io_i2s_rx_master_close(uint32_t dev_id)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
/* reset I2S hardware */
REG_WRITE(I2S_IMR0, 0x03); // mask RX interrupts
REG_WRITE(I2S_RER0, 0x01); // reset channel enable to default (1)
REG_WRITE(I2S_CER, 0x00); // disable clk
REG_WRITE(I2S_IRER, 0x00); // disable receive block
REG_WRITE(I2S_RCR0, 0x02); // reset wlen to default (2)
REG_WRITE(I2S_RFCR0, 0x00); // reset threshold
REG_WRITE(I2S_IER, 0x00); // disable device and flushes fifo
#ifdef __Xdmac
/* reset DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 0); // aux-DMA channel reset bug fix
_dma_chan_reset(0x1 << dev->dmachanid);
/* deinitialize DMA interrupt handlers */
_setvecti(DMAC_INT_BASE + dev->dmachanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmachanid, NULL);
#endif
/* deinitialize non DMA interrupt handlers */
_setvecti(dev->rx_vector, NULL);
_setvecti(dev->err_vector, NULL);
/* reset driver internal variables */
dev->rx_cb = NULL;
dev->err_cb = NULL;
dev->xfr_started = 0;
/* reset device handler */
i2s_rx_master_handles[dev_id] = 0;
}
void io_i2s_rx_master_read(uint32_t dev_id, uint32_t *data,
uint32_t *size)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
uint32_t idx = dev->usr_cnt; // copy user access counter to the temporary variable
if (((idx - dev->sys_cnt) != 2) && (*size != 0)) {
idx = idx & 0x0001; // current index in dev->buffer[] & dev->bufsize[]
#ifdef __Xdmac
if (dev->dmachanid != DMA_NONE) {
uint32_t burst_size = (REG_READ(I2S_RFCR0) + 1) << 1; // actual FIFO trigger level
uint32_t xfer_size = (*size) << 2; // transfer size in bytes (ToDo: limited by 8KB)
idx = idx << 2; // calculate available buffer' index
/* DMA: update DMACTRL and DMADAR part of descriptor */
dev->dmadescriptor[idx + 0] =
I2S_RX_MASTER_DMA_CTRL |
(burst_size << I2S_RX_MASTER_DMA_CTRL_XFER_POS) |
((xfer_size - 1) << I2S_RX_MASTER_DMA_CTRL_SIZE_POS);
dev->dmadescriptor[idx + 2] = (uint32_t) data + xfer_size - 2;
if (dev->xfr_started == 0) { /* I2S transfer not yet started -> init DMA and I2S Rx */
dev->xfr_started = 1;
REG_WRITE(I2S_RXFFR, 0x01); // I2S: reset RX FIFO
REG_WRITE(I2S_RFF0, 0x01); // I2S: flush RX FIFO
REG_WRITE(I2S_CER, 0x01); // I2S: start the clock
REG_WRITE(I2S_IRER, 0x01); // I2S: enable receive block
REG_WRITE(I2S_IMR0, ~0x02); // I2S: Unmask RX overrun interrupt
if (dev->dmachanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmachanid, &(dev->dmadescriptor[0])); // dev->dmaidx must be 0 !!!
} else {
_dma_chan_desc_aux(dev->dmachanid, &(dev->dmadescriptor[0])); // dev->dmaidx must be 0 !!!
}
/* Start DMA channel / renew descriptor */
_dma_chan_enable((0x1 << dev->dmachanid), 1);
}
} else {
#endif /* __Xdmac */
/* Update data buffer parameters */
dev->buffer[idx] = data;
dev->bufsize[idx] = size;
if (dev->xfr_started == 0) { /* I2S transfer not yet started -> init I2S Rx */
dev->xfr_started = 1;
/* Start I2S non DMA interrupt flow */
REG_WRITE(I2S_RXFFR, 0x01); // I2S: reset RX FIFO
REG_WRITE(I2S_RFF0, 0x01); // I2S: flush RX FIFO
REG_WRITE(I2S_CER, 0x01); // I2S: start the clock
REG_WRITE(I2S_IRER, 0x01); // I2S: enable receive block
REG_WRITE(I2S_IMR0, ~0x03); // I2S: Unmask all RX interrupts
}
#ifdef __Xdmac
}
#endif /* __Xdmac */
dev->usr_cnt++; // update user' buffer access counter
}
}
void io_i2s_rx_master_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
case IO_I2S_RX_MASTER_SET_SAMPLE_WIDTH:
/* channel must be disabled before programming I2S_RCR0 */
REG_WRITE(I2S_RCR0, (*(uint32_t *) arg));
break;
case IO_I2S_RX_MASTER_SET_FIFO_THRESHOLD:
/* channel must be disabled before programming I2S_RFCR0 */
REG_WRITE(I2S_RFCR0, (*(uint32_t *) arg));
break;
case IO_I2S_RX_MASTER_SET_BITCLOCK:
REG_WRITE(I2S_CER, *((uint32_t *) arg));
break;
default:
break;
}
}
static uint32_t i2s_rx_master_read_samples(uint32_t dev_id,
uint32_t *count)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
uint32_t free_cnt = 0;
if (dev->usr_cnt == dev->sys_cnt) { /* no more data buffer available (buffer underflow error) */
/* if no buffer will be available until FIFO is full then error callback will be called from error ISR */
return (1);
} else {
uint32_t idx = dev->sys_cnt & 0x0001;
uint32_t *buff = dev->buffer[idx];
uint32_t *size = dev->bufsize[idx];
free_cnt = (*size - dev->xfr_len);
if (*count <= free_cnt) { /* enough space in buffer[0] */
free_cnt = *count;
*count = 0;
} else { /* *count > free_cnt: there will be samples remaining for the next buffer */
*count -= free_cnt;
}
/* fill current buffer */
for (int32_t i = 0; i != free_cnt; i++) {
buff[dev->xfr_len + i] = REG_READ(I2S_LRBR0);
buff[dev->xfr_len + i] |= (REG_READ(I2S_RRBR0) << 16);
}
dev->xfr_len += free_cnt;
/* if current buffer is full: rx callback, and increment system counter */
if (dev->xfr_len == *size) {
dev->sys_cnt++;
dev->xfr_len = 0;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
}
return (0);
}
/* I2S RX data available interrupt handler */
static void i2s_rx_master_rx_ISR_proc(uint32_t dev_id)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
uint32_t sample_cnt = 0;
uint32_t error = 0;
/* Rx FIFO trigger level reached - data available interrupt */
#ifdef __Xdmac
if (dev->dmachanid == DMA_NONE) { /* DMA either disabled or does not exist */
#endif /* __Xdmac */
sample_cnt = REG_READ(I2S_RFCR0) + 1; // actual FIFO trigger level
while (sample_cnt != 0) {
error = i2s_rx_master_read_samples(dev_id, &sample_cnt);
if (error != 0) { /* buffer underrun - no user' buffer left to receive data */
REG_WRITE(I2S_IMR0, 0x0001); // I2S: mask RXDA interrupt
break;
}
}
#ifdef __Xdmac
} else { /* DMA enabled for I2S peripheral */
if (++dev->sys_cnt == dev->usr_cnt) { /* no data buffers left - disable dma channel and mask data available interrupt */
_dma_chan_enable((0x1 << dev->dmachanid), 0);
} else {
// update channel descriptor
_dma_chan_enable((0x1 << dev->dmachanid), 1);
}
if (NULL != dev->rx_cb) { /* call for Rx callback if any */
dev->rx_cb(dev_id);
}
_dma_int_clear((0x1 << dev->dmachanid)); // clear DMA interrupt flag
}
#endif /* __Xdmac */
}
/* I2S RX error (FIFO overflow) interrupt handler */
static void i2s_rx_master_err_ISR_proc(uint32_t dev_id)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
/* Rx FIFO overrun case */
#ifdef __Xdmac
if (dev->dmachanid != DMA_NONE) {
/* DMA: disable DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 0);
_dma_int_clear((0x1 << dev->dmachanid));
}
#endif
/* I2S: stop I2S device */
REG_WRITE(I2S_IMR0, 0x03); // I2S: mask RX interrupts
REG_WRITE(I2S_CER, 0x00); // I2S: disable clk
REG_WRITE(I2S_IER, 0x00); // I2S: disable device
/* call error callback if any */
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
}
#endif

View File

@@ -1,531 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include "device/subsystem/i2s_tx_master.h"
#include "io_config.h"
#include "apexextensions.h"
/* I2S Tx Master device registers */
#define I2S_IER 0x000
#define I2S_ITER 0x008
#define I2S_CER 0x00c
#define I2S_CCR 0x010
#define I2S_TXFFR 0x018
#define I2S_LTHR 0x020
#define I2S_RTHR 0x024
#define I2S_TER 0x02C
#define I2S_TCR 0x034 // Transmit configuration register
#define I2S_ISR 0x038 // Interrupt status register
#define I2S_IMR 0x03c // Interrupt mask register
#define I2S_TOR 0x044
#define I2S_TFCR 0x04c
#define I2S_TFF 0x054
#define I2S_TXDMA 0x1c8
/* I2S Tx Master device specific macros */
#define I2S_TX_MASTER_DMA_CTRL (0x6000006F) /* am=b01, i=b1, dw/inc=b011, dtt=b01, r=b1, op=b11 */
#define I2S_TX_MASTER_DMA_CTRL_SIZE_POS (8)
#define I2S_TX_MASTER_DMA_CTRL_XFER_POS (21)
#define DMA_NONE (0xff)
typedef _Interrupt void (*ISR) ();
typedef struct i2s_tx_master_info_struct {
/* I2S peripheral configuration values */
const uint32_t reg_base; // base address of device register set
const uint8_t instID; // I2S module instance ID
const uint16_t fifo_size; // FIFO depth
const uint16_t dmachanid; // DMA channel ID
/* I2S data buffer related fields */
uint32_t xfr_len; // number of transferred samples in current buffer
uint32_t xfr_started; // I2S transfer started flag (used for nonDMA xfer)
uint32_t *buffer[2]; // two pointers to the user data buffers
uint32_t *bufsize[2]; // two pointers to the user data buffer sizes
volatile uint32_t sys_cnt; // read access buffer counter (incremented by ISR)
volatile uint32_t usr_cnt; // write access buffer counter (incremented from write service)
#ifdef __Xdmac
_Uncached uint32_t *dmadescriptor; // pointer to DMA descriptors location
#endif
/* User callbacks */
IO_CB_FUNC tx_cb; // user' TX completion callback
IO_CB_FUNC err_cb; // user' error callback
/* Interrupt numbers and handlers */
const uint8_t tx_vector; // TX interrupt vector number
const uint8_t err_vector; // Error interrupt vector number
ISR tx_isr; // I2S data available ISRs
ISR err_isr; // I2S FIFO overrun ISRs
} i2s_tx_master_info_t, *i2s_tx_master_info_pt;
#ifdef IO_I2S_TX_MST0_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_TX_MST1_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_TX_MST2_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_TX_MST3_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_TX_MST4_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef I2S_TX_MASTER_DEV_PRESENT
#define I2S_TX_MASTER_MAX_CNT (4)
static void i2s_tx_master_tx_ISR_proc(uint32_t dev_id);
static void i2s_tx_master_err_ISR_proc(uint32_t dev_id);
#ifdef IO_I2S_TX_MST0_PRESENT
static _Interrupt void i2s_tx_master0_tx_ISR()
{
i2s_tx_master_tx_ISR_proc(0);
}
static _Interrupt void i2s_tx_master0_err_ISR()
{
i2s_tx_master_err_ISR_proc(0);
}
#endif
#ifdef IO_I2S_TX_MST1_PRESENT
static _Interrupt void i2s_tx_master1_tx_ISR()
{
i2s_tx_master_tx_ISR_proc(1);
}
static _Interrupt void i2s_tx_master1_err_ISR()
{
i2s_tx_master_err_ISR_proc(1);
}
#endif
#ifdef IO_I2S_TX_MST2_PRESENT
static _Interrupt void i2s_tx_master2_tx_ISR()
{
i2s_tx_master_tx_ISR_proc(2);
}
static _Interrupt void i2s_tx_master2_err_ISR()
{
i2s_tx_master_err_ISR_proc(2);
}
#endif
#ifdef IO_I2S_TX_MST3_PRESENT
static _Interrupt void i2s_tx_master3_tx_ISR()
{
i2s_tx_master_tx_ISR_proc(3);
}
static _Interrupt void i2s_tx_master3_err_ISR()
{
i2s_tx_master_err_ISR_proc(3);
}
#endif
/* I2S TX Master devices private data structures */
static i2s_tx_master_info_pt i2s_tx_master_handles[I2S_TX_MASTER_MAX_CNT] =
{ 0 };
#ifdef __Xdmac
static __attribute__ ((aligned(32)))
_Uncached uint32_t i2s_tx_master_dma_descriptors[8 *
I2S_TX_MASTER_MAX_CNT];
#endif
static i2s_tx_master_info_t i2s_tx_master_devs[] = {
#ifdef IO_I2S_TX_MST0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_I2S_TX_MST0_IER,
.tx_vector = IO_I2S_TX_MST0_INT_TX_REQ,
.err_vector = IO_I2S_TX_MST0_INT_ERR,
.tx_isr = i2s_tx_master0_tx_ISR,
.err_isr = i2s_tx_master0_err_ISR,
#ifdef IO_I2S_TX_MST0_DMA
.dmachanid = IO_I2S_TX_MST0_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_TX_MST0_FS },
#endif
#ifdef IO_I2S_TX_MST1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_I2S_TX_MST1_IER,
.tx_vector = IO_I2S_TX_MST1_INT_TX_REQ,
.err_vector = IO_I2S_TX_MST1_INT_ERR,
.tx_isr = i2s_tx_master1_tx_ISR,
.err_isr = i2s_tx_master1_err_ISR,
#ifdef IO_I2S_TX_MST1_DMA
.dmachanid = IO_I2S_TX_MST1_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_TX_MST1_FS },
#endif
#ifdef IO_I2S_TX_MST2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_I2S_TX_MST2_IER,
.tx_vector = IO_I2S_TX_MST2_INT_TX_REQ,
.err_vector = IO_I2S_TX_MST2_INT_ERR,
.tx_isr = i2s_tx_master2_tx_ISR,
.err_isr = i2s_tx_master2_err_ISR,
#ifdef IO_I2S_TX_MST2_DMA
.dmachanid = IO_I2S_TX_MST2_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_TX_MST2_FS },
#endif
#ifdef IO_I2S_TX_MST3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_I2S_TX_MST3_IER,
.tx_vector = IO_I2S_TX_MST3_INT_TX_REQ,
.err_vector = IO_I2S_TX_MST3_INT_ERR,
.tx_isr = i2s_tx_master3_tx_ISR,
.err_isr = i2s_tx_master3_err_ISR,
#ifdef IO_I2S_TX_MST3_DMA
.dmachanid = IO_I2S_TX_MST3_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_TX_MST3_FS },
#endif
{ .instID = I2S_TX_MASTER_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((uint32_t)((x)), (uint32_t)(dev->reg_base + reg))
#define REG_READ(reg) _lr((uint32_t)(dev->reg_base + (reg)))
/* API functions */
uint32_t io_i2s_tx_master_open(uint32_t dev_id)
{
i2s_tx_master_info_pt dev;
uint32_t h = 0;
/* check device descriptor availability */
while ((i2s_tx_master_devs[h].instID != dev_id)
&& (i2s_tx_master_devs[h].instID != I2S_TX_MASTER_MAX_CNT)) {
h++;
}
if ((i2s_tx_master_devs[h].instID == I2S_TX_MASTER_MAX_CNT) || (0 != i2s_tx_master_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
i2s_tx_master_handles[dev_id] = &i2s_tx_master_devs[h];
dev = i2s_tx_master_handles[dev_id];
dev->xfr_started = 0; // clear transfer started flag
dev->xfr_len = 0; // clear transfer lenght
dev->sys_cnt = dev->usr_cnt = 0; // reset buffer' access counters
#ifdef __Xdmac
/* initialize DMA descriptors */
dev->dmadescriptor = &i2s_tx_master_dma_descriptors[8 * h];
if (dev->dmachanid != DMA_NONE) {
dev->dmadescriptor[0] = dev->dmadescriptor[4] = 0;
dev->dmadescriptor[1] = dev->dmadescriptor[5] = 0;
dev->dmadescriptor[2] = dev->dmadescriptor[6] =
dev->reg_base + I2S_TXDMA;
dev->dmadescriptor[3] = (uint32_t) &(dev->dmadescriptor[4]);
dev->dmadescriptor[7] = (uint32_t) &(dev->dmadescriptor[0]);
/* assign DMA interrupt vectors */
_setvecti(dev->err_vector, dev->err_isr);
_setvecti(DMAC_INT_BASE + dev->dmachanid, dev->tx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmachanid, dev->err_isr);
} else {
#endif
_setvecti(dev->tx_vector, dev->tx_isr);
_setvecti(dev->err_vector, dev->err_isr);
#ifdef __Xdmac
}
#endif
REG_WRITE(I2S_IER, 0x01); // I2S: enable device
return (0);
}
void io_i2s_tx_master_close(uint32_t dev_id)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
/* put I2S registers into "after reset" state */
REG_WRITE(I2S_IMR, 0x30); // mask TX interrupts
REG_WRITE(I2S_TER, 0x00); // disable channel
REG_WRITE(I2S_TFCR, 0x00); // reset threshold to default (0)
REG_WRITE(I2S_TCR, 0x02); // reset wlen to default (2)
REG_WRITE(I2S_TER, 0x01); // reset channel enable to default (1)
REG_WRITE(I2S_CER, 0x00); // disable clk
REG_WRITE(I2S_ITER, 0x00); // disable receive block
REG_WRITE(I2S_IER, 0x00); // disable device and flushes fifo
#ifdef __Xdmac
/* reset DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 0); // aux-DMA channel reset bug fix
_dma_chan_reset(0x1 << dev->dmachanid);
/* deinitialize DMA interrupt handlers */
_setvecti(DMAC_INT_BASE + dev->dmachanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmachanid, NULL);
#endif
/* deinitialize non DMA interrupt handlers */
_setvecti(dev->tx_vector, NULL);
_setvecti(dev->err_vector, NULL);
/* clear driver internal variables */
dev->tx_cb = NULL;
dev->err_cb = NULL;
dev->xfr_started = 0;
/* reset device handler */
i2s_tx_master_handles[dev_id] = 0;
}
void io_i2s_tx_master_write(uint32_t dev_id, uint32_t *data,
uint32_t *size)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
uint32_t idx = dev->usr_cnt;
if (((idx - dev->sys_cnt) != 2) && (*size != 0)) {
idx = idx & 0x0001; // current index in dev->buffer[] & dev->bufsize[]
#ifdef __Xdmac
if (dev->dmachanid != DMA_NONE) {
uint32_t burst_size = (dev->fifo_size - REG_READ(I2S_TFCR)) << 1; // actual FIFO trigger level
uint32_t xfer_size = (*size) << 2; // transfer size in bytes (ToDo: limited by 8KB)
idx = idx << 2; // now this is index in the array of DMA descriptors
/* DMA: update DMACTRL and DMASAR part of descriptor */
dev->dmadescriptor[idx + 0] =
I2S_TX_MASTER_DMA_CTRL |
(burst_size << I2S_TX_MASTER_DMA_CTRL_XFER_POS) |
((xfer_size - 1) << I2S_TX_MASTER_DMA_CTRL_SIZE_POS);
dev->dmadescriptor[idx + 1] = (uint32_t) data + xfer_size - 2;
dev->usr_cnt++; // update user' buffer access counter;
/* init DMA if required */
if (dev->xfr_started == 0) { /* I2S transfer is not yet started -> init I2S Tx and DMA channel */
dev->xfr_started = 1;
REG_WRITE(I2S_TXFFR, 0x01); // I2S: reset TX FIFO
REG_WRITE(I2S_TFF, 0x01); // I2S: flush TX FIFO
REG_WRITE(I2S_CER, 0x01); // I2S: start the clock
REG_WRITE(I2S_ITER, 0x01); // I2S: enable transmitter block
REG_WRITE(I2S_IMR, ~0x20); // I2S: Unmask TX FIFO write overrun interrupts
if (dev->dmachanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmachanid,
&(dev->dmadescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmachanid,
&(dev->dmadescriptor[0]));
}
/* Start DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 1);
}
} else {
#endif /* __Xdmac */
/* Store data buffer parameters */
dev->buffer[idx] = data;
dev->bufsize[idx] = size;
dev->usr_cnt++; // update user' buffer access counter;
if (dev->xfr_started == 0) { /* I2S transfer not yet started -> init I2S Rx */
dev->xfr_started = 1;
REG_WRITE(I2S_TXFFR, 0x01); // I2S: reset TX FIFO
REG_WRITE(I2S_TFF, 0x01); // I2S: flush TX FIFO
REG_WRITE(I2S_CER, 0x01); // I2S: start the clock
REG_WRITE(I2S_ITER, 0x01); // I2S: enable transmitter block
REG_WRITE(I2S_IMR, ~0x30); // I2S: Unmask TX interrupts
}
#ifdef __Xdmac
}
#endif /* __Xdmac */
}
}
void io_i2s_tx_master_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
switch (cmd) {
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
case IO_I2S_TX_MASTER_SET_SAMPLE_WIDTH:
/* channel must be disabled before programming I2S_TCR */
REG_WRITE(I2S_TCR, (*(uint32_t *) arg));
break;
case IO_I2S_TX_MASTER_SET_FIFO_THRESHOLD:
/* channel must be disabled before programming I2S_TFCR */
REG_WRITE(I2S_TFCR, (*(uint32_t *) arg));
break;
case IO_I2S_TX_MASTER_SET_BITCLOCK:
REG_WRITE(I2S_CER, *((uint32_t *) arg));
break;
default:
break;
}
}
static uint32_t i2s_tx_master_write_samples(uint32_t dev_id,
uint32_t *count)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
uint32_t avail_cnt = 0;
if (dev->sys_cnt == dev->usr_cnt) { /* no more data buffer available (buffer underflow error) */
/* if no buffer will be available until FIFO is full then error callback will be called from error ISR */
return (1);
} else {
uint32_t idx = dev->sys_cnt & 0x0001;
uint32_t *buff = dev->buffer[idx];
uint32_t *size = dev->bufsize[idx];
avail_cnt = (*size - dev->xfr_len);
if (*count <= avail_cnt) { /* enough space in current buffer */
avail_cnt = *count;
*count = 0;
} else { /* *count > avail_cnt: there will be samples remaining for the next buffer */
*count -= avail_cnt;
}
/* fill current buffer */
for (int32_t i = 0; i != avail_cnt; i++) {
REG_WRITE(I2S_LTHR, buff[dev->xfr_len + i]);
REG_WRITE(I2S_RTHR, buff[dev->xfr_len + i] >> 16);
}
dev->xfr_len += avail_cnt;
/* if current buffer is full: call user' callback, and increment read access counter */
if (dev->xfr_len == *size) {
dev->sys_cnt++;
dev->xfr_len = 0;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
}
}
return (0);
}
/* I2S TX data available interrupt handler */
static void i2s_tx_master_tx_ISR_proc(uint32_t dev_id)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
uint32_t sample_cnt = 0;
uint32_t error = 0;
/* Tx FIFO trigger level reached - data available interrupt */
#ifdef __Xdmac
if (dev->dmachanid == DMA_NONE) { /* DMA either disabled or does not exist */
#endif /* __Xdmac */
sample_cnt = dev->fifo_size;
if (dev->xfr_started == 0) {
dev->xfr_started = 1;
} else {
sample_cnt -= REG_READ(I2S_TFCR); // available data space in FIFO
}
while (sample_cnt != 0) {
error = i2s_tx_master_write_samples(dev_id, &sample_cnt);
if (error != 0) { /* buffer underrun - no user' buffer left to receive data */
REG_WRITE(I2S_IMR, 0x10); // I2S: mask TXFE interrupt
break;
}
}
#ifdef __Xdmac
} else { /* DMA enabled for I2S peripheral */
if (++dev->sys_cnt == dev->usr_cnt) { /* no data buffers left - disable dma channel and mask data available interrupt */
_dma_chan_enable((0x1 << dev->dmachanid), 0);
} else {
// update buffer descriptor
_dma_chan_enable((0x1 << dev->dmachanid), 1);
}
if (NULL != dev->tx_cb) { /* call for Tx callback if any */
dev->tx_cb(dev_id);
}
_dma_int_clear(0x1 << dev->dmachanid); // clear DMA interrupt flag
}
#endif /* __Xdmac */
}
/* I2S TX error (FIFO overflow) interrupt handler */
static void i2s_tx_master_err_ISR_proc(uint32_t dev_id)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
/* Tx FIFO overrun case */
#ifdef __Xdmac
if (dev->dmachanid != DMA_NONE) {
/* DMA: disable DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 0);
_dma_int_clear((0x1 << dev->dmachanid));
}
#endif
/* I2S: stop I2S device */
REG_WRITE(I2S_IMR, 0x30); // I2S: mask TX interrupts
REG_WRITE(I2S_CER, 0x00); // I2S: disable clk
REG_WRITE(I2S_IER, 0x00); // I2S: disable device
/* call error callback if any */
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
}
#endif

View File

@@ -1,345 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/* the wrapper of subsystem i2s master driver */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "device/subsystem/i2s_rx_master.h"
#include "device/subsystem/i2s_tx_master.h"
#include "device/subsystem/ss_i2s_master.h"
/** check expressions used in DFSS I2S driver implementation */
#define SS_I2S_MASTER_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
/* I2S Master device registers */
#define I2S_IER 0x000 /*!< (0x000) : Enable Register */
#define I2S_IRER 0x004 /*!< (0x004) : I2S Receiver Block Enable Register */
#define I2S_ITER 0x008
#define I2S_CER 0x00c /*!< (0x00C) : Clock Enable Register */
#define I2S_CCR 0x010 /*!< (0x010) : Clock Configuration Register */
#define I2S_RXFFR 0x014 /*!< (0x014) : Receiver Block FIFO Register */
#define I2S_TXFFR 0x018
#define I2S_LTHR0 0x020 /*!< (0x020) : Left Transmit Holding Register 0 */
#define I2S_RTHR0 0x024 /*!< (0x024) : Right Transmit Holding Register 0 */
#define I2S_RER0 0x028 /*!< (0x028) : Receive Enable Register 0 */
#define I2S_TER0 0x02C
#define I2S_RCR0 0x030 /*!< (0x030) : Receive Configuration Register 0 */
#define I2S_TCR0 0x034
#define I2S_ISR0 0x038 /*!< (0x038) : Interrupt Status Register 0 */
#define I2S_IMR0 0x03c /*!< (0x03C) : Interrupt Mask Register 0 */
#define I2S_ROR0 0x040 /*!< (0x040) : Receive Overrun Register 0 */
#define I2S_TOR0 0x044
#define I2S_RFCR0 0x048 /*!< (0x048) : Receive FIFO Configuration Register 0 */
#define I2S_RFF0 0x050 /*!< (0x050) : Receive FIFO Flush 0 */
#define I2S_TFF0 0x054
#define I2S_RXDMA 0x1c0 /*!< (0x1C0) : Receiver Block DMA Register */
#define I2S_TXDMA 0x1c8
#define REG_READ(x) arc_aux_read((ctx->reg_base + x))
#define REG_WRITE(x, y) arc_aux_write((ctx->reg_base + x), y)
static void ss_i2s_master_reset(SS_I2S_MST_DEV_CONTEXT *ctx)
{
}
static void ss_i2s_master_flush_tx(SS_I2S_MST_DEV_CONTEXT *ctx)
{
}
static void ss_i2s_master_flush_rx(SS_I2S_MST_DEV_CONTEXT *ctx)
{
}
static void ss_i2s_master_enable(SS_I2S_MST_DEV_CONTEXT *ctx)
{
// enable device
REG_WRITE(I2S_IER, 1);
}
static void ss_i2s_master_disable(SS_I2S_MST_DEV_CONTEXT *ctx)
{
// disable device
REG_WRITE(I2S_IER, 0);
}
int32_t ss_i2s_mst_open(SS_I2S_MST_DEV_CONTEXT *ctx, uint32_t mode, uint32_t param)
{
uint32_t dev_id = ctx->dev_id;
uint8_t io_mode = ctx->io_mode;
DEV_I2S_INFO_PTR info = ctx->info;
io_cb_t callback;
int32_t int_e = 0;
if (mode != DEV_MASTER_MODE) {
return E_PAR;
}
if (info->opn_cnt > 0) {
info->opn_cnt++;
return E_OPNED;
}
info->opn_cnt++;
if (io_mode == SS_I2S_RX) {
if (io_i2s_rx_master_open(dev_id)) {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->int_rx_cb;
int_e = int_e | int_enable(ctx->int_rx_avil);
int_e = int_e | int_enable(ctx->int_rx_err);
io_i2s_rx_master_ioctl(dev_id, IO_SET_CB_RX, &callback);
} else if (io_mode == SS_I2S_TX) {
if (io_i2s_tx_master_open(dev_id)) {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->int_tx_cb;
io_i2s_tx_master_ioctl(dev_id, IO_SET_CB_TX, &callback);
int_e = int_e | int_enable(ctx->int_tx_req);
int_e = int_e | int_enable(ctx->int_tx_err);
} else {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->int_err_cb;
io_i2s_tx_master_ioctl(dev_id, IO_SET_CB_ERR, &callback);
if (int_e != 0) {
return E_PAR;
}
return E_OK;
}
int32_t ss_i2s_mst_close(SS_I2S_MST_DEV_CONTEXT *ctx)
{
DEV_I2S_INFO_PTR info = ctx->info;
uint8_t io_mode = ctx->io_mode;
info->opn_cnt--;
if (info->opn_cnt == 0) {
if (io_mode == SS_I2S_RX) {
int_disable(ctx->int_rx_avil);
int_disable(ctx->int_rx_err);
io_i2s_rx_master_close(ctx->dev_id);
} else if (io_mode == SS_I2S_TX) {
int_disable(ctx->int_tx_req);
int_disable(ctx->int_tx_err);
io_i2s_tx_master_close(ctx->dev_id);
} else {
return E_SYS;
}
info->opn_cnt = 0;
info->status = DEV_DISABLED;
ctx->flags = 0;
} else {
return E_OPNED;
}
return E_OK;
}
int32_t ss_i2s_mst_read(SS_I2S_MST_DEV_CONTEXT *ctx, void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
uint8_t io_mode = ctx->io_mode;
uint32_t rd_len = len;
if (ctx->flags) {
return E_NORES;
}
if (io_mode == SS_I2S_TX) {
return E_OBJ;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* because the bottom driver is simply interrupt driven
*/
return E_SYS;
}
ctx->flags = SS_I2S_MASTER_FLAG_RX;
io_i2s_rx_master_read(dev_id, data, &rd_len);
/* wait finished: i2s master int enable & no cpu lock */
while (ctx->flags & SS_I2S_MASTER_FLAG_RX) {
;
}
if (ctx->flags & SS_I2S_MASTER_FLAG_RX_ERROR) {
ctx->flags = 0;
return E_SYS;
}
return rd_len;
}
int32_t ss_i2s_mst_write(SS_I2S_MST_DEV_CONTEXT *ctx, void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
uint8_t io_mode = ctx->io_mode;
uint32_t wt_len = len;
if (ctx->flags) {
return E_NORES;
}
if (io_mode == SS_I2S_RX) {
return E_OBJ;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* because the bottom driver is simply interrupt driven
*/
return E_SYS;
}
ctx->flags = SS_I2S_MASTER_FLAG_TX;
io_i2s_tx_master_write(dev_id, data, &wt_len);
/* wait finished: i2s master int enable & no cpu lock */
while (ctx->flags & SS_I2S_MASTER_FLAG_TX) {
;
}
if (ctx->flags & SS_I2S_MASTER_FLAG_TX_ERROR) {
ctx->flags = 0;
return E_SYS;
}
return wt_len;
}
int32_t ss_i2s_mst_control(SS_I2S_MST_DEV_CONTEXT *ctx, uint32_t cmd, void *param)
{
uint32_t dev_id = ctx->dev_id;
uint8_t io_mode = ctx->io_mode;
DEV_I2S_INFO_PTR info = ctx->info;
int32_t ercd = E_OK;
io_i2s_rx_master_ioctl(dev_id, cmd, param);
io_i2s_tx_master_ioctl(dev_id, cmd, param);
switch (cmd) {
case I2S_CMD_GET_STATUS:
SS_I2S_MASTER_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = info->status;
break;
case I2S_CMD_SET_TXCB:
if (io_mode == SS_I2S_TX) {
SS_I2S_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
io_i2s_tx_master_ioctl(dev_id, IO_SET_CB_TX, param);
}
break;
case I2S_CMD_SET_RXCB:
if (io_mode == SS_I2S_RX) {
SS_I2S_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
io_i2s_rx_master_ioctl(dev_id, IO_SET_CB_RX, param);
}
break;
case I2S_CMD_SET_ERRCB:
if (io_mode == SS_I2S_RX) {
SS_I2S_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
io_i2s_rx_master_ioctl(dev_id, IO_SET_CB_ERR, param);
} else if (io_mode == SS_I2S_TX) {
SS_I2S_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
io_i2s_tx_master_ioctl(dev_id, IO_SET_CB_ERR, param);
}
break;
case I2S_CMD_SET_TXINT: break;
case I2S_CMD_SET_RXINT: break;
case I2S_CMD_RESET:
ss_i2s_master_reset(ctx);
break;
case I2S_CMD_FLUSH_TX:
ss_i2s_master_flush_tx(ctx);
break;
case I2S_CMD_FLUSH_RX:
ss_i2s_master_flush_rx(ctx);
break;
case I2S_CMD_ENA_DEV:
ss_i2s_master_enable(ctx);
break;
case I2S_CMD_DIS_DEV:
ss_i2s_master_disable(ctx);
break;
case I2S_CMD_SET_TXINT_BUF: break;
case I2S_CMD_SET_RXINT_BUF: break;
case I2S_CMD_SET_TXCHET_BUF: break;
case I2S_CMD_SET_RXCHDT_BUF: break;
case I2S_CMD_MST_SET_CLK: break;
case I2S_CMD_MST_SET_WSS: break;
case I2S_CMD_MST_SET_SCLKG: break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
void ss_i2s_mst_int_tx_cb(SS_I2S_MST_DEV_CONTEXT *ctx, void *param)
{
DEV_I2S_INFO_PTR info = ctx->info;
if (ctx->flags & SS_I2S_MASTER_FLAG_TX) {
ctx->flags &= ~SS_I2S_MASTER_FLAG_TX;
if (info->i2s_cbs.tx_cb) {
info->i2s_cbs.tx_cb(info);
}
}
}
void ss_i2s_mst_int_rx_cb(SS_I2S_MST_DEV_CONTEXT *ctx, void *param)
{
DEV_I2S_INFO_PTR info = ctx->info;
if (ctx->flags & SS_I2S_MASTER_FLAG_RX) {
ctx->flags &= ~SS_I2S_MASTER_FLAG_RX;
if (info->i2s_cbs.rx_cb) {
info->i2s_cbs.rx_cb(info);
}
}
}
void ss_i2s_mst_int_err_cb(SS_I2S_MST_DEV_CONTEXT *ctx, void *param)
{
DEV_I2S_INFO_PTR info = ctx->info;
uint8_t io_mode = ctx->io_mode;
uint32_t flag;
flag = (io_mode == SS_I2S_RX) ? SS_I2S_MASTER_FLAG_RX_ERROR : SS_I2S_MASTER_FLAG_TX_ERROR;
if (ctx->flags & flag) {
ctx->flags &= ~flag;
if (info->i2s_cbs.err_cb) {
info->i2s_cbs.err_cb(info);
}
}
}

View File

@@ -1,947 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "device/subsystem/i2c_master.h"
#include "device/subsystem/i2c_priv.h"
#include "io_config.h"
#include "apexextensions.h"
/* Notes:
*
*/
#ifdef IO_I2C_MST0_PRESENT
#define I2C_DEV_PRESENT
#endif
#ifdef IO_I2C_MST1_PRESENT
#define I2C_DEV_PRESENT
#endif
#ifdef IO_I2C_MST2_PRESENT
#define I2C_DEV_PRESENT
#endif
#ifdef IO_I2C_MST3_PRESENT
#define I2C_DEV_PRESENT
#endif
#ifdef I2C_DEV_PRESENT
#define I2C_MAX_CNT (4)
static void i2c_mst_err_ISR_proc(uint32_t dev_id);
static void i2c_mst_rx_avail_ISR_proc(uint32_t dev_id);
static void i2c_mst_tx_req_ISR_proc(uint32_t dev_id);
static void i2c_mst_stop_det_ISR_proc(uint32_t dev_id);
#ifdef IO_I2C_MST0_PRESENT
static _Interrupt void i2c_mst0_err_ISR()
{
i2c_mst_err_ISR_proc(0);
}
static _Interrupt void i2c_mst0_rx_avail_ISR()
{
i2c_mst_rx_avail_ISR_proc(0);
}
static _Interrupt void i2c_mst0_tx_req_ISR()
{
i2c_mst_tx_req_ISR_proc(0);
}
static _Interrupt void i2c_mst0_stop_det_ISR()
{
i2c_mst_stop_det_ISR_proc(0);
}
#endif
#ifdef IO_I2C_MST1_PRESENT
static _Interrupt void i2c_mst1_err_ISR()
{
i2c_mst_err_ISR_proc(1);
}
static _Interrupt void i2c_mst1_rx_avail_ISR()
{
i2c_mst_rx_avail_ISR_proc(1);
}
static _Interrupt void i2c_mst1_tx_req_ISR()
{
i2c_mst_tx_req_ISR_proc(1);
}
static _Interrupt void i2c_mst1_stop_det_ISR()
{
i2c_mst_stop_det_ISR_proc(1);
}
#endif
#ifdef IO_I2C_MST2_PRESENT
static _Interrupt void i2c_mst2_err_ISR()
{
i2c_mst_err_ISR_proc(2);
}
static _Interrupt void i2c_mst2_rx_avail_ISR()
{
i2c_mst_rx_avail_ISR_proc(2);
}
static _Interrupt void i2c_mst2_tx_req_ISR()
{
i2c_mst_tx_req_ISR_proc(2);
}
static _Interrupt void i2c_mst2_stop_det_ISR()
{
i2c_mst_stop_det_ISR_proc(2);
}
#endif
#ifdef IO_I2C_MST3_PRESENT
static _Interrupt void i2c_mst3_err_ISR()
{
i2c_mst_err_ISR_proc(3);
}
static _Interrupt void i2c_mst3_rx_avail_ISR()
{
i2c_mst_rx_avail_ISR_proc(3);
}
static _Interrupt void i2c_mst3_tx_req_ISR()
{
i2c_mst_tx_req_ISR_proc(3);
}
static _Interrupt void i2c_mst3_stop_det_ISR()
{
i2c_mst_stop_det_ISR_proc(3);
}
#endif
static void fill_txfifo(i2c_info_pt dev);
static void fill_txfifo_for_rx(i2c_info_pt dev);
static void retrieve_rxfifo(i2c_info_pt dev);
#ifdef __Xdmac
static void create_dma_descriptors_rx(i2c_info_pt dev, uint8_t *dest,
uint32_t size, uint32_t burst);
static void create_dma_descriptors_tx(i2c_info_pt dev, uint8_t *src,
uint32_t size, uint32_t burst);
static void create_dma_descriptors_tx_for_rx(i2c_info_pt dev,
uint32_t size,
uint32_t burst);
#endif
/* I2C master devices private data structures */
static i2c_info_pt i2c_handles[I2C_MAX_CNT] = { 0 };
#ifdef __Xdmac
static _Uncached uint32_t i2c_dmarx_descriptors[4 * I2C_MAX_CNT];
static _Uncached uint32_t i2c_dmatx_descriptors[8 * I2C_MAX_CNT];
#endif
static i2c_info_t i2c_master_devs[] = {
#ifdef IO_I2C_MST0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_I2C_MST0_CON,
#ifdef IO_I2C_MST0_DMA_RX
.dmarxchanid = IO_I2C_MST0_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_MST0_DMA_TX
.dmatxchanid = IO_I2C_MST0_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_MST0_FS,
.vector_err = IO_I2C_MST0_INT_ERR,
.isr_err = i2c_mst0_err_ISR,
.vector_rx_avail = IO_I2C_MST0_INT_RX_AVAIL,
.isr_rx_avail = i2c_mst0_rx_avail_ISR,
.vector_tx_req = IO_I2C_MST0_INT_TX_REQ,
.isr_tx_req = i2c_mst0_tx_req_ISR,
.vector_stop_det = IO_I2C_MST0_INT_STOP_DET,
.isr_stop_det = i2c_mst0_stop_det_ISR },
#endif
#ifdef IO_I2C_MST1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_I2C_MST1_CON,
#ifdef IO_I2C_MST1_DMA_RX
.dmarxchanid = IO_I2C_MST1_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_MST1_DMA_TX
.dmatxchanid = IO_I2C_MST1_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_MST1_FS,
.vector_err = IO_I2C_MST1_INT_ERR,
.isr_err = i2c_mst1_err_ISR,
.vector_rx_avail = IO_I2C_MST1_INT_RX_AVAIL,
.isr_rx_avail = i2c_mst1_rx_avail_ISR,
.vector_tx_req = IO_I2C_MST1_INT_TX_REQ,
.isr_tx_req = i2c_mst1_tx_req_ISR,
.vector_stop_det = IO_I2C_MST1_INT_STOP_DET,
.isr_stop_det = i2c_mst1_stop_det_ISR },
#endif
#ifdef IO_I2C_MST2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_I2C_MST2_CON,
#ifdef IO_I2C_MST2_DMA_RX
.dmarxchanid = IO_I2C_MST2_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_MST2_DMA_TX
.dmatxchanid = IO_I2C_MST2_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_MST2_FS,
.vector_err = IO_I2C_MST2_INT_ERR,
.isr_err = i2c_mst2_err_ISR,
.vector_rx_avail = IO_I2C_MST2_INT_RX_AVAIL,
.isr_rx_avail = i2c_mst2_rx_avail_ISR,
.vector_tx_req = IO_I2C_MST2_INT_TX_REQ,
.isr_tx_req = i2c_mst2_tx_req_ISR,
.vector_stop_det = IO_I2C_MST2_INT_STOP_DET,
.isr_stop_det = i2c_mst2_stop_det_ISR },
#endif
#ifdef IO_I2C_MST3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_I2C_MST3_CON,
#ifdef IO_I2C_MST3_DMA_RX
.dmarxchanid = IO_I2C_MST3_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_MST3_DMA_TX
.dmatxchanid = IO_I2C_MST3_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_MST3_FS,
.vector_err = IO_I2C_MST3_INT_ERR,
.isr_err = i2c_mst3_err_ISR,
.vector_rx_avail = IO_I2C_MST3_INT_RX_AVAIL,
.isr_rx_avail = i2c_mst3_rx_avail_ISR,
.vector_tx_req = IO_I2C_MST3_INT_TX_REQ,
.isr_tx_req = i2c_mst3_tx_req_ISR,
.vector_stop_det = IO_I2C_MST3_INT_STOP_DET,
.isr_stop_det = i2c_mst3_stop_det_ISR },
#endif
{ .instID = I2C_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
#define REG_WRITE_BITS(reg, x, y, len, pos) REG_WRITE(reg, ((((x) & ~((~(0xffffffff << len)) << pos)) \
| (((y) << pos) & ((~(0xffffffff << len)) << pos)))))
/* API functions */
uint32_t io_i2c_master_open(uint32_t dev_id)
{
uint32_t h = 0;
i2c_info_pt dev;
h = 0;
while ((i2c_master_devs[h].instID != dev_id)
&& (i2c_master_devs[h].instID != I2C_MAX_CNT)) {
h++;
}
if ((i2c_master_devs[h].instID == I2C_MAX_CNT) || (0 != i2c_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
i2c_handles[dev_id] = &i2c_master_devs[h];
dev = i2c_handles[dev_id];
/* enable clock */
REG_WRITE(I2C_CLKEN, 0x1);
/* mask all interrupts */
REG_WRITE(I2C_INTR_MASK, 0);
/* initialize */
dev->handling_tx = dev->handling_rx = 0;
dev->tx_data = dev->rx_data = NULL;
dev->next_cond = I2C_STOP_CMD;
/* set interrupt vector */
_setvecti(dev->vector_err, dev->isr_err);
_setvecti(dev->vector_rx_avail, dev->isr_rx_avail);
_setvecti(dev->vector_tx_req, dev->isr_tx_req);
_setvecti(dev->vector_stop_det, dev->isr_stop_det);
#ifdef __Xdmac
dev->dmarxdescriptor = &i2c_dmarx_descriptors[4 * h];
dev->dmatxdescriptor = &i2c_dmatx_descriptors[8 * h];
if (dev->dmarxchanid != DMA_NONE) {
dev->dmarxdescriptor[1] = dev->reg_base + I2C_DATA_CMD;
dev->dmarxdescriptor[3] = 0;
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, dev->isr_rx_avail);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, dev->isr_err);
}
if (dev->dmatxchanid != DMA_NONE) {
dev->dmatxdescriptor[2] = dev->dmatxdescriptor[6] =
dev->reg_base + I2C_DATA_CMD;
dev->dmatxdescriptor[3] = (uint32_t) &(dev->dmatxdescriptor[4]);
dev->dmatxdescriptor[7] = 0;
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, dev->isr_tx_req);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, dev->isr_err);
}
#endif
/* enable device */
REG_WRITE(I2C_ENABLE, 0x1);
/* unmask error interrupt: stop-detection, tx-abort, rx-over */
REG_WRITE(I2C_INTR_MASK, R_TX_ABRT | R_RX_OVER);
return 0;
}
void io_i2c_master_close(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t enable = REG_READ(I2C_ENABLE);
/* clear all interrupts */
REG_WRITE(I2C_INTR_MASK, 0);
REG_READ(I2C_CLR_INTR);
/* abort (and wait) */
REG_WRITE(I2C_ENABLE, (enable | (0x1 << 1)));
while ((REG_READ(I2C_TX_ABRT_SOURCE) & (0x1 << 16)) == 0) {
;
}
/* disable */
REG_WRITE(I2C_ENABLE, 0);
/* reset regs */
REG_WRITE(I2C_CON, 0x65);
REG_WRITE(I2C_TAR, 0x55);
REG_WRITE(I2C_SS_SCL_HCNT, 0x30);
REG_WRITE(I2C_SS_SCL_LCNT, 0x38);
REG_WRITE(I2C_FS_SCL_HCNT, 0);
REG_WRITE(I2C_FS_SCL_LCNT, 0);
REG_WRITE(I2C_RX_TL, 0);
REG_WRITE(I2C_TX_TL, 0);
REG_WRITE(I2C_SDA_HOLD, 0x1);
REG_WRITE(I2C_FS_SPKLEN, 0x1);
/* gate the I2C clock */
REG_WRITE(I2C_CLKEN, 0);
_setvecti(dev->vector_err, NULL);
_setvecti(dev->vector_rx_avail, NULL);
_setvecti(dev->vector_tx_req, NULL);
_setvecti(dev->vector_stop_det, NULL);
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmarxchanid);
}
if (dev->dmatxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmatxchanid);
}
#endif
dev->rx_cb = NULL;
dev->tx_cb = NULL;
dev->err_cb = NULL;
i2c_handles[dev_id] = 0;
}
void io_i2c_master_read(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
dev->rx_size = *size;
dev->rx_count = dev->rx_req_count = 0;
dev->rx_data = data;
/* check whether a master-tx is in progress; if so, postpone until tx completion */
if (dev->handling_tx == 0) {
dev->handling_rx = 1;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* write first requests to fifo, assuming size > 0 */
fill_txfifo_for_rx(dev);
/* unmask interrupts: tx-threshold (tx-empty), rx-threshold (rx-full) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY | R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else {
/* RX descriptor - to fetch data */
if (*size != 0) {
/* rx data available; at least one */
create_dma_descriptors_rx(dev, data, *size,
(1 + REG_READ(I2C_RX_TL)));
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
}
/* TX descriptor - for read command and a closing read+stop command */
if (*size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx_for_rx(dev, *size,
(dev->fifo_depth -
REG_READ(I2C_TX_TL)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
}
}
void io_i2c_master_write(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
dev->tx_size = *size;
dev->tx_count = 0;
dev->tx_data = data;
/* check whether a master-rx is in progress; if so, postpone until rx completion */
if (dev->handling_rx == 0) {
dev->handling_tx = 1;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write first bytes to fifo, assuming size > 0 */
fill_txfifo(dev);
/* unmask interrupt: tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else {
/* TX descriptor - data+write command and a closing data+write+stop command */
if (*size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx(dev, data, *size,
(dev->fifo_depth -
REG_READ(I2C_TX_TL)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
}
}
void io_i2c_master_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
uint32_t data = 0, enable = 0;
i2c_info_pt dev = i2c_handles[dev_id];
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
case IO_I2C_MASTER_SET_NEXT_COND:
dev->next_cond = (uint16_t)*((uint32_t *) arg);
break;
default:
{
enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable & ~(0x1)));
switch (cmd) {
case IO_I2C_MASTER_SET_HOLD_TIME_RX:
data = REG_READ(I2C_SDA_HOLD);
REG_WRITE_BITS(I2C_SDA_HOLD, data, *((uint32_t *) arg), 8,
16);
break;
case IO_I2C_MASTER_SET_HOLD_TIME_TX:
data = REG_READ(I2C_SDA_HOLD);
REG_WRITE_BITS(I2C_SDA_HOLD, data, *((uint32_t *) arg), 16,
0);
break;
case IO_I2C_MASTER_SET_SPEED:
data = REG_READ(I2C_CON);
REG_WRITE_BITS(I2C_CON, data, *((uint32_t *) arg), 2, 1);
break;
case IO_I2C_MASTER_SET_10BIT_ADDR:
data = REG_READ(I2C_CON);
REG_WRITE_BITS(I2C_CON, data, *((uint32_t *) arg), 1, 3);
break;
case IO_I2C_MASTER_SET_SPKLEN:
REG_WRITE(I2C_FS_SPKLEN, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_TARGET_ADDR:
REG_WRITE(I2C_TAR, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_SS_SCL_HCNT:
REG_WRITE(I2C_SS_SCL_HCNT, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_SS_SCL_LCNT:
REG_WRITE(I2C_SS_SCL_LCNT, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_FS_SCL_HCNT:
REG_WRITE(I2C_FS_SCL_HCNT, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_FS_SCL_LCNT:
REG_WRITE(I2C_FS_SCL_LCNT, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_RX_THRESHOLD:
REG_WRITE(I2C_RX_TL, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_TX_THRESHOLD:
REG_WRITE(I2C_TX_TL, *((uint32_t *) arg));
break;
default:
break;
}
while ((0x1 & REG_READ(I2C_ENABLE_STATUS)) != 0) {
;
}
enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable | 0x1));
break;
}
}
}
static void i2c_mst_err_ISR_proc(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
if (REG_READ(I2C_CLR_TX_ABRT)) {
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
}
if (REG_READ(I2C_CLR_RX_OVER)) {
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
}
}
static void i2c_mst_rx_avail_ISR_proc(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read data from fifo */
retrieve_rxfifo(dev);
if (dev->rx_size == dev->rx_count) { /* read buffer completely filled, mask rx-avail interrupt */
val = REG_READ(I2C_INTR_MASK) & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
dev->handling_rx = 0;
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
#ifdef __Xdmac
} else {
/* DMA RX xfer done */
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_int_clear((0x1 << dev->dmarxchanid));
}
#endif
}
static void i2c_mst_tx_req_ISR_proc(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
if (dev->handling_tx == 1) {
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
if (dev->tx_size == dev->tx_count) { /* no data left to put into the fifo, mask tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
/* tx done */
dev->handling_tx = 0;
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
} else { /* write data into fifo */
fill_txfifo(dev);
}
#ifdef __Xdmac
} else {
/* DMA TX xfer done */
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
}
#endif
}
if (dev->handling_rx == 1) {
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
if (dev->rx_size == dev->rx_req_count) { /* no data left to put into the fifo, mask tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
} else { /* write data into fifo */
fill_txfifo_for_rx(dev);
}
#ifdef __Xdmac
} else {
/* DMA TX xfer done */
dev->rx_req_count = dev->rx_size;
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
}
#endif
}
}
static void i2c_mst_stop_det_ISR_proc(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
if (dev->handling_tx == 1) {
/* tx done */
dev->handling_tx = 0;
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
/* handle pending rx, if any */
if (dev->rx_data != NULL) {
dev->handling_rx = 1;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* write first requests to fifo, assuming size > 0 */
fill_txfifo_for_rx(dev);
/* unmask interrupts: tx-threshold (tx-empty), rx-threshold (rx-full) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY | R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else {
/* RX descriptor - to fetch data */
if (dev->rx_size != 0) {
/* rx data available; at least one */
create_dma_descriptors_rx(dev, dev->rx_data,
dev->rx_size,
(1 + REG_READ(I2C_RX_TL)));
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
}
/* TX descriptor - for read command and a closing read+stop command */
if (dev->rx_size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx_for_rx(dev, dev->rx_size,
(dev->fifo_depth -
REG_READ
(I2C_TX_TL)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
} else { /* done, prevent threshold interrupts */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
}
} else if (dev->handling_rx == 1) {
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read remaining data from fifo */
retrieve_rxfifo(dev);
#ifdef __Xdmac
}
#endif
/* rx done */
dev->handling_rx = 0;
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
/* handle pending tx, if any */
if (dev->tx_data != NULL) {
dev->handling_tx = 1;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write first bytes to fifo, assuming size > 0 */
fill_txfifo(dev);
/* unmask interrupt: tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else {
/* TX descriptor - data+write command and a closing data+write+stop command */
if (dev->tx_size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx(dev, dev->tx_data,
dev->tx_size,
(dev->fifo_depth -
REG_READ(I2C_TX_TL)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
} else { /* done, prevent threshold interrupts */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
}
}
REG_READ(I2C_CLR_STOP_DET);
}
static void fill_txfifo(i2c_info_pt dev)
{
uint32_t h = 0, free = 0, cnt = 0;
cnt = dev->tx_size - dev->tx_count;
free = dev->fifo_depth - REG_READ(I2C_TXFLR);
if (cnt > free) {
cnt = free;
}
for (h = 0; h != (cnt - 1); h++) {
REG_WRITE(I2C_DATA_CMD, (dev->tx_data[dev->tx_count++]));
}
if ((dev->tx_size - 1) == dev->tx_count) { /* end of message, insert stop condition */
REG_WRITE(I2C_DATA_CMD,
(dev->tx_data[dev->tx_count++] | dev->next_cond));
} else { /* continue */
REG_WRITE(I2C_DATA_CMD, (dev->tx_data[dev->tx_count++]));
}
}
static void fill_txfifo_for_rx(i2c_info_pt dev)
{
uint32_t h = 0, free = 0, cnt = 0;
cnt = dev->rx_size - dev->rx_req_count;
free = dev->fifo_depth - REG_READ(I2C_TXFLR);
if (cnt > free) {
cnt = free;
}
for (h = 0; h != (cnt - 1); h++) {
REG_WRITE(I2C_DATA_CMD, I2C_READ_CMD);
}
dev->rx_req_count += cnt;
if (dev->rx_size == dev->rx_req_count) { /* end of message, insert stop condition */
REG_WRITE(I2C_DATA_CMD, (I2C_READ_CMD | dev->next_cond));
} else { /* continue */
REG_WRITE(I2C_DATA_CMD, I2C_READ_CMD);
}
}
static void retrieve_rxfifo(i2c_info_pt dev)
{
uint32_t h = 0, avail = 0, cnt = 0;
cnt = dev->rx_size - dev->rx_count;
avail = REG_READ(I2C_RXFLR);
if (cnt > avail) {
cnt = avail;
}
for (h = 0; h != cnt; h++) {
dev->rx_data[dev->rx_count++] = REG_READ(I2C_DATA_CMD);
}
}
#ifdef __Xdmac
#define I2C_MST_DMA_RX_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b000, dtt=b10, r=b1, op=b01 */
#define I2C_MST_DMA_TX_FOR_RX_CTRL (0x0000006f) /* am=b00, i=b0, dw/inc=b011, dtt=b01, r=b1, op=b11 */
#define I2C_MST_DMA_TX_END_CTRL (0x2000006d) /* am=b00, i=b1, dw/inc=b011, dtt=b01, r=b1, op=b01 */
#define I2C_MST_DMA_TX_CTRL (0x4000000f) /* am=b01, i=b0, dw/inc=b000, dtt=b01, r=b1, op=b11 */
#define I2C_MST_DMA_CTRL_SIZE_POS (8)
#define I2C_MST_DMA_CTRL_XFER_POS (21)
static uint16_t readCommand = I2C_READ_CMD;
static uint16_t readstopCommand = I2C_READ_CMD | I2C_STOP_CMD;
static void create_dma_descriptors_rx(i2c_info_pt dev, uint8_t *dest,
uint32_t size, uint32_t burst)
{
dev->dmarxdescriptor[0] =
I2C_MST_DMA_RX_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS) |
((size - 1) << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmarxdescriptor[2] = (uint32_t) dest + (size - 1);
}
static void create_dma_descriptors_tx(i2c_info_pt dev, uint8_t *src,
uint32_t size, uint32_t burst)
{
if (size > 1) {
dev->dmatxdescriptor[0] =
I2C_MST_DMA_TX_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS) |
((size - 2) << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) src + (size - 2);
dev->dmatx_last = src[size - 1] | I2C_STOP_CMD;
dev->dmatxdescriptor[4 + 0] =
I2C_MST_DMA_TX_END_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS)
| (1 << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[4 + 1] = (uint32_t) &(dev->dmatx_last);
} else { /* size == 1 */
dev->dmatx_last = src[0] | I2C_STOP_CMD;
dev->dmatxdescriptor[0] =
I2C_MST_DMA_TX_END_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS)
| (1 << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) &(dev->dmatx_last);
}
}
static void create_dma_descriptors_tx_for_rx(i2c_info_pt dev,
uint32_t size, uint32_t burst)
{
if (size > 1) {
dev->dmatxdescriptor[0] =
I2C_MST_DMA_TX_FOR_RX_CTRL | (burst <<
I2C_MST_DMA_CTRL_XFER_POS) |
(((size - 1) * 2 - 1) << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) &readCommand;
dev->dmatxdescriptor[4 + 0] =
I2C_MST_DMA_TX_END_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS)
| (1 << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[4 + 1] = (uint32_t) &readstopCommand;
} else { /* size == 1 */
dev->dmatxdescriptor[0] =
I2C_MST_DMA_TX_END_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS)
| (1 << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) &readstopCommand;
}
}
#endif
#endif

View File

@@ -1,690 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "device/subsystem/i2c_slave.h"
#include "device/subsystem/i2c_priv.h"
#include "io_config.h"
#include "apexextensions.h"
/* Notes:
*
*/
#ifdef IO_I2C_SLV0_PRESENT
#define I2C_DEV_PRESENT
static _Interrupt void i2c_slv0_err_ISR();
static _Interrupt void i2c_slv0_rx_avail_ISR();
static _Interrupt void i2c_slv0_tx_req_ISR();
static _Interrupt void i2c_slv0_stop_det_ISR();
static _Interrupt void i2c_slv0_rd_req_ISR();
/* I2C slave devices private data structures; at most 1 instance */
static i2c_info_pt i2c_handles[1] = { 0 };
#ifdef __Xdmac
static _Uncached uint32_t i2c_dmarx_descriptors[4 * 1];
static _Uncached uint32_t i2c_dmatx_descriptors[8 * 1];
#endif
#define I2C_SLV_DMA_RX_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b000, dtt=b10, r=b1, op=b01 */
#define I2C_SLV_DMA_TX_CTRL (0x6000000d) /* am=b01, i=b1, dw/inc=b000, dtt=b01, r=b1, op=b01 */
#define I2C_SLV_DMA_CTRL_SIZE_POS (8)
#define I2C_SLV_DMA_CTRL_XFER_POS (21)
static i2c_info_t i2c_slave_devs[] = {
{ .instID = 0,
.reg_base = AR_IO_I2C_SLV0_CON,
#ifdef IO_I2C_SLV0_DMA_RX
.dmarxchanid = IO_I2C_SLV0_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_SLV0_DMA_TX
.dmatxchanid = IO_I2C_SLV0_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_SLV0_FS,
.vector_err = IO_I2C_SLV0_INT_ERR,
.isr_err = i2c_slv0_err_ISR,
.vector_rx_avail = IO_I2C_SLV0_INT_RX_AVAIL,
.isr_rx_avail = i2c_slv0_rx_avail_ISR,
.vector_tx_req = IO_I2C_SLV0_INT_TX_REQ,
.isr_tx_req = i2c_slv0_tx_req_ISR,
.vector_stop_det = IO_I2C_SLV0_INT_STOP_DET,
.isr_stop_det = i2c_slv0_stop_det_ISR,
.vector_restart_det = IO_I2C_SLV0_INT_RESTART_DET,
.vector_rd_req = IO_I2C_SLV0_INT_RD_REQ,
.isr_rd_req = i2c_slv0_rd_req_ISR }
};
#endif
#ifdef I2C_DEV_PRESENT
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
#define REG_WRITE_BITS(reg, x, y, len, pos) REG_WRITE(reg, ((((x) & ~((~(0xffffffff << len)) << pos)) \
| (((y) << pos) & ((~(0xffffffff << len)) << pos)))))
/* API functions */
uint32_t io_i2c_slave_open(uint32_t dev_id)
{
i2c_info_pt dev;
uint32_t h = 0;
if ((0 != i2c_handles[0]) || (dev_id != 0)) { /* device still open or non-zero id */
return 1;
}
i2c_handles[0] = &i2c_slave_devs[0];
dev = i2c_handles[0];
/* enable clock; replicate code to make sure i2c enable is 255+ cycles later (see databook) */
for (h = 0; h != 255; h++) {
REG_WRITE(I2C_CLKEN, 0x1);
}
/* mask all interrupts */
REG_WRITE(I2C_INTR_MASK, 0);
/* get stop detect interrupt only when addressed */
REG_WRITE(I2C_CON, (REG_READ(I2C_CON) | (0x1 << 7)));
/* initialize */
dev->handling_tx = dev->handling_rx = 0;
dev->tx_data = dev->rx_data = NULL;
/* set interrupt vector, mid/high priority */
_setvecti(dev->vector_err, dev->isr_err);
_setvecti(dev->vector_rx_avail, dev->isr_rx_avail);
_setvecti(dev->vector_tx_req, dev->isr_tx_req);
_setvecti(dev->vector_stop_det, dev->isr_stop_det);
_setvecti(dev->vector_restart_det, dev->isr_stop_det);
_setvecti(dev->vector_rd_req, dev->isr_rd_req);
#ifdef __Xdmac
dev->dmarxdescriptor = &i2c_dmarx_descriptors[4 * 0];
dev->dmatxdescriptor = &i2c_dmatx_descriptors[8 * 0];
if (dev->dmarxchanid != DMA_NONE) {
dev->dmarxdescriptor[1] = dev->reg_base + I2C_DATA_CMD;
dev->dmarxdescriptor[3] = 0;
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, dev->isr_rx_avail);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, dev->isr_err);
}
if (dev->dmatxchanid != DMA_NONE) { /* one descriptor only */
dev->dmatxdescriptor[2] = dev->reg_base + I2C_DATA_CMD;
dev->dmatxdescriptor[3] = 0;
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, dev->isr_tx_req);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, dev->isr_err);
}
#endif
/* enable device */
REG_WRITE(I2C_ENABLE, 0x1);
/* unmask interrupt: stop-detect, rd-req, rx-over, tx-abort */
REG_WRITE(I2C_INTR_MASK,
R_STOP_DET | R_RD_REQ | R_RX_OVER | R_TX_ABRT);
return 0;
}
void io_i2c_slave_close(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
/* clear all interrupts */
REG_WRITE(I2C_INTR_MASK, 0);
REG_READ(I2C_CLR_INTR);
/* disable */
REG_WRITE(I2C_ENABLE, 0);
/* reset regs */
REG_WRITE(I2C_CON, 0x4);
REG_WRITE(I2C_SAR, 0);
REG_WRITE(I2C_RX_TL, 0);
REG_WRITE(I2C_TX_TL, 0);
REG_WRITE(I2C_SDA_HOLD, 0x1);
REG_WRITE(I2C_SDA_SETUP, 0x64);
REG_WRITE(I2C_FS_SPKLEN, 0x1);
/* gate the I2C clock */
REG_WRITE(I2C_CLKEN, 0);
_setvecti(dev->vector_err, NULL);
_setvecti(dev->vector_rx_avail, NULL);
_setvecti(dev->vector_tx_req, NULL);
_setvecti(dev->vector_stop_det, NULL);
_setvecti(dev->vector_restart_det, NULL);
_setvecti(dev->vector_rd_req, NULL);
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmarxchanid);
}
if (dev->dmatxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmatxchanid);
}
#endif
dev->rx_cb = NULL;
dev->tx_cb = NULL;
dev->err_cb = NULL;
i2c_handles[dev_id] = 0;
}
void io_i2c_slave_read(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, avail = 0;
dev->rx_data = data;
dev->rx_size = *size;
dev->rx_count = 0;
dev->p_rxsize = size;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* mask stop-condition interrupt (to prevent stop-det ISR from interrupting) */
val = REG_READ(I2C_INTR_MASK);
REG_WRITE(I2C_INTR_MASK, (val & ~R_STOP_DET));
if (dev->handling_rx == 0) {
dev->handling_rx = 1;
dev->stop_detected = 0;
/* unmask interrupt: rx threshold (rx-full) */
val = REG_READ(I2C_INTR_MASK) | R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
} else {
/* RX already in progress, due to earlier read() calls */
if (dev->stop_detected == 0) {
/* unmask interrupts: rx threshold (rx-full) and stop-condition */
val = REG_READ(I2C_INTR_MASK) | R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
} else {
/* there is data in the rx-fifo remaining: read it */
cnt = dev->rx_size - dev->rx_count;
avail = REG_READ(I2C_RXFLR);
if (cnt >= avail) { /* after reading, all data processed, rx buffer not completely filled */
cnt = avail;
dev->handling_rx = 0;
}
for (h = 0; h != cnt; h++) {
dev->rx_data[dev->rx_count++] = REG_READ(I2C_DATA_CMD);
}
if (dev->handling_rx == 0) {
if (dev->rx_size != dev->rx_count) { /* read buffer NOT completely filled */
*(dev->p_rxsize) = dev->rx_count;
}
}
/* slave rx done */
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
}
/* unmask stop-condition interrupt again */
val = REG_READ(I2C_INTR_MASK) | R_STOP_DET;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else { /* DMA: create descriptor */
uint32_t threshold;
dev->handling_rx = 1;
dev->stop_detected = 0;
if (*size != 0) {
/* rx data available; at least one, more is uncertain */
threshold = REG_READ(I2C_RX_TL);
dev->dmarxdescriptor[0] =
I2C_SLV_DMA_RX_CTRL | ((threshold + 1) <<
I2C_SLV_DMA_CTRL_XFER_POS) | ((*size
-
1) <<
I2C_SLV_DMA_CTRL_SIZE_POS);
dev->dmarxdescriptor[2] = (uint32_t) data + (*size - 1);
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
}
}
#endif
}
void io_i2c_slave_write(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, free = 0;
dev->tx_data = data;
dev->tx_size = *size;
dev->tx_count = 0;
dev->p_txsize = size;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* mask read request interrupt (to prevent read request ISR from interrupting) */
val = REG_READ(I2C_INTR_MASK);
REG_WRITE(I2C_INTR_MASK, (val & ~R_RD_REQ));
if (dev->handling_tx == 0) {
dev->handling_tx = 1;
dev->rd_req_detected = 0;
} else {
/* TX already in progress, due to earlier write() calls */
if (dev->rd_req_detected != 0) {
/* there is space in the tx-fifo remaining: fill it */
cnt = dev->tx_size - dev->tx_count;
free = dev->fifo_depth - REG_READ(I2C_TXFLR);
if (cnt > free) {
cnt = free;
}
for (h = 0; h != cnt; h++) {
REG_WRITE(I2C_DATA_CMD,
(dev->tx_data[dev->tx_count++]));
}
if (dev->tx_size == dev->tx_count) { /* write buffer completely emptied */
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
}
/* unmask interrupt: tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
}
}
/* unmask rd-req interrupt again */
val = REG_READ(I2C_INTR_MASK) | R_RD_REQ;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else { /* DMA: create descriptor */
uint32_t threshold;
dev->handling_tx = 1;
dev->rd_req_detected = 0;
if (*size != 0) {
/* tx data available; at least one, more is uncertain */
threshold = REG_READ(I2C_TX_TL);
dev->dmatxdescriptor[0] =
I2C_SLV_DMA_TX_CTRL | ((dev->fifo_depth - threshold) <<
I2C_SLV_DMA_CTRL_XFER_POS) | ((*size
-
1) <<
I2C_SLV_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) data + (*size - 1);
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
}
}
#endif
}
void io_i2c_slave_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t data = 0, enable = 0;
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
default:
{
enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable & ~(0x1)));
switch (cmd) {
case IO_I2C_SLAVE_SET_HOLD_TIME_RX:
data = REG_READ(I2C_SDA_HOLD);
REG_WRITE_BITS(I2C_SDA_HOLD, data, *((uint32_t *) arg), 8,
16);
break;
case IO_I2C_SLAVE_SET_HOLD_TIME_TX:
data = REG_READ(I2C_SDA_HOLD);
REG_WRITE_BITS(I2C_SDA_HOLD, data, *((uint32_t *) arg), 16,
0);
break;
case IO_I2C_SLAVE_SET_10BIT_ADDR:
data = REG_READ(I2C_CON);
REG_WRITE_BITS(I2C_CON, data, *((uint32_t *) arg), 1, 3);
break;
case IO_I2C_SLAVE_SET_SETUP_TIME:
REG_WRITE(I2C_SDA_SETUP, *((uint32_t *) arg));
break;
case IO_I2C_SLAVE_SET_SPKLEN:
REG_WRITE(I2C_FS_SPKLEN, *((uint32_t *) arg));
break;
case IO_I2C_SLAVE_SET_ADDR:
REG_WRITE(I2C_SAR, *((uint32_t *) arg));
break;
case IO_I2C_SLAVE_SET_RX_THRESHOLD:
REG_WRITE(I2C_RX_TL, *((uint32_t *) arg));
break;
case IO_I2C_SLAVE_SET_TX_THRESHOLD:
REG_WRITE(I2C_TX_TL, *((uint32_t *) arg));
break;
default:
break;
}
while ((0x1 & REG_READ(I2C_ENABLE_STATUS)) != 0) {
;
}
enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable | 0x1));
break;
}
}
}
static _Interrupt void i2c_slv0_err_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
if (REG_READ(I2C_CLR_RX_OVER)) {
if (NULL != dev->err_cb) {
dev->err_cb(0);
}
}
if (REG_READ(I2C_CLR_TX_ABRT)) {
/* must be reception of read command (rd_req) while tx-fifo non-empty: results in flush of fifo */
}
}
static _Interrupt void i2c_slv0_rx_avail_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, avail = 0;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read data from fifo */
cnt = dev->rx_size - dev->rx_count;
avail = REG_READ(I2C_RXFLR);
if (cnt > avail) {
cnt = avail;
}
for (h = 0; h != cnt; h++) {
dev->rx_data[dev->rx_count++] = REG_READ(I2C_DATA_CMD);
}
if (dev->rx_size == dev->rx_count) { /* read buffer completely filled */
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
/* mask rx-avail interrupt */
val = REG_READ(I2C_INTR_MASK) & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
}
#ifdef __Xdmac
} else {
/* DMA RX xfer done */
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_int_clear((0x1 << dev->dmarxchanid));
/* call user callback function, if any */
dev->rx_data = NULL;
if (dev->rx_cb != NULL) {
dev->rx_cb(dev_id);
}
}
#endif
}
static _Interrupt void i2c_slv0_tx_req_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, free = 0;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write data into fifo */
cnt = dev->tx_size - dev->tx_count;
free = dev->fifo_depth - REG_READ(I2C_TXFLR);
if (cnt > free) {
cnt = free;
}
for (h = 0; h != cnt; h++) {
REG_WRITE(I2C_DATA_CMD, (dev->tx_data[dev->tx_count++]));
}
if (dev->tx_size == dev->tx_count) {
/* write buffer completely emptied */
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
/* mask tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
}
#ifdef __Xdmac
} else {
/* DMA TX xfer done */
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
/* call user callback function, if any */
dev->tx_data = NULL;
if (dev->tx_cb != NULL) {
dev->tx_cb(dev_id);
}
}
#endif
}
static _Interrupt void i2c_slv0_stop_det_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, avail = 0;
if (dev->handling_rx == 1) {
avail = REG_READ(I2C_RXFLR);
if (dev->rx_data == NULL) {
if (avail == 0) { /* all data processed */
dev->handling_rx = 0;
} else { /* still data in fifo to process, new data will not become available anymore */
dev->stop_detected = 1;
}
} else {
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) { /* disable DMA transfer and determine how much data has been transferred */
uint32_t ctrl;
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_chan_desc_get_ctrl(dev->dmarxchanid, &ctrl);
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc_get_ctrl(dev->dmarxchanid, &ctrl);
} else {
_dma_chan_desc_aux_get_ctrl(dev->dmarxchanid, &ctrl);
}
dev->rx_count =
((dev->rx_size - 1) -
((ctrl >> I2C_SLV_DMA_CTRL_SIZE_POS) & 0x1fff));
}
#endif
/* read remaining data from fifo */
cnt = dev->rx_size - dev->rx_count;
if (cnt < avail) { /* after reading, still data in fifo to process, new data will not become available anymore */
dev->stop_detected = 1;
} else if (cnt == avail) { /* after reading, all data processed */
dev->handling_rx = 0;
} else { /* after reading, all data processed, rx buffer not completely filled */
cnt = avail;
dev->handling_rx = 0;
}
for (h = 0; h != cnt; h++) {
dev->rx_data[dev->rx_count++] = REG_READ(I2C_DATA_CMD);
}
if (dev->handling_rx == 0) {
if (dev->rx_size != dev->rx_count) { /* read buffer NOT completely filled */
*(dev->p_rxsize) = dev->rx_count;
}
}
/* slave rx done */
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
/* mask rx-avail interrupt, if not done yet */
val = REG_READ(I2C_INTR_MASK) & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
}
if (dev->handling_tx == 1) {
dev->handling_tx = 0;
if (dev->tx_data != NULL) {
/* slave tx done */
*(dev->p_txsize) = dev->tx_count - REG_READ(I2C_TXFLR);
dev->tx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
}
REG_READ(I2C_CLR_STOP_DET);
}
static _Interrupt void i2c_slv0_rd_req_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0;
if (dev->tx_data != NULL) {
dev->rd_req_detected = 1;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write data into (empty) fifo */
cnt = dev->tx_size - dev->tx_count;
if (cnt > dev->fifo_depth) {
cnt = dev->fifo_depth;
}
for (h = 0; h != cnt; h++) {
REG_WRITE(I2C_DATA_CMD, (dev->tx_data[dev->tx_count++]));
}
if (dev->tx_size == dev->tx_count) { /* write buffer completely emptied */
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
} else {
/* unmask interrupts: tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
}
#ifdef __Xdmac
} else { /* have DMAC fill the fifo */
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
#endif
} else {
/* no data available for tx --> the only thing to do is returning any data */
REG_WRITE(I2C_DATA_CMD, 0xff);
}
REG_READ(I2C_CLR_RD_REQ);
}
#endif

View File

@@ -1,491 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "arc/arc_exception.h"
#include "device/subsystem/i2c_master.h"
#include "device/subsystem/ss_i2c_master.h"
#include "device/subsystem/i2c_priv.h"
#define REG_READ(x) arc_aux_read((ctx->reg_base + x))
#define REG_WRITE(x, y) arc_aux_write((ctx->reg_base + x), y)
/**
* @fn int32_t ss_iic_master_putready(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief Test whether iic is ready to write, 1 ready, 0 not ready
*/
Inline int32_t ss_iic_master_putready(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t status = REG_READ(I2C_STATUS);
return ((status & IC_STATUS_TFNF) != 0);
}
/**
* @fn int32_t ss_iic_master_getready(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief test whether iic is ready to receive, 1 ready, 0 not ready
*/
Inline int32_t ss_iic_master_getready(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t status = REG_READ(I2C_STATUS);
return ((status & IC_STATUS_RFNE) != 0);
}
/**
* @fn void ss_iic_mask_interrupt(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t mask)
* @brief Mask iic interrupt
*/
Inline void ss_iic_mask_interrupt(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t mask)
{
uint32_t intr_mask = REG_READ(I2C_INTR_MASK);
REG_WRITE(I2C_INTR_MASK, intr_mask & (~mask));
}
static void ss_iic_master_enable_device(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
DEV_IIC_INFO *info = ctx->info;
uint32_t enable = REG_READ(I2C_ENABLE);
if (((enable & 0x1) & DEV_ENABLED) == 0) {
REG_WRITE(I2C_ENABLE, (enable | 0x1));
info->status |= DEV_ENABLED;
}
}
static void ss_iic_master_disable_device(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable & (~(0x1))));
while ((0x1 & REG_READ(I2C_ENABLE_STATUS)) != 0) {
;
}
}
/* reset IIC master */
static void ss_iic_master_reset_device(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
DEV_IIC_INFO *info = ctx->info;
io_i2c_master_close(ctx->dev_id);
info->next_cond = IIC_MODE_STOP;
info->cur_state = IIC_FREE;
info->err_state = IIC_ERR_NONE;
ctx->flags = 0;
io_i2c_master_open(ctx->dev_id);
}
/** disable iic master interrupt for transmit or receive */
static void ss_iic_master_dis_cbr(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t cbrtn)
{
switch (cbrtn) {
case SS_IIC_MASTER_RDY_SND:
ss_iic_mask_interrupt(ctx, R_TX_EMPTY);
break;
case SS_IIC_MASTER_RDY_RCV:
ss_iic_mask_interrupt(ctx, R_TX_EMPTY | R_RX_FULL);
break;
default:
break;
}
}
/**
* @fn void ss_iic_master_flush_tx(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief flush TX FIFO
*/
Inline void ss_iic_master_flush_tx(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
}
/**
* @fn int32_t ss_iic_master_flush_rx(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief Flush RX FIFO
*/
Inline void ss_iic_master_flush_rx(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
}
/**
* @fn uint32_t ss_iic_master_get_txavail(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief Get available transmit FIFO count
*/
Inline uint32_t ss_iic_master_get_txavail(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t flr = REG_READ(I2C_TXFLR);
return (int32_t)(IC_TX_RX_FIFO_SIZE - flr);
}
/**
* @fn ss_iic_master_get_rxavail(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief Get available receive FIFO count
*/
Inline uint32_t ss_iic_master_get_rxavail(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t flr = REG_READ(I2C_RXFLR);
return (int32_t)flr;
}
int32_t ss_iic_master_close(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
int32_t ret = E_OK;
DEV_IIC_INFO *info = ctx->info;
if (info->opn_cnt > 0) {
info->opn_cnt = 0;
io_i2c_master_close(ctx->dev_id);
int_disable(ctx->int_err);
int_disable(ctx->int_rx_avail);
int_disable(ctx->int_tx_req);
int_disable(ctx->int_stop_det);
} else {
ret = E_CLSED;
}
return ret;
}
int32_t ss_iic_master_control(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
uint32_t val32;
uint32_t arg;
uint32_t dev_id = ctx->dev_id;
DEV_IIC_INFO *iic_info_ptr = ctx->info;
io_cb_t callback;
switch (ctrl_cmd) {
case IIC_CMD_GET_STATUS:
SS_IIC_MASTER_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = iic_info_ptr->status;
break;
case IIC_CMD_ENA_DEV:
ss_iic_master_enable_device(ctx);
break;
case IIC_CMD_DIS_DEV:
ss_iic_master_disable_device(ctx);
break;
case IIC_CMD_RESET:
ss_iic_master_reset_device(ctx);
break;
case IIC_CMD_FLUSH_TX:
ss_iic_master_flush_tx(ctx);
break;
case IIC_CMD_FLUSH_RX:
ss_iic_master_flush_rx(ctx);
break;
case IIC_CMD_SET_ADDR_MODE:
val32 = (uint32_t)param;
SS_IIC_MASTER_CHECK_EXP((val32 == IIC_7BIT_ADDRESS) || (val32 == IIC_10BIT_ADDRESS), E_PAR);
if (val32 == IIC_10BIT_ADDRESS) {
arg = 1;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_10BIT_ADDR, &arg);
iic_info_ptr->addr_mode = IIC_10BIT_ADDRESS;
} else {
arg = 0;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_10BIT_ADDR, &arg);
iic_info_ptr->addr_mode = IIC_7BIT_ADDRESS;
}
iic_info_ptr->addr_mode = val32;
break;
case IIC_CMD_GET_RXAVAIL:
SS_IIC_MASTER_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = ss_iic_master_get_rxavail(ctx);
break;
case IIC_CMD_GET_TXAVAIL:
SS_IIC_MASTER_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = ss_iic_master_get_txavail(ctx);
break;
case IIC_CMD_SET_TXCB:
SS_IIC_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
callback.cb = param;
io_i2c_master_ioctl(dev_id, IO_SET_CB_TX, &callback);
break;
case IIC_CMD_SET_RXCB:
SS_IIC_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
callback.cb = param;
io_i2c_master_ioctl(dev_id, IO_SET_CB_RX, &callback);
break;
case IIC_CMD_SET_ERRCB:
SS_IIC_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
callback.cb = param;
io_i2c_master_ioctl(dev_id, IO_SET_CB_ERR, &callback);
break;
case IIC_CMD_ABORT_TX:
ercd = E_NOSPT;
break;
case IIC_CMD_ABORT_RX:
ercd = E_NOSPT;
break;
case IIC_CMD_SET_TXINT:
val32 = (uint32_t)param;
if (val32 == 0) {
ss_iic_master_dis_cbr(ctx, SS_IIC_MASTER_RDY_SND);
} else {
ss_iic_master_dis_cbr(ctx, SS_IIC_MASTER_RDY_SND);
}
break;
case IIC_CMD_SET_RXINT:
val32 = (uint32_t)param;
if (val32 == 0) {
ss_iic_master_dis_cbr(ctx, SS_IIC_MASTER_RDY_RCV);
} else {
ss_iic_master_dis_cbr(ctx, SS_IIC_MASTER_RDY_RCV);
}
break;
case IIC_CMD_SET_TXINT_BUF:
ercd = E_NOSPT;
break;
case IIC_CMD_SET_RXINT_BUF:
ercd = E_NOSPT;
break;
case IIC_CMD_MST_SET_SPEED_MODE:
val32 = (uint32_t)param;
SS_IIC_MASTER_CHECK_EXP((val32 >= IIC_SPEED_STANDARD) && (val32 <= IIC_SPEED_FAST), E_PAR);
if (val32 == IIC_SPEED_STANDARD) {
arg = 1;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_SPEED, &arg);
iic_info_ptr->speed_mode = IIC_SPEED_STANDARD;
} else {
arg = 2;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_SPEED, &arg);
iic_info_ptr->speed_mode = IIC_SPEED_FAST;
}
break;
case IIC_CMD_MST_SET_TAR_ADDR:
if (iic_info_ptr->addr_mode == IIC_7BIT_ADDRESS) {
val32 = ((uint32_t)param) & IIC_7BIT_ADDRESS_MASK;
} else {
val32 = ((uint32_t)param) & IIC_10BIT_ADDRESS_MASK;
}
if (val32 != iic_info_ptr->tar_addr) {
arg = val32;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_TARGET_ADDR, &arg);
iic_info_ptr->tar_addr = val32;
}
break;
case IIC_CMD_MST_SET_NEXT_COND:
val32 = (uint32_t) param;
if (val32 == IIC_MODE_STOP) {
arg = I2C_STOP_CMD;
} else if (val32 == IIC_MODE_RESTART) {
arg = I2C_RESTART_CMD;
} else {
arg = 0;
}
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_NEXT_COND, &arg);
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
/* param: speed mode, 1-standard mode, 2-fast mode, 2 as default in hardware */
int32_t ss_iic_master_open(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t param)
{
int32_t ercd = E_OK;
uint32_t dev_id = ctx->dev_id;
DEV_IIC_INFO *info = ctx->info;
io_cb_t callback;
int32_t int_e = 0;
uint32_t arg;
SS_IIC_MASTER_CHECK_EXP((param >= IIC_SPEED_STANDARD) && (param <= IIC_SPEED_FAST), E_PAR);
if (info->opn_cnt == 0) {
SS_IIC_MASTER_CHECK_EXP(io_i2c_master_open(dev_id) == 0, E_SYS);
if (param == IIC_SPEED_STANDARD) {
arg = 1;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_SPEED, &arg);
info->speed_mode = IIC_SPEED_STANDARD;
} else {
arg = 2;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_SPEED, &arg);
info->speed_mode = IIC_SPEED_FAST;
}
callback.cb = (IO_CB_FUNC)ctx->int_rx_cb;
io_i2c_master_ioctl(dev_id, IO_SET_CB_RX, &callback);
callback.cb = (IO_CB_FUNC)ctx->int_tx_cb;
io_i2c_master_ioctl(dev_id, IO_SET_CB_TX, &callback);
callback.cb = (IO_CB_FUNC)ctx->int_err_cb;
io_i2c_master_ioctl(dev_id, IO_SET_CB_ERR, &callback);
info->opn_cnt++;
info->addr_mode = IIC_7BIT_ADDRESS;
info->mode = DEV_MASTER_MODE;
info->tar_addr &= IIC_7BIT_ADDRESS_MASK;
ctx->flags = 0;
/* enable interrupt */
int_e = int_e | int_enable(ctx->int_err);
int_e = int_e | int_enable(ctx->int_rx_avail);
int_e = int_e | int_enable(ctx->int_tx_req);
int_e = int_e | int_enable(ctx->int_stop_det);
if (int_e != 0) {
ercd = E_PAR;
}
} else {
ercd = E_OPNED;
}
error_exit:
return ercd;
}
int32_t ss_iic_master_write(SS_IIC_MASTER_DEV_CONTEXT *ctx, const void *data, uint32_t len)
{
uint32_t xlen;
uint32_t dev_id = ctx->dev_id;
if (ctx->flags) {
return E_NORES;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* because the bottom driver is simply interrupt driven
*/
return E_SYS;
}
xlen = len;
ctx->flags = SS_IIC_MASTER_FLAG_TX;
io_i2c_master_write(dev_id, (uint8_t *)data, &xlen);
/* wait finished: i2c master int enable & no cpu lock */
while (ctx->flags & SS_IIC_MASTER_FLAG_TX) {
;
}
if (ctx->flags & SS_IIC_MASTER_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
return len;
}
int32_t ss_iic_master_read(SS_IIC_MASTER_DEV_CONTEXT *ctx, const void *data, uint32_t len)
{
uint32_t xlen;
uint32_t dev_id = ctx->dev_id;
if (ctx->flags) {
return E_NORES;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* because the bottom driver is simply interrupt driven
*/
return E_SYS;
}
xlen = len;
ctx->flags = SS_IIC_MASTER_FLAG_RX;
io_i2c_master_read(dev_id, (uint8_t *)data, &xlen);
/* wait finished: i2c master int enable & no cpu lock */
while (ctx->flags & SS_IIC_MASTER_FLAG_RX) {
;
}
if (ctx->flags & SS_IIC_MASTER_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
return len;
}
void ss_iic_master_tx_cb(SS_IIC_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_IIC_INFO *info = ctx->info;
if (ctx->flags & SS_IIC_MASTER_FLAG_TX) {
ctx->flags &= ~SS_IIC_MASTER_FLAG_TX;
if (info->iic_cbs.tx_cb) {
info->iic_cbs.tx_cb(info);
}
}
}
void ss_iic_master_rx_cb(SS_IIC_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_IIC_INFO *info = ctx->info;
if (ctx->flags & SS_IIC_MASTER_FLAG_RX) {
ctx->flags &= ~SS_IIC_MASTER_FLAG_RX;
if (info->iic_cbs.rx_cb) {
info->iic_cbs.rx_cb(info);
}
}
}
void ss_iic_master_err_cb(SS_IIC_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_IIC_INFO *info = ctx->info;
ctx->flags |= SS_IIC_MASTER_FLAG_ERROR;
if (info->iic_cbs.err_cb) {
info->iic_cbs.err_cb(info);
}
}

View File

@@ -1,949 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include "device/subsystem/spi_slave.h"
#include "device/subsystem/spi_priv.h"
#include "io_config.h"
#include "apexextensions.h"
/* local defines (!!) */
#define SPI_TRANSMIT_RECEIVE_MODE (0)
#define SPI_TRANSMIT_ONLY_MODE (1)
#define SPI_RECEIVE_ONLY_MODE (2)
#ifdef IO_SPI_SLV0_PRESENT
#define SPI_DEV_PRESENT
#endif
#ifdef IO_SPI_SLV1_PRESENT
#define SPI_DEV_PRESENT
#endif
#ifdef IO_SPI_SLV2_PRESENT
#define SPI_DEV_PRESENT
#endif
#ifdef IO_SPI_SLV3_PRESENT
#define SPI_DEV_PRESENT
#endif
#ifdef SPI_DEV_PRESENT
#define SPI_MAX_CNT (4)
static void spi_slv_rx_ISR_proc(uint32_t dev_id);
static void spi_slv_tx_ISR_proc(uint32_t dev_id);
static void spi_slv_idle_ISR_proc(uint32_t dev_id);
static void spi_slv_err_ISR_proc(uint32_t dev_id);
#ifdef IO_SPI_SLV0_PRESENT
static _Interrupt void spi_slv0_rx_ISR()
{
spi_slv_rx_ISR_proc(0);
}
static _Interrupt void spi_slv0_tx_ISR()
{
spi_slv_tx_ISR_proc(0);
}
static _Interrupt void spi_slv0_idle_ISR()
{
spi_slv_idle_ISR_proc(0);
}
static _Interrupt void spi_slv0_err_ISR()
{
spi_slv_err_ISR_proc(0);
}
#endif
#ifdef IO_SPI_SLV1_PRESENT
static _Interrupt void spi_slv1_rx_ISR()
{
spi_slv_rx_ISR_proc(1);
}
static _Interrupt void spi_slv1_tx_ISR()
{
spi_slv_tx_ISR_proc(1);
}
static _Interrupt void spi_slv1_idle_ISR()
{
spi_slv_idle_ISR_proc(1);
}
static _Interrupt void spi_slv1_err_ISR()
{
spi_slv_err_ISR_proc(1);
}
#endif
#ifdef IO_SPI_SLV2_PRESENT
static _Interrupt void spi_slv2_rx_ISR()
{
spi_slv_rx_ISR_proc(2);
}
static _Interrupt void spi_slv2_tx_ISR()
{
spi_slv_tx_ISR_proc(2);
}
static _Interrupt void spi_slv2_idle_ISR()
{
spi_slv_idle_ISR_proc(2);
}
static _Interrupt void spi_slv2_err_ISR()
{
spi_slv_err_ISR_proc(2);
}
#endif
#ifdef IO_SPI_SLV3_PRESENT
static _Interrupt void spi_slv3_rx_ISR()
{
spi_slv_rx_ISR_proc(3);
}
static _Interrupt void spi_slv3_tx_ISR()
{
spi_slv_tx_ISR_proc(3);
}
static _Interrupt void spi_slv3_idle_ISR()
{
spi_slv_idle_ISR_proc(3);
}
static _Interrupt void spi_slv3_err_ISR()
{
spi_slv_err_ISR_proc(3);
}
#endif
static void fill_txfifo(spi_info_pt dev);
static void retrieve_rxfifo(spi_info_pt dev);
#ifdef __Xdmac
static void create_dma_descriptors_rx(spi_info_pt dev, uint8_t *dest,
uint32_t size, uint32_t burst);
static void create_dma_descriptors_tx(spi_info_pt dev, uint8_t *src,
uint32_t size, uint32_t burst);
#endif
/* SPI slave devices private data structures */
static spi_info_pt spi_handles[SPI_MAX_CNT] = { 0 };
#ifdef __Xdmac
static _Uncached uint32_t spi_dmarx_descriptors[8 * SPI_MAX_CNT];
static _Uncached uint32_t spi_dmatx_descriptors[8 * SPI_MAX_CNT];
#endif
static spi_info_t spi_slave_devs[] = {
#ifdef IO_SPI_SLV0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_SPI_SLV0_CTRLR0,
#ifdef IO_SPI_SLV0_DMA_RX
.dmarxchanid = IO_SPI_SLV0_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_SPI_SLV0_DMA_TX
.dmatxchanid = IO_SPI_SLV0_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.rx_vector = IO_SPI_SLV0_INT_RX_AVAIL,
.tx_vector = IO_SPI_SLV0_INT_TX_REQ,
.idle_vector = IO_SPI_SLV0_INT_IDLE,
.err_vector = IO_SPI_SLV0_INT_ERR,
.rx_isr = spi_slv0_rx_ISR,
.tx_isr = spi_slv0_tx_ISR,
.idle_isr = spi_slv0_idle_ISR,
.err_isr = spi_slv0_err_ISR,
.log_xfer_size = (IO_SPI_SLV0_MAX_XFER_SIZE >> 4),
.max_xfer_size = (IO_SPI_SLV0_MAX_XFER_SIZE),
.fifo_depth = IO_SPI_SLV0_FS },
#endif
#ifdef IO_SPI_SLV1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_SPI_SLV1_CTRLR0,
#ifdef IO_SPI_SLV1_DMA_RX
.dmarxchanid = IO_SPI_SLV1_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_SPI_SLV1_DMA_TX
.dmatxchanid = IO_SPI_SLV1_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.rx_vector = IO_SPI_SLV1_INT_RX_AVAIL,
.tx_vector = IO_SPI_SLV1_INT_TX_REQ,
.idle_vector = IO_SPI_SLV1_INT_IDLE,
.err_vector = IO_SPI_SLV1_INT_ERR,
.rx_isr = spi_slv1_rx_ISR,
.tx_isr = spi_slv1_tx_ISR,
.idle_isr = spi_slv1_idle_ISR,
.err_isr = spi_slv1_err_ISR,
.log_xfer_size = (IO_SPI_SLV1_MAX_XFER_SIZE >> 4),
.max_xfer_size = (IO_SPI_SLV1_MAX_XFER_SIZE),
.fifo_depth = IO_SPI_SLV1_FS },
#endif
#ifdef IO_SPI_SLV2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_SPI_SLV2_CTRLR0,
#ifdef IO_SPI_SLV2_DMA_RX
.dmarxchanid = IO_SPI_SLV2_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_SPI_SLV2_DMA_TX
.dmatxchanid = IO_SPI_SLV2_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.rx_vector = IO_SPI_SLV2_INT_RX_AVAIL,
.tx_vector = IO_SPI_SLV2_INT_TX_REQ,
.idle_vector = IO_SPI_SLV2_INT_IDLE,
.err_vector = IO_SPI_SLV2_INT_ERR,
.rx_isr = spi_slv2_rx_ISR,
.tx_isr = spi_slv2_tx_ISR,
.idle_isr = spi_slv2_idle_ISR,
.err_isr = spi_slv2_err_ISR,
.log_xfer_size = (IO_SPI_SLV2_MAX_XFER_SIZE >> 4),
.max_xfer_size = (IO_SPI_SLV2_MAX_XFER_SIZE),
.fifo_depth = IO_SPI_SLV2_FS },
#endif
#ifdef IO_SPI_SLV3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_SPI_SLV3_CTRLR0,
#ifdef IO_SPI_SLV3_DMA_RX
.dmarxchanid = IO_SPI_SLV3_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_SPI_SLV3_DMA_TX
.dmatxchanid = IO_SPI_SLV3_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.rx_vector = IO_SPI_SLV3_INT_RX_AVAIL,
.tx_vector = IO_SPI_SLV3_INT_TX_REQ,
.idle_vector = IO_SPI_SLV3_INT_IDLE,
.err_vector = IO_SPI_SLV3_INT_ERR,
.rx_isr = spi_slv3_rx_ISR,
.tx_isr = spi_slv3_tx_ISR,
.idle_isr = spi_slv3_idle_ISR,
.err_isr = spi_slv3_err_ISR,
.log_xfer_size = (IO_SPI_SLV3_MAX_XFER_SIZE >> 4),
.max_xfer_size = (IO_SPI_SLV3_MAX_XFER_SIZE),
.fifo_depth = IO_SPI_SLV3_FS },
#endif
{ .instID = SPI_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
#define REG_WRITE_BITS(reg, x, y, len, pos) REG_WRITE(reg, ((((x) & ~((~(0xffffffff << len)) << pos)) \
| (((y) << pos) & ((~(0xffffffff << len)) << pos)))))
#define REG_GET_BITS(reg, len, pos) ((REG_READ(reg) >> pos) & ~(0xffffffff << len))
uint32_t io_spi_slave_open(uint32_t dev_id)
{
uint32_t h = 0;
spi_info_pt dev;
h = 0;
while ((spi_slave_devs[h].instID != dev_id)
&& (spi_slave_devs[h].instID != SPI_MAX_CNT)) {
h++;
}
if ((spi_slave_devs[h].instID == SPI_MAX_CNT) || (0 != spi_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
spi_handles[dev_id] = &spi_slave_devs[h];
dev = spi_handles[dev_id];
/* enable clock */
REG_WRITE(CLK_ENA, 0x1);
if (dev->max_xfer_size == 16) { /* 16-bits SPI; log_xfer_size == 1 */
dev->log_xfer_size = dev->max_xfer_size >> 4;
REG_WRITE_BITS(CTRL0, 0x0, 15, 4, 0);
} else {
/* 32-bits SPI; log_xfer_size == 2 */
dev->log_xfer_size = dev->max_xfer_size >> 4;
REG_WRITE_BITS(CTRL0, 0x0, 31, 5, 16);
}
/* mask RX-available and TX-empty interrupts, always mask TX-underflow */
REG_WRITE(IMR, ~(R_TX_EMPTY | R_RX_FULL | R_TX_UNDER));
dev->handling_rx = dev->handling_tx = 0;
_setvecti(dev->rx_vector, dev->rx_isr);
_setvecti(dev->tx_vector, dev->tx_isr);
_setvecti(dev->idle_vector, dev->idle_isr);
_setvecti(dev->err_vector, dev->err_isr);
#ifdef __Xdmac
dev->dmarxdescriptor = &spi_dmarx_descriptors[8 * h];
dev->dmatxdescriptor = &spi_dmatx_descriptors[8 * h];
if (dev->dmarxchanid != DMA_NONE) {
dev->dmarxdescriptor[1] = dev->dmarxdescriptor[5] =
dev->reg_base + DR;
dev->dmarxdescriptor[3] = (uint32_t) &(dev->dmarxdescriptor[4]);
dev->dmarxdescriptor[7] = 0;
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, dev->rx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, dev->err_isr);
}
if (dev->dmatxchanid != DMA_NONE) {
dev->dmatxdescriptor[2] = dev->dmatxdescriptor[6] =
dev->reg_base + DR;
dev->dmatxdescriptor[3] = (uint32_t) &(dev->dmatxdescriptor[4]);
dev->dmatxdescriptor[7] = 0;
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, dev->tx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, dev->err_isr);
}
#endif
REG_WRITE(SPIEN, 0x1);
return 0;
}
void io_spi_slave_close(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
REG_WRITE(IMR, 0);
REG_WRITE(SPIEN, 0);
REG_WRITE(CTRL0, 0x7);
REG_WRITE(TXFTLR, 0);
REG_WRITE(RXFTLR, 0);
REG_WRITE(IMR, 0xff);
/* gate clock */
REG_WRITE(CLK_ENA, 0);
_setvecti(dev->rx_vector, NULL);
_setvecti(dev->tx_vector, NULL);
_setvecti(dev->idle_vector, NULL);
_setvecti(dev->err_vector, NULL);
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmarxchanid);
}
if (dev->dmatxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmatxchanid);
}
#endif
dev->rx_cb = NULL;
dev->tx_cb = NULL;
dev->err_cb = NULL;
spi_handles[dev_id] = 0;
}
void io_spi_slave_read(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
dev->rx_size = *size;
dev->p_rxsize = size;
dev->rx_count = 0;
dev->rx_buff = (void *) data;
dev->handling_rx = 1;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* Enable RX-available and Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, (val | R_RX_FULL | R_IDLE));
#ifdef __Xdmac
} else { /* RX descriptor */
if (*size != 0) {
/* rx data available; at least one */
create_dma_descriptors_rx(dev, data, *size,
(1 + REG_READ(RXFTLR)));
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
/* enable the Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, val | R_IDLE);
}
}
#endif
}
void io_spi_slave_write(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
dev->tx_size = *size;
dev->tx_count = 0;
dev->tx_buff = (void *) data;
dev->handling_tx = 1;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write first bytes to fifo, assuming size > 0 */
fill_txfifo(dev);
/* Enable TX-empty, Idle interrupt, and (optional) RX-available */
if (REG_GET_BITS(CTRL0, 2, 8) == SPI_TRANSMIT_ONLY_MODE) {
val = REG_READ(IMR);
REG_WRITE(IMR, (val | R_TX_EMPTY | R_IDLE));
} else { /* TX-RX mode */
val = REG_READ(IMR);
REG_WRITE(IMR, (val | R_TX_EMPTY | R_IDLE | R_RX_FULL));
}
#ifdef __Xdmac
} else { /* TX descriptor */
if (*size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx(dev, data, *size,
(dev->fifo_depth -
REG_READ(TXFTLR)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
/* enable the Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, val | R_IDLE);
}
}
#endif
}
void io_spi_slave_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t regval;
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SPI_SLAVE_SET_RX_THRESHOLD:
REG_WRITE(RXFTLR, *((uint32_t *) arg));
break;
case IO_SPI_SLAVE_SET_TX_THRESHOLD:
REG_WRITE(TXFTLR, *((uint32_t *) arg));
break;
case IO_SPI_SLAVE_SET_PACKING:
{ /* DFS must be set prior applying this option */
regval = REG_READ(CTRL0);
if (*((uint32_t *) arg) == 0) { /* reset packing */
dev->log_xfer_size = dev->max_xfer_size >> 4;
} else { /* set packing */
if (dev->max_xfer_size == 32) { /* 32-bits SPI */
regval = (regval >> 16) & 0x01F; // Get DFS field from CTRL0 value
dev->log_xfer_size =
(regval == 15) ? 1 : (regval ==
7) ? 0 : dev->
max_xfer_size >> 4;
} else { /* 16-bits SPI */
regval = regval & 0x00F; // Get DFS field from CTRL0 value
dev->log_xfer_size =
(regval == 7) ? 0 : dev->max_xfer_size >> 4;
}
}
break;
}
default:
{
/* ioctl calls that require disabling of the SPI first */
REG_WRITE(SPIEN, 0);
regval = REG_READ(CTRL0);
switch (cmd) {
case IO_SPI_SLAVE_SET_TRANSFER_MODE:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 2, 8);
break;
case IO_SPI_SLAVE_SET_SCPH:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 1, 6);
break;
case IO_SPI_SLAVE_SET_SCPL:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 1, 7);
break;
case IO_SPI_SLAVE_SET_SRL_MODE:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 1, 11);
break;
case IO_SPI_SLAVE_SET_OUTPUT_ENABLE:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 1, 10);
break;
case IO_SPI_SLAVE_SET_DFS:
REG_WRITE_BITS(CTRL0, regval, ((*((uint32_t *) arg)) - 1),
(3 + dev->log_xfer_size),
((dev->log_xfer_size - 1) << 4));
break;
default:
break;
}
REG_WRITE(SPIEN, 0x1);
break;
}
}
}
static void spi_slv_rx_ISR_proc(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read remaining data from fifo */
retrieve_rxfifo(dev);
if (dev->rx_size <= (dev->rx_count << dev->log_xfer_size)) { /* read buffer completely filled, mask RX-avail interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, (val & ~R_RX_FULL));
}
#ifdef __Xdmac
} else {
uint32_t divisor = 0, remainder = 0;
/* DMA RX xfer done */
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_int_clear((0x1 << dev->dmarxchanid));
/* process final data, if it is a partial (half)word */
divisor = dev->rx_size >> dev->log_xfer_size;
remainder = dev->rx_size - (divisor << dev->log_xfer_size);
if (remainder != 0) {
uint32_t mask = ~((~0x0) << (remainder * 8));
if (dev->log_xfer_size == 1) {
((uint16_t *) (dev->rx_buff))[divisor] =
(((uint16_t *) (dev->
rx_buff))[divisor] & ~mask) | (dev->
dmarx_last16
& mask);
} else if (dev->log_xfer_size == 2) {
((uint32_t *) (dev->rx_buff))[divisor] =
(((uint32_t *) (dev->
rx_buff))[divisor] & ~mask) | (dev->
dmarx_last32
& mask);
}
}
}
#endif
}
static void spi_slv_tx_ISR_proc(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
if (dev->tx_size <= (dev->tx_count << dev->log_xfer_size)) {
/* no data left to put into the fifo, mask TX-request */
val = REG_READ(IMR);
REG_WRITE(IMR, (val & ~R_TX_EMPTY));
} else { /* write data into the fifo */
fill_txfifo(dev);
}
#ifdef __Xdmac
} else {
/* DMA TX xfer done */
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
}
#endif
}
static void spi_slv_idle_ISR_proc(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
if (dev->handling_tx == 1) {
if ((dev->tx_size <= (dev->tx_count << dev->log_xfer_size)) || (dev->dmatxchanid != DMA_NONE)) { /* buffer completely processed */
dev->handling_tx = 0;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
/* mask TX-empty (if not done yet) and Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, (val & ~R_TX_EMPTY & ~R_IDLE));
}
}
if (dev->handling_rx == 1) {
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read remaining data from fifo */
retrieve_rxfifo(dev);
#ifdef __Xdmac
}
#endif
if ((dev->rx_size <= (dev->rx_count << dev->log_xfer_size)) || (dev->dmarxchanid != DMA_NONE)) { /* buffer completely processed */
dev->handling_rx = 0;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
/* mask RX-available (if not done yet) and Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, (val & ~R_RX_FULL & ~R_IDLE));
}
}
/* clear idle interrupt */
REG_WRITE(ICR, R_IDLE);
}
static void spi_slv_err_ISR_proc(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
REG_WRITE(IMR, 0);
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
REG_WRITE(ICR, R_RX_OVER | R_RX_UNDER | R_TX_OVER | R_TX_UNDER);
}
static void fill_txfifo(spi_info_pt dev)
{
uint32_t cnt = 0, h = 0, free = 0;
cnt = dev->tx_size - (dev->tx_count << dev->log_xfer_size);
free = (dev->fifo_depth - REG_READ(TXFLR)) << dev->log_xfer_size;
if (cnt > free) {
cnt = free;
}
if (dev->log_xfer_size == 0) { /* 8-bits data */
for (h = 0; h != cnt; h++) {
REG_WRITE(DR, ((uint8_t *) (dev->tx_buff))[dev->tx_count++]);
}
} else if (dev->log_xfer_size == 1) { /* 16-bits data */
for (h = 0; h != cnt / 2; h++) {
REG_WRITE(DR, ((uint16_t *) (dev->tx_buff))[dev->tx_count++]);
}
/* if 2h != cnt: partial tx left at the end */
if (2 * h != cnt) {
REG_WRITE(DR,
((((uint16_t *) (dev->tx_buff))[dev->
tx_count++]) &
0x00ff));
}
} else { /* log_xfer_size == 2; 32-bits data */
for (h = 0; h != cnt / 4; h++) {
REG_WRITE(DR, ((uint32_t *) (dev->tx_buff))[dev->tx_count++]);
}
/* if 4h != cnt: partial tx left at the end */
if (4 * h != cnt) {
uint32_t mask32 = ~((~0x0) << ((cnt - 4 * h) * 8));
REG_WRITE(DR,
((((uint32_t *) (dev->tx_buff))[dev->
tx_count++]) &
mask32));
}
}
}
static void retrieve_rxfifo(spi_info_pt dev)
{
uint32_t cnt = 0, h = 0, avail = 0;
cnt = dev->rx_size - (dev->rx_count << dev->log_xfer_size);
avail = REG_READ(RXFLR) << dev->log_xfer_size;
if (cnt > avail) {
cnt = avail;
}
if (dev->log_xfer_size == 0) { /* 8-bits data */
for (h = 0; h != cnt; h++) {
((uint8_t *) (dev->rx_buff))[dev->rx_count++] =
(uint8_t) REG_READ(DR);
}
} else if (dev->log_xfer_size == 1) { /* 16-bits data */
for (h = 0; h != cnt / 2; h++) {
((uint16_t *) (dev->rx_buff))[dev->rx_count++] =
(uint16_t) REG_READ(DR);
}
/* if 2h != cnt: partial rx left at the end */
if (2 * h != cnt) {
((uint16_t *) (dev->rx_buff))[dev->rx_count] =
(((uint16_t *) (dev->rx_buff))[dev->
rx_count] & ~0x00ff) |
(REG_READ(DR) & 0x00ff);
dev->rx_count++;
}
} else { /* 32-bits data; log_xfer_size == 2 */
for (h = 0; h != cnt / 4; h++) {
((uint32_t *) (dev->rx_buff))[dev->rx_count++] = REG_READ(DR);
}
/* if 4h != cnt: partial rx left at the end */
if (4 * h != cnt) {
uint32_t mask32 = ~((~0x0) << ((cnt - 4 * h) * 8));
((uint32_t *) (dev->rx_buff))[dev->rx_count] =
(((uint32_t *) (dev->rx_buff))[dev->
rx_count] & ~mask32) |
(REG_READ(DR) & mask32);
dev->rx_count++;
}
}
}
#ifdef __Xdmac
#define SPI_SLV_DMA_RX_CTRL (0x80000017) /* am=b10, i=b0, dw/inc=b..., dtt=b10, r=b1, op=b11 */
#define SPI_SLV_DMA_RX_END_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b..., dtt=b10, r=b1, op=b01 */
#define SPI_SLV_DMA_RX_REM_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b..., dtt=b10, r=b1, op=b01 */
#define SPI_SLV_DMA_TX_CTRL (0x4000000f) /* am=b01, i=b0, dw/inc=b..., dtt=b01, r=b1, op=b11 */
#define SPI_SLV_DMA_TX_END_CTRL (0x6000000d) /* am=b01, i=b1, dw/inc=b..., dtt=b01, r=b1, op=b01 */
#define SPI_SLV_DMA_TX_REM_CTRL (0x6000000d) /* am=b01, i=b1, dw/inc=b..., dtt=b01, r=b1, op=b01 */
#define SPI_SLV_DMA_CTRL_DWINC_POS (5)
#define SPI_SLV_DMA_CTRL_SIZE_POS (8)
#define SPI_SLV_DMA_CTRL_XFER_POS (21)
#define SPI_SLV_DMA_FORCE_INT (0x1 << 29)
static void create_dma_descriptors_rx(spi_info_pt dev, uint8_t *dest,
uint32_t size, uint32_t burst)
{
uint32_t divisor = 0, remainder = 0;
divisor = size >> dev->log_xfer_size;
remainder = size - (divisor << dev->log_xfer_size);
if (dev->log_xfer_size == 0) {
dev->dmarxdescriptor[0] =
SPI_SLV_DMA_RX_END_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS);
dev->dmarxdescriptor[2] = (uint32_t) dest + (size - 1);
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[3] = 0;
}
} else if ((divisor > 0) && (remainder == 0)) {
dev->dmarxdescriptor[0] =
SPI_SLV_DMA_RX_END_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
dev->dmarxdescriptor[2] = (uint32_t) dest + (size - 1);
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[3] = 0;
}
} else if ((divisor > 0) && (remainder > 0)) {
dev->dmarxdescriptor[0] =
SPI_SLV_DMA_RX_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1 - remainder) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
dev->dmarxdescriptor[2] = (uint32_t) dest + (size - 1 - remainder);
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[0] |= SPI_SLV_DMA_FORCE_INT;
dev->dmarxdescriptor[3] =
(uint32_t) &(dev->dmarxdescriptor[4]);
}
dev->dmarxdescriptor[4 + 0] =
SPI_SLV_DMA_RX_REM_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((2 * dev->log_xfer_size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
if (dev->log_xfer_size == 1) {
dev->dmarxdescriptor[4 + 2] =
(uint32_t) &(dev->dmarx_last16) + 1;
} else {
dev->dmarxdescriptor[4 + 2] =
(uint32_t) &(dev->dmarx_last32) + 3;
}
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[4 + 3] = 0;
}
} else { /* divisor == 0, remainder > 0 */
dev->dmarxdescriptor[0] =
SPI_SLV_DMA_RX_REM_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((2 * dev->log_xfer_size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
if (dev->log_xfer_size == 1) {
dev->dmarxdescriptor[2] = (uint32_t) &(dev->dmarx_last16) + 1;
} else {
dev->dmarxdescriptor[2] = (uint32_t) &(dev->dmarx_last32) + 3;
}
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[3] = 0;
}
}
}
static void create_dma_descriptors_tx(spi_info_pt dev, uint8_t *src,
uint32_t size, uint32_t burst)
{
uint32_t divisor = 0, remainder = 0;
divisor = size >> dev->log_xfer_size;
remainder = size - (divisor << dev->log_xfer_size);
if (dev->log_xfer_size == 1) {
dev->dmatx_last16 =
((uint16_t *) (dev->
tx_buff))[divisor] & ~((~0x0) << (remainder *
8));
} else {
dev->dmatx_last32 =
((uint32_t *) (dev->
tx_buff))[divisor] & ~((~0x0) << (remainder *
8));
}
if (dev->log_xfer_size == 0) {
dev->dmatxdescriptor[0] =
SPI_SLV_DMA_TX_END_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) src + (size - 1);
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[3] = 0;
}
} else if ((divisor > 0) && (remainder == 0)) {
dev->dmatxdescriptor[0] =
SPI_SLV_DMA_TX_END_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
dev->dmatxdescriptor[1] = (uint32_t) src + (size - 1);
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[3] = 0;
}
} else if ((divisor > 0) && (remainder > 0)) {
dev->dmatxdescriptor[0] =
SPI_SLV_DMA_TX_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1 - remainder) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
dev->dmatxdescriptor[1] = (uint32_t) src + (size - 1 - remainder);
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[0] |= SPI_SLV_DMA_FORCE_INT;
dev->dmatxdescriptor[3] =
(uint32_t) &(dev->dmatxdescriptor[4]);
}
dev->dmatxdescriptor[4 + 0] =
SPI_SLV_DMA_TX_REM_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((2 * dev->log_xfer_size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
if (dev->log_xfer_size == 1) {
dev->dmatxdescriptor[4 + 1] =
(uint32_t) &(dev->dmatx_last16) + 1;
} else {
dev->dmatxdescriptor[4 + 1] =
(uint32_t) &(dev->dmatx_last32) + 3;
}
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[4 + 3] = 0;
}
} else { /* divisor == 0, remainder > 0 */
dev->dmatxdescriptor[0] =
SPI_SLV_DMA_TX_REM_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((2 * dev->log_xfer_size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
if (dev->log_xfer_size == 1) {
dev->dmatxdescriptor[1] = (uint32_t) &(dev->dmatx_last16) + 1;
} else {
dev->dmatxdescriptor[1] = (uint32_t) &(dev->dmatx_last32) + 3;
}
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[3] = 0;
}
}
}
#endif
#endif

View File

@@ -1,416 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1) Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "arc/arc_exception.h"
#include "device/subsystem/spi_master.h"
#include "device/subsystem/ss_spi_master.h"
int32_t ss_spi_master_open(SS_SPI_MASTER_DEV_CONTEXT *ctx, uint32_t mode, uint32_t param)
{
uint32_t dev_id = ctx->dev_id;
DEV_SPI_INFO *info = ctx->info;
io_cb_t callback;
uint32_t val;
if (mode != DEV_MASTER_MODE) {
return E_PAR;
}
if (info->opn_cnt > 0) {
if (param != info->freq) {
return E_OPNED;
} else {
return E_OK;
}
}
if (io_spi_master_open(dev_id)) {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->int_rx_cb;
io_spi_master_ioctl(dev_id, IO_SET_CB_RX, &callback);
callback.cb = (IO_CB_FUNC)ctx->int_tx_cb;
io_spi_master_ioctl(dev_id, IO_SET_CB_TX, &callback);
callback.cb = (IO_CB_FUNC)ctx->int_err_cb;
io_spi_master_ioctl(dev_id, IO_SET_CB_ERR, &callback);
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_DFS, &info->dfs);
val = 1;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_PACKING, &val);
info->freq = param;
param = ctx->bus_freq / param;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_BAUD, &param);
info->opn_cnt++;
ctx->flags = 0;
/* cs pin will toggle when FIFO is empty, to avoid this, spi master operation
* should not be interruptted by others. so set int pri to INT_PRI_MIN
*/
int_enable(ctx->intno_rx);
int_pri_set(ctx->intno_rx, INT_PRI_MIN);
int_enable(ctx->intno_tx);
int_pri_set(ctx->intno_tx, INT_PRI_MIN);
int_enable(ctx->intno_idle);
int_pri_set(ctx->intno_idle, INT_PRI_MIN);
int_enable(ctx->intno_err);
int_pri_set(ctx->intno_err, INT_PRI_MIN);
return E_OK;
}
int32_t ss_spi_master_close(SS_SPI_MASTER_DEV_CONTEXT *ctx)
{
DEV_SPI_INFO *info = ctx->info;
info->opn_cnt--;
if (info->opn_cnt == 0) {
io_spi_master_close(ctx->dev_id);
int_disable(ctx->intno_rx);
int_disable(ctx->intno_tx);
int_disable(ctx->intno_idle);
int_disable(ctx->intno_err);
info->status = DEV_DISABLED;
ctx->flags = 0;
} else {
return E_OPNED;
}
return E_OK;
}
int32_t ss_spi_master_control(SS_SPI_MASTER_DEV_CONTEXT *ctx, uint32_t ctrl_cmd, void *param)
{
uint32_t dev_id = ctx->dev_id;
DEV_SPI_INFO *info = ctx->info;
uint32_t val32 = (uint32_t)param;
DEV_BUFFER *buf = (DEV_BUFFER *)param;
DEV_SPI_TRANSFER *spi_xfer = &(info->xfer);
switch (ctrl_cmd) {
case SPI_CMD_SET_TXINT_BUF:
if (buf && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
DEV_SPI_XFER_SET_TXBUF(spi_xfer, buf->buf, buf->ofs, buf->len);
ctx->flags |= SS_SPI_MASTER_FLAG_TX_READY;
} else {
return E_NOSPT;
}
break;
case SPI_CMD_SET_TXINT:
if (val32 && (ctx->flags & SS_SPI_MASTER_FLAG_TX_READY) && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
ctx->flags |= SS_SPI_MASTER_FLAG_BUSY;
val32 = SPI_TRANSMIT_ONLY_MODE;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_write(dev_id, spi_xfer->tx_buf + spi_xfer->tx_ofs,
&spi_xfer->tx_len);
} else {
return E_SYS;
}
break;
case SPI_CMD_SET_RXINT_BUF:
if (buf && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
DEV_SPI_XFER_SET_RXBUF(spi_xfer, buf->buf, buf->ofs, buf->len);
ctx->flags |= SS_SPI_MASTER_FLAG_RX_READY;
} else {
return E_NOSPT;
}
break;
case SPI_CMD_SET_RXINT:
if (val32 && (ctx->flags & SS_SPI_MASTER_FLAG_RX_READY) && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
ctx->flags |= SS_SPI_MASTER_FLAG_BUSY;
val32 = SPI_RECEIVE_ONLY_MODE;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, spi_xfer->rx_buf + spi_xfer->rx_ofs,
&spi_xfer->rx_len);
} else {
return E_SYS;
}
break;
case SPI_CMD_TRANSFER_INT:
if (param != NULL && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
ctx->flags = SS_SPI_MASTER_FLAG_BUSY | SS_SPI_MASTER_FLAG_TX_RX;
*spi_xfer = *((DEV_SPI_TRANSFER *)param);
if (spi_xfer->rx_len == 0) {
val32 = SPI_TRANSMIT_ONLY_MODE;
ctx->flags |= SS_SPI_MASTER_FLAG_TX_READY;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_write(dev_id, spi_xfer->tx_buf, &spi_xfer->tx_len);
} else if (spi_xfer->tx_len == 0) {
val32 = SPI_RECEIVE_ONLY_MODE;
ctx->flags |= SS_SPI_MASTER_FLAG_RX_READY;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, spi_xfer->rx_buf, &spi_xfer->rx_len);
} else if (spi_xfer->rx_ofs == spi_xfer->tx_len && spi_xfer->tx_ofs == 0) {
ctx->flags |= (SS_SPI_MASTER_FLAG_RX_READY | SS_SPI_MASTER_FLAG_TX_READY);
val32 = SPI_RECEIVE_AFTER_TRANSMIT_MODE;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, spi_xfer->rx_buf, &spi_xfer->rx_len);
io_spi_master_write(dev_id, spi_xfer->tx_buf, &spi_xfer->tx_len);
} else {
if (spi_xfer->tx_ofs != 0 || spi_xfer->rx_ofs != 0) {
return E_NOSPT;
}
ctx->flags |= (SS_SPI_MASTER_FLAG_RX_READY | SS_SPI_MASTER_FLAG_TX_READY);
DEV_SPI_XFER_INIT(spi_xfer);
val32 = SPI_TRANSMIT_RECEIVE_MODE;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, spi_xfer->rx_buf, &spi_xfer->tot_len);
io_spi_master_write(dev_id, spi_xfer->tx_buf, &spi_xfer->tot_len);
}
} else {
return E_NOSPT;
}
break;
case SPI_CMD_TRANSFER_POLLING:
if (param != NULL && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
spi_xfer = (DEV_SPI_TRANSFER *)param;
while (spi_xfer != NULL) {
ctx->flags = SS_SPI_MASTER_FLAG_BUSY;
DEV_SPI_XFER_INIT(spi_xfer);
io_spi_master_polling(dev_id, spi_xfer);
ctx->flags &= ~SS_SPI_MASTER_FLAG_BUSY;
spi_xfer = spi_xfer->next;
}
} else {
return E_NOSPT;
}
break;
case SPI_CMD_SET_TXCB:
info->spi_cbs.tx_cb = param;
break;
case SPI_CMD_SET_RXCB:
info->spi_cbs.rx_cb = param;
break;
case SPI_CMD_SET_XFERCB:
info->spi_cbs.xfer_cb = param;
break;
case SPI_CMD_SET_ERRCB:
info->spi_cbs.err_cb = param;
break;
case SPI_CMD_SET_CLK_MODE:
switch (val32) {
case SPI_CPOL_0_CPHA_0:
val32 = 0;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPL, &val32);
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPH, &val32);
break;
case SPI_CPOL_0_CPHA_1:
val32 = 0;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPL, &val32);
val32 = 1;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPH, &val32);
break;
case SPI_CPOL_1_CPHA_0:
val32 = 1;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPL, &val32);
val32 = 0;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPH, &val32);
break;
case SPI_CPOL_1_CPHA_1:
val32 = 1;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPL, &val32);
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPH, &val32);
break;
}
break;
case SPI_CMD_SET_DFS:
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_DFS, &val32);
break;
case SPI_CMD_MST_SET_FREQ:
info->freq = val32;
val32 = ctx->bus_freq / val32;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_BAUD, &val32);
break;
case SPI_CMD_MST_SEL_DEV:
info->slave = val32;
val32 = (1 << val32);
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SE, &val32);
break;
case SPI_CMD_MST_DSEL_DEV:
val32 = info->slave & (~(1 << val32));
info->slave = SPI_SLAVE_NOT_SELECTED;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SE, &val32);
break;
default:
return E_NOSPT;
}
return E_OK;
}
int32_t ss_spi_master_write(SS_SPI_MASTER_DEV_CONTEXT *ctx, const void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
uint32_t len_ = len;
uint32_t val32 = SPI_TRANSMIT_ONLY_MODE;
/* spi busy */
if (ctx->flags & SS_SPI_MASTER_FLAG_BUSY) {
return E_NORES;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* Beacue the bottom drvier is simply interrupt driven
*/
return E_SYS;
}
ctx->flags = SS_SPI_MASTER_FLAG_BUSY;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_write(dev_id, (uint8_t *) data, &len_);
/* wait finished: spi int enable & no cpu lock */
while (ctx->flags & SS_SPI_MASTER_FLAG_BUSY) {
;
}
if (ctx->flags & SS_SPI_MASTER_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
return E_OK;
}
int32_t ss_spi_master_read(SS_SPI_MASTER_DEV_CONTEXT *ctx, void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
uint32_t len_ = len;
uint32_t val32 = SPI_RECEIVE_ONLY_MODE;
if (ctx->flags & SS_SPI_MASTER_FLAG_BUSY) {
return E_NORES;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* Beacue the bottom drvier is simply interrupt driven
*/
return E_SYS;
}
ctx->flags = SS_SPI_MASTER_FLAG_BUSY;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, (uint8_t *)data, &len_);
while (ctx->flags & SS_SPI_MASTER_FLAG_BUSY) {
;
}
if (ctx->flags & SS_SPI_MASTER_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
return 0;
}
void ss_spi_master_tx_cb(SS_SPI_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_SPI_INFO *info = ctx->info;
DEV_SPI_TRANSFER *spi_xfer = &(info->xfer);
if (ctx->flags & SS_SPI_MASTER_FLAG_TX_RX) {
if (spi_xfer->rx_len == 0) {
ctx->flags &= ~SS_SPI_MASTER_FLAG_TX_RX;
if (ctx->flags & SS_SPI_MASTER_FLAG_TX_READY && info->spi_cbs.xfer_cb) {
info->spi_cbs.xfer_cb(info);
}
}
} else if (ctx->flags & SS_SPI_MASTER_FLAG_TX_READY && info->spi_cbs.tx_cb) {
info->spi_cbs.tx_cb(info);
}
ctx->flags &= ~(SS_SPI_MASTER_FLAG_TX_READY | SS_SPI_MASTER_FLAG_BUSY);
}
void ss_spi_master_rx_cb(SS_SPI_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_SPI_INFO *info = ctx->info;
if (ctx->flags & SS_SPI_MASTER_FLAG_TX_RX) {
if (ctx->flags & SS_SPI_MASTER_FLAG_RX_READY && info->spi_cbs.xfer_cb) {
info->spi_cbs.xfer_cb(info);
}
ctx->flags &= ~(SS_SPI_MASTER_FLAG_RX_READY | SS_SPI_MASTER_FLAG_TX_READY |
SS_SPI_MASTER_FLAG_BUSY | SS_SPI_MASTER_FLAG_TX_RX);
} else {
if (ctx->flags & SS_SPI_MASTER_FLAG_RX_READY && info->spi_cbs.rx_cb) {
info->spi_cbs.rx_cb(info);
}
ctx->flags &= ~(SS_SPI_MASTER_FLAG_RX_READY | SS_SPI_MASTER_FLAG_BUSY);
}
}
void ss_spi_master_err_cb(SS_SPI_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_SPI_INFO *info = ctx->info;
ctx->flags = SS_SPI_MASTER_FLAG_ERROR;
if (info->spi_cbs.err_cb) {
info->spi_cbs.err_cb(info);
}
}

View File

@@ -1,33 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1) Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */

View File

@@ -1,440 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "arc/arc_exception.h"
#include "device/subsystem/uart.h"
#include "device/subsystem/ss_uart.h"
#include "io_config.h"
/* APEX UART device registers */
#define UART_RBR (0x00)
#define UART_THR (0x00)
#define UART_DLL (0x00)
#define UART_IER (0x04)
#define UART_DLH (0x04)
#define UART_IIR (0x08)
#define UART_FCR (0x08)
#define UART_LCR (0x0c)
#define UART_MCR (0x10)
#define UART_LSR (0x14) // unused
#define UART_MSR (0x18) // unused
#define UART_USR (0x7c) // unused
#define UART_CLKEN (0xc0)
#define REG_READ(x) arc_aux_read((ctx->reg_base + x))
#define REG_WRITE(x, y) arc_aux_write((ctx->reg_base + x), y)
/** convert uart baudrate to subsystem divisor */
#define SS_UART_BAUD2DIV(perifreq, baud) ((perifreq) / ((baud) * 16) + 1)
/**
* @fn int32_t set_hwfc(uint32_t dev_id, uint32_t control)
*/
Inline int32_t set_hwfc(uint32_t dev_id, uint32_t control)
{
uint32_t param = 0;
if (control == UART_FC_NONE) {
param = 0;
} else {
param = 1;
}
io_uart_ioctl(dev_id, IO_UART_SET_FLOW_CONTROL, &param);
return E_OK;
}
/**
* @fn int32_t set_baud(SS_UART_DEV_CONTEXT *ctx, uint32_t baud)
*/
Inline int32_t set_baud(SS_UART_DEV_CONTEXT *ctx, uint32_t baud)
{
uint32_t param;
DEV_UART_INFO *info = ctx->info;
param = SS_UART_BAUD2DIV(ctx->bus_freq, baud);
io_uart_ioctl(ctx->dev_id, IO_UART_SET_DLx, &param);
info->baudrate = baud;
return E_OK;
}
static int32_t set_dps(uint32_t dev_id, const UART_DPS_FORMAT *format)
{
uint32_t param = 0;
switch (format->databits) {
case 6:
param |= 0x1;
break;
case 7:
param |= 0x2;
break;
case 8:
param |= 0x3;
break;
default:
return E_NOSPT;
}
if (format->stopbits == UART_STPBITS_ONE) {
} else if (format->stopbits == UART_STPBITS_ONEHALF && format->databits == 5) {
param |= 0x4;
} else {
return E_NOSPT;
}
if (format->parity != UART_PARITY_NONE) {
param |= 0x8; // PEN
if (format->parity == UART_PARITY_EVEN) {
param |= 0x10; // EPS
} else if (format->parity == UART_PARITY_MARK) {
// PEN & Stick parity = logic 1
param |= (0x20);
} else if (format->parity == UART_PARITY_SPACE) {
// PEN & EPS & Stick parity = logic 0
param |= (0x10 | 0x20);
}
}
io_uart_ioctl(dev_id, IO_UART_SET_LCR, &param);
return E_OK;
}
static void io_uart_poll_write(SS_UART_DEV_CONTEXT *ctx, uint8_t *data, uint32_t *size)
{
uint32_t old_val;
uint32_t i = 0;
uint32_t len;
/* disbale uart interrupt */
old_val = REG_READ(UART_IER);
REG_WRITE(UART_IER, 0x80);
len = *size;
while (i < len) {
while ((REG_READ(UART_LSR) & 0x20)) {
; // wait THR empty
}
REG_WRITE(UART_THR, data[i++]);
}
REG_WRITE(UART_IER, old_val);
}
static void io_uart_poll_read(SS_UART_DEV_CONTEXT *ctx, uint8_t *data, uint32_t *size)
{
uint32_t i = 0;
uint32_t len;
uint32_t old_val;
old_val = REG_READ(UART_IER);
REG_WRITE(UART_IER, 0x80);
len = *size;
while (i < len) {
while (!(REG_READ(UART_LSR) & 0x1)) {
; // wait data ready
}
data[i++] = REG_READ(UART_RBR);
}
REG_WRITE(UART_IER, old_val);
}
static void io_uart_rx_int(SS_UART_DEV_CONTEXT *ctx, uint32_t enable)
{
uint32_t val;
if (enable) {
/* enable ERBFI interrupt */
val = REG_READ(UART_IER) | 0x1;
REG_WRITE(UART_IER, val);
} else {
val = REG_READ(UART_IER) & ~0x1;
REG_WRITE(UART_IER, val);
}
}
static void io_uart_tx_int(SS_UART_DEV_CONTEXT *ctx, uint32_t enable)
{
uint32_t val;
if (enable) {
/* enable ETBEI interrupt and enable use of interrupt for TX threshold */
val = REG_READ(UART_IER) | 0x82;
REG_WRITE(UART_IER, val);
} else {
val = REG_READ(UART_IER) & ~0x82;
REG_WRITE(UART_IER, val);
}
}
int32_t ss_uart_open(SS_UART_DEV_CONTEXT *ctx, uint32_t baud)
{
int32_t ret = E_OK;
DEV_UART_INFO *info = ctx->info;
io_cb_t callback;
int32_t dev_id = ctx->dev_id;
info->opn_cnt++;
if (info->opn_cnt > 1) {
if (baud == info->baudrate) {
return E_OK;
} else {
return E_OPNED;
}
}
if (io_uart_open(dev_id)) {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->tx_cb;
io_uart_ioctl(dev_id, IO_SET_CB_TX, &callback);
callback.cb = (IO_CB_FUNC)ctx->rx_cb;
io_uart_ioctl(dev_id, IO_SET_CB_RX, &callback);
callback.cb = (IO_CB_FUNC)ctx->err_cb;
io_uart_ioctl(dev_id, IO_SET_CB_ERR, &callback);
UART_DPS_FORMAT_DEFAULT(info->dps_format);
set_dps(dev_id, &info->dps_format);
info->hwfc = UART_FC_DEFAULT;
set_hwfc(dev_id, info->hwfc);
set_baud(ctx, baud);
ctx->flags = 0;
info->baudrate = baud;
int_enable(ctx->intno);
return ret;
}
int32_t ss_uart_close(SS_UART_DEV_CONTEXT *ctx)
{
DEV_UART_INFO *info = ctx->info;
info->opn_cnt--;
if (info->opn_cnt == 0) {
info->baudrate = 0;
io_uart_close(ctx->dev_id);
int_disable(ctx->intno);
}
return E_OK;
}
int32_t ss_uart_control(SS_UART_DEV_CONTEXT *ctx, uint32_t ctrl_cmd, void *param)
{
DEV_BUFFER *devbuf;
uint32_t int_val = (uint32_t)param;
int32_t dev_id = ctx->dev_id;
DEV_UART_INFO *info = ctx->info;
switch (ctrl_cmd) {
case UART_CMD_SET_BAUD:
return set_baud(ctx, int_val);
case UART_CMD_SET_HWFC:
io_uart_ioctl(dev_id, IO_UART_SET_FLOW_CONTROL, param);
return E_OK;
case UART_CMD_SET_DPS_FORMAT:
return set_dps(dev_id, (UART_DPS_FORMAT *)param);
case UART_CMD_GET_RXAVAIL:
if (REG_READ(UART_LSR) & 0x1) {
/* at least one byte */
*((uint32_t *)param) = 1;
} else {
*((uint32_t *)param) = 0;
}
return E_OK;
case UART_CMD_GET_TXAVAIL:
int_val = REG_READ(UART_LSR);
if (int_val & 0x40) {
*((uint32_t *)param) = IO_UART0_FS;
} else {
if (int_val & 0x20) {
/* FIFO full */
*((uint32_t *)param) = 0;
} else {
*((uint32_t *)param) = 1;
}
}
return E_OK;
case UART_CMD_SET_RXCB:
info->uart_cbs.rx_cb = param;
return E_OK;
case UART_CMD_SET_TXCB:
info->uart_cbs.tx_cb = param;
return E_OK;
case UART_CMD_SET_ERRCB:
info->uart_cbs.err_cb = param;
return E_OK;
case UART_CMD_SET_TXINT:
io_uart_tx_int(ctx, int_val);
return E_OK;
case UART_CMD_SET_RXINT:
io_uart_rx_int(ctx, int_val);
return E_OK;
case UART_CMD_SET_TXINT_BUF:
if (param != NULL) {
devbuf = (DEV_BUFFER *)param;
info->tx_buf = *devbuf;
info->tx_buf.ofs = 0;
io_uart_write(dev_id, (uint8_t *)(devbuf->buf),
&(devbuf->len));
} else {
info->tx_buf.buf = NULL;
info->tx_buf.len = 0;
info->tx_buf.ofs = 0;
io_uart_write(dev_id, NULL, &(info->tx_buf.len));
}
break;
case UART_CMD_SET_RXINT_BUF:
if (param != NULL) {
devbuf = (DEV_BUFFER *)param;
info->rx_buf = *devbuf;
info->rx_buf.ofs = 0;
io_uart_read(dev_id, (uint8_t *)(devbuf->buf),
&(devbuf->len));
} else {
info->rx_buf.buf = NULL;
info->rx_buf.len = 0;
info->rx_buf.ofs = 0;
io_uart_read(dev_id, NULL, &(info->rx_buf.len));
}
break;
case UART_CMD_BREAK_SET:
case UART_CMD_BREAK_CLR:
return E_NOSPT;
default:
return E_NOSPT;
}
return E_OK;
}
int32_t ss_uart_write(SS_UART_DEV_CONTEXT *ctx, const void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
if (arc_locked() || arc_int_active()) {
io_uart_poll_write(ctx, (uint8_t *) data, &len);
} else {
ctx->flags = SS_UART_FLAG_TX;
io_uart_write(dev_id, (uint8_t *) data, &len);
/* wait finished: uart int enable & no cpu lock */
while (ctx->flags & SS_UART_FLAG_TX) {
;
}
if (ctx->flags & SS_UART_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
}
return len;
}
int32_t ss_uart_read(SS_UART_DEV_CONTEXT *ctx, void *data, uint32_t len)
{
int32_t dev_id = ctx->dev_id;
if (arc_locked() || arc_int_active()) {
io_uart_poll_read(ctx, (uint8_t *) data, &len);
} else {
ctx->flags = SS_UART_FLAG_RX;
io_uart_read(dev_id, (uint8_t *) data, &len);
/* wait finished: uart int enable & no cpu lock */
while (ctx->flags & SS_UART_FLAG_RX) {
;
}
if (ctx->flags & SS_UART_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
}
return len;
}
void ss_uart_tx_cb(SS_UART_DEV_CONTEXT *ctx, void *param)
{
DEV_UART_INFO *info = ctx->info;
if (ctx->flags & SS_UART_FLAG_TX) {
ctx->flags &= ~SS_UART_FLAG_TX;
} else if (info->uart_cbs.tx_cb) {
info->uart_cbs.tx_cb(info);
}
}
void ss_uart_rx_cb(SS_UART_DEV_CONTEXT *ctx, void *param)
{
DEV_UART_INFO *info = ctx->info;
if (ctx->flags & SS_UART_FLAG_RX) {
ctx->flags &= ~SS_UART_FLAG_RX;
} else if (info->uart_cbs.rx_cb) {
info->uart_cbs.rx_cb(info);
}
}
void ss_uart_err_cb(SS_UART_DEV_CONTEXT *ctx, void *param)
{
DEV_UART_INFO *info = ctx->info;
ctx->flags = SS_UART_FLAG_ERROR;
if (info->uart_cbs.err_cb) {
info->uart_cbs.err_cb(info);
}
}

View File

@@ -1,950 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include "device/subsystem/uart.h"
#include "io_config.h"
#include "apexextensions.h"
/* APEX UART device registers */
#define UART_RBR (0x00)
#define UART_THR (0x00)
#define UART_DLL (0x00)
#define UART_IER (0x04)
#define UART_DLH (0x04)
#define UART_IIR (0x08)
#define UART_FCR (0x08)
#define UART_LCR (0x0c)
#define UART_MCR (0x10)
#define UART_LSR (0x14) // unused
#define UART_MSR (0x18) // unused
#define UART_USR (0x7c) // unused
#define UART_CLKEN (0xc0)
#define DMA_NONE (0xff)
#define FLOW_CONTROL_OFF 0 // Flow Control is OFF
#define FLOW_CONTROL_ON 1 // Using software implementation of CTS/RTS handling
#define nCTS_LOW 0
#define nCTS_HIGH 1
typedef _Interrupt void (*ISR) ();
/* Private data structure maintained by the driver. */
typedef struct uart_info_struct {
uint32_t reg_base; /* base address of device register set */
/* TX & RX Buffer and lengths */
uint8_t *tx_data;
uint32_t tx_size;
uint32_t tx_count;
uint8_t *rx_data;
uint32_t rx_size, *p_rxsize;
uint32_t rx_count;
uint8_t instID;
uint16_t dmarxchanid, dmatxchanid;
#ifdef __Xdmac
_Uncached uint32_t *dmarxdescriptor, *dmatxdescriptor;
uint8_t dmarxidx;
uint8_t dmatxidx;
#endif
/* Callbacks */
IO_CB_FUNC tx_cb;
IO_CB_FUNC rx_cb;
IO_CB_FUNC err_cb;
/* Interrupt numbers and handlers */
uint8_t isr_vector; /* ISR vector */
ISR uart_isr; /* UART device ISRs */
ISR uart_dmatx_isr; /* UART DMA TX ISRs */
ISR uart_dmarx_isr; /* UART DMA RX ISRs */
uint32_t fifo_depth, rx_threshold, tx_threshold;
uint8_t fcr_mirror;
uint8_t flow_control;
uint8_t nCTS_state;
} uart_info_t, *uart_info_pt;
#ifdef IO_UART0_PRESENT
#define UART_DEV_PRESENT
#endif
#ifdef IO_UART1_PRESENT
#define UART_DEV_PRESENT
#endif
#ifdef IO_UART2_PRESENT
#define UART_DEV_PRESENT
#endif
#ifdef IO_UART3_PRESENT
#define UART_DEV_PRESENT
#endif
#ifdef UART_DEV_PRESENT
#define UART_MAX_CNT (4)
static void uart_isr_proc(uint32_t dev_id);
static void uart_dmatx_isr_proc(uint32_t dev_id);
static void uart_dmarx_isr_proc(uint32_t dev_id);
#ifdef IO_UART0_PRESENT
static _Interrupt void uart0_ISR()
{
uart_isr_proc(0);
}
static _Interrupt void uart0_dmatx_ISR()
{
uart_dmatx_isr_proc(0);
}
static _Interrupt void uart0_dmarx_ISR()
{
uart_dmarx_isr_proc(0);
}
#endif
#ifdef IO_UART1_PRESENT
static _Interrupt void uart1_ISR()
{
uart_isr_proc(1);
}
static _Interrupt void uart1_dmatx_ISR()
{
uart_dmatx_isr_proc(1);
}
static _Interrupt void uart1_dmarx_ISR()
{
uart_dmarx_isr_proc(1);
}
#endif
#ifdef IO_UART2_PRESENT
static _Interrupt void uart2_ISR()
{
uart_isr_proc(2);
}
static _Interrupt void uart2_dmatx_ISR()
{
uart_dmatx_isr_proc(2);
}
static _Interrupt void uart2_dmarx_ISR()
{
uart_dmarx_isr_proc(2);
}
#endif
#ifdef IO_UART3_PRESENT
static _Interrupt void uart3_ISR()
{
uart_isr_proc(3);
}
static _Interrupt void uart3_dmatx_ISR()
{
uart_dmatx_isr_proc(3);
}
static _Interrupt void uart3_dmarx_ISR()
{
uart_dmarx_isr_proc(3);
}
#endif
#ifdef __Xdmac
static void create_dma_descriptor_rx(uart_info_pt dev, uint32_t burst,
uint8_t idx);
static void create_dma_descriptor_tx(uart_info_pt dev, uint32_t burst,
uint8_t idx);
#endif
/* UART devices private data structures */
static uart_info_pt uart_handles[UART_MAX_CNT] = { 0 };
#ifdef __Xdmac
static _Uncached uint32_t uart_dmarx_descriptors[8 * UART_MAX_CNT];
static _Uncached uint32_t uart_dmatx_descriptors[8 * UART_MAX_CNT];
#endif
static uart_info_t uart_devs[] = {
#ifdef IO_UART0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_UART0_RBR_THR_DLL,
.isr_vector = IO_UART0_INTR,
.uart_isr = uart0_ISR,
.uart_dmatx_isr = uart0_dmatx_ISR,
.uart_dmarx_isr = uart0_dmarx_ISR,
#ifdef IO_UART0_DMA_RX
.dmarxchanid = IO_UART0_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_UART0_DMA_TX
.dmatxchanid = IO_UART0_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_UART0_FS },
#endif
#ifdef IO_UART1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_UART1_RBR_THR_DLL,
.isr_vector = IO_UART1_INTR,
.uart_isr = uart1_ISR,
.uart_dmatx_isr = uart1_dmatx_ISR,
.uart_dmarx_isr = uart1_dmarx_ISR,
#ifdef IO_UART1_DMA_RX
.dmarxchanid = IO_UART1_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_UART1_DMA_TX
.dmatxchanid = IO_UART1_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_UART1_FS },
#endif
#ifdef IO_UART2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_UART2_RBR_THR_DLL,
.isr_vector = IO_UART2_INTR,
.uart_isr = uart2_ISR,
.uart_dmatx_isr = uart2_dmatx_ISR,
.uart_dmarx_isr = uart2_dmarx_ISR,
#ifdef IO_UART2_DMA_RX
.dmarxchanid = IO_UART2_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_UART2_DMA_TX
.dmatxchanid = IO_UART2_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_UART2_FS },
#endif
#ifdef IO_UART3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_UART3_RBR_THR_DLL,
.isr_vector = IO_UART3_INTR,
.uart_isr = uart3_ISR,
.uart_dmatx_isr = uart3_dmatx_ISR,
.uart_dmarx_isr = uart3_dmarx_ISR,
#ifdef IO_UART3_DMA_RX
.dmarxchanid = IO_UART3_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_UART3_DMA_TX
.dmatxchanid = IO_UART3_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_UART3_FS },
#endif
{ .instID = UART_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
uint32_t io_uart_open(uint32_t dev_id)
{
uint32_t h = 0;
uint32_t val = 0;
uart_info_pt dev;
h = 0;
while ((uart_devs[h].instID != dev_id)
&& (uart_devs[h].instID != UART_MAX_CNT)) {
h++;
}
if ((uart_devs[h].instID == UART_MAX_CNT) || (0 != uart_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
uart_handles[dev_id] = &uart_devs[h];
dev = uart_handles[dev_id];
REG_WRITE(UART_CLKEN, 0x1);
REG_WRITE(UART_IER, 0x0);
REG_READ(UART_RBR);
/* when there are fifos available, always enable and reset these */
if (dev->fifo_depth != 0) {
REG_WRITE(UART_FCR, 0x07);
dev->fcr_mirror = 0;
dev->rx_threshold = 1;
dev->tx_threshold = 0;
}
/* save nCTS state */
val = REG_READ(UART_MSR);
dev->nCTS_state = (val & 0x10) ? nCTS_LOW : nCTS_HIGH;
_setvecti(dev->isr_vector, dev->uart_isr);
#ifdef __Xdmac
dev->dmarxdescriptor = &uart_dmarx_descriptors[8 * h];
dev->dmatxdescriptor = &uart_dmatx_descriptors[8 * h];
if (dev->dmarxchanid != DMA_NONE) {
dev->dmarxdescriptor[1] = dev->dmarxdescriptor[4 + 1] =
dev->reg_base + UART_RBR;
dev->dmarxdescriptor[3] = (uint32_t) &(dev->dmarxdescriptor[4]);
dev->dmarxdescriptor[4 + 3] =
(uint32_t) &(dev->dmarxdescriptor[0]);
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, dev->uart_dmarx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, dev->uart_isr);
}
if (dev->dmatxchanid != DMA_NONE) {
dev->dmatxdescriptor[2] = dev->dmatxdescriptor[4 + 2] =
dev->reg_base + UART_THR;
dev->dmatxdescriptor[3] = (uint32_t) &(dev->dmatxdescriptor[4]);
dev->dmatxdescriptor[4 + 3] =
(uint32_t) &(dev->dmatxdescriptor[0]);
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, dev->uart_dmatx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, dev->uart_isr);
}
#endif
return 0;
}
void io_uart_close(uint32_t dev_id)
{
uart_info_pt dev = uart_handles[dev_id];
// bring uart instance to reset state
if (dev->fifo_depth != 0) {
REG_WRITE(UART_FCR, 0x07); // reset FIFOs
}
REG_WRITE(UART_IER, 0x0); // clear interrupt enable register
/* gate the UART clock */
REG_WRITE(UART_CLKEN, 0x0);
_setvecti(dev->isr_vector, NULL);
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmarxchanid);
}
if (dev->dmatxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmatxchanid);
}
#endif
dev->rx_cb = NULL;
dev->tx_cb = NULL;
dev->err_cb = NULL;
uart_handles[dev_id] = 0;
}
void io_uart_read(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
uart_info_pt dev = uart_handles[dev_id];
uint32_t val = 0;
dev->rx_data = data;
dev->rx_size = *size;
dev->p_rxsize = size;
dev->rx_count = 0;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
if (dev->rx_size > 0) {
if ((dev->fifo_depth != 0) && (dev->rx_size < dev->rx_threshold)) {
/* temporary reset the rx_threshold to 1 */
REG_WRITE(UART_FCR, (((dev->fcr_mirror & ~0xC) << 4) | 0x01));
}
/* enable ERBFI and ELSI interrupt */
val = REG_READ(UART_IER) | 0x5;
REG_WRITE(UART_IER, val);
}
#ifdef __Xdmac
} else { /* DMA: create descriptor */
if (dev->rx_size != 0) {
if (dev->fifo_depth == 0) { /* fifos are not available */
val = 1;
} else {
val = dev->rx_threshold;
}
create_dma_descriptor_rx(dev, val, 0);
if (dev->rx_size != dev->rx_count) {
create_dma_descriptor_rx(dev, val, 4);
}
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
dev->dmarxidx = 0;
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
/* enable ELSI interrupt */
val = REG_READ(UART_IER) | 0x4;
REG_WRITE(UART_IER, val);
}
}
/*
* De-assert nRTS line if flow control is enabled
* Note that UART controller inverts the MCR bit value
*/
if (dev->flow_control == FLOW_CONTROL_ON) {
val = REG_READ(UART_MCR) | 0x2;
REG_WRITE(UART_MCR, val);
}
#endif
}
void io_uart_write(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
uart_info_pt dev = uart_handles[dev_id];
uint32_t cnt = 0;
uint32_t h = 0;
uint32_t val = 0;
dev->tx_data = data;
dev->tx_size = *size;
dev->tx_count = 0;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* If...
* - flow control is disabled or
* - flow control is enabled && nCTS is already LOW
* ...start data transmit immediately, wait for nCTS change IRQ otherwise */
if ((dev->flow_control == FLOW_CONTROL_OFF) ||
((dev->flow_control == FLOW_CONTROL_ON)
&& (dev->nCTS_state == nCTS_LOW))) {
/* write first bytes to fifo (if any) */
cnt = dev->tx_size - dev->tx_count;
if (cnt > 0) {
if (dev->fifo_depth == 0) { /* fifos are not available */
cnt = 1;
} else if (cnt > dev->fifo_depth) { /* fifos enabled (and by definition != FIFO_NONE) */
cnt = dev->fifo_depth;
}
for (h = 0; h != cnt; h++) {
REG_WRITE(UART_THR, (dev->tx_data[dev->tx_count++]));
}
/* enable ETBEI interrupt and enable use of interrupt for TX threshold */
val = REG_READ(UART_IER) | 0x82;
REG_WRITE(UART_IER, val);
}
}
#ifdef __Xdmac
} else {
/* DMA: create descriptor */
if (dev->fifo_depth == 0) { /* fifos are not available */
cnt = 1;
} else {
cnt = dev->fifo_depth - dev->tx_threshold;
}
create_dma_descriptor_tx(dev, cnt, 0);
if (dev->tx_size != dev->tx_count) {
create_dma_descriptor_tx(dev, cnt, 4);
}
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid, &(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
dev->dmatxidx = 0;
/* If nCTS is already LOW and flow control is enabled - start data transmit immediately,
* wait for nCTS change IRQ otherwise */
if (!
((dev->flow_control == FLOW_CONTROL_ON)
&& (dev->nCTS_state == nCTS_HIGH))) {
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
}
void io_uart_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
uart_info_pt dev = uart_handles[dev_id];
uint32_t val = 0;
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
#if 0
case IO_UART_SET_MCR: // not part of public API (yet)
REG_WRITE(UART_MCR, *((uint32_t *) arg));
break;
case IO_UART_GET_MCR: // not part of public API (yet)
*((uint32_t *) arg) = REG_READ(UART_MCR);
break;
#endif
case IO_UART_SET_LCR:
/* leave the LDAB bit cleared */
REG_WRITE(UART_LCR, (*((uint32_t *) arg) & 0x7f));
break;
case IO_UART_GET_LCR:
*((uint32_t *) arg) = REG_READ(UART_LCR);
break;
case IO_UART_SET_DLx:
/* 16 bit divisor --> DLL (lower 8) and DLH (upper 8) registers */
/* set LDAB bit for DLx register access, first */
val = REG_READ(UART_LCR);
REG_WRITE(UART_LCR, (val | (0x1 << 7)));
REG_WRITE(UART_DLL, (*((uint32_t *) arg) & 0x00ff));
REG_WRITE(UART_DLH, ((*((uint32_t *) arg) & 0xff00) >> 8));
REG_WRITE(UART_LCR, val);
break;
case IO_UART_GET_DLx:
/* set LDAB bit for DLx register access, first */
val = REG_READ(UART_LCR);
REG_WRITE(UART_LCR, (val | (0x1 << 7)));
*((uint32_t *) arg) =
(REG_READ(UART_DLL) | (REG_READ(UART_DLH) << 8));
REG_WRITE(UART_LCR, val);
break;
case IO_UART_SET_RX_THRESHOLD:
/* precondition: can only be called for dev->fifo_depth != 0 */
val = *((uint32_t *) arg);
dev->fcr_mirror = (dev->fcr_mirror & ~0xC) | (val << 2);
REG_WRITE(UART_FCR, ((dev->fcr_mirror << 4) | 0x01));
if (val == 0) {
dev->rx_threshold = 1;
} else if (val == 1) {
dev->rx_threshold = dev->fifo_depth >> 2;
} else if (val == 2) {
dev->rx_threshold = dev->fifo_depth >> 1;
} else if (val == 3) {
dev->rx_threshold = dev->fifo_depth - 2;
}
break;
case IO_UART_SET_TX_THRESHOLD:
/* precondition: can only be called for dev->fifo_depth != 0 */
val = *((uint32_t *) arg);
dev->fcr_mirror = (dev->fcr_mirror & ~0x3) | val;
REG_WRITE(UART_FCR, ((dev->fcr_mirror << 4) | 0x01));
if (val == 0) {
dev->tx_threshold = 0;
} else if (val == 1) {
dev->tx_threshold = 2;
} else if (val == 2) {
dev->tx_threshold = dev->fifo_depth >> 2;
} else if (val == 3) {
dev->tx_threshold = dev->fifo_depth >> 1;
}
break;
case IO_UART_SET_FLOW_CONTROL:
if ((uint32_t) (*((uint32_t *) arg)) == 1) {
// Enable Flow Control
dev->flow_control = FLOW_CONTROL_ON; // Use software implementation of CTS/RTS control
val = REG_READ(UART_IER) | 0x08;
REG_WRITE(UART_IER, val); // Enable modem status interrupt
val = REG_READ(UART_MSR);
if (val & 0x10) {
dev->nCTS_state = nCTS_LOW;
} else {
dev->nCTS_state = nCTS_HIGH;
}
} else {
// Diable Flow Control
dev->flow_control = FLOW_CONTROL_OFF;
val = REG_READ(UART_IER) & ~0x08;
REG_WRITE(UART_IER, val); // Disable modem status interrupt
}
break;
default:
break;
}
}
static void uart_isr_proc(uint32_t dev_id)
{
uart_info_pt dev = uart_handles[dev_id];
uint32_t intid = 0;
uint32_t cnt = 0;
uint32_t h = 0;
volatile uint32_t val = 0;
intid = REG_READ(UART_IIR) & 0x0f;
/* workaround for break detect: break interrupt may have been cleared by DMAC reading from rxfifo... */
if (intid == 0x1) { /* break detect + dma: copy source from while loop */
/* line break detected; complete read immediately */
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
*(dev->p_rxsize) = dev->rx_count;
REG_READ(UART_RBR);
#ifdef __Xdmac
} else {
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc_get_ctrl(dev->dmarxchanid, &val);
} else {
_dma_chan_desc_aux_get_ctrl(dev->dmarxchanid, &val);
}
*(dev->p_rxsize) = dev->rx_count - 1 - ((val >> 8) & 0x1fff);
*(dev->p_rxsize) -= 1;
}
#endif
/* disable (ERBFI and) ELSI interrupt */
val = REG_READ(UART_IER) & ~0x5;
REG_WRITE(UART_IER, val);
if (dev->fifo_depth != 0) { /* restore threshold to user defined value */
REG_WRITE(UART_FCR, ((dev->fcr_mirror << 4) | 0x01));
}
/* call user callback function, if any */
if (dev->rx_cb != 0) {
dev->rx_cb(dev_id);
}
}
while (intid != 0x1) {
switch (intid) {
case 0x2:
{ /* tx empty */
if (dev->tx_data == NULL) {
if (dev->tx_cb != 0) {
dev->tx_cb(dev_id);
} else {
val = REG_READ(UART_IER) & ~0x82;
REG_WRITE(UART_IER, val);
}
} else {
if (dev->tx_count == dev->tx_size) { /* disable ETBEI interrupt (and disable threshold interrupt IER[7]) */
val = REG_READ(UART_IER) & ~0x82;
REG_WRITE(UART_IER, val);
/* call user callback function, if any */
if (dev->tx_cb != 0) {
dev->tx_cb(dev_id);
}
dev->tx_size = 0; // indicates no TX pending
} else {
/* write next bytes to fifo (if any) */
cnt = dev->tx_size - dev->tx_count;
if (dev->fifo_depth == 0) { /* fifos are not available */
cnt = 1;
} else if (cnt > dev->fifo_depth) { /* fifos enabled (and by definition != FIFO_NONE) */
cnt = dev->fifo_depth;
}
if (REG_READ(UART_IER) & 0x80) { /* if IER[7] is set, threshold shall be taken into account */
if (cnt > (dev->fifo_depth - dev->tx_threshold)) {
cnt = dev->fifo_depth - dev->tx_threshold;
}
}
for (h = 0; h != cnt; h++) {
REG_WRITE(UART_THR,
(dev->tx_data[dev->tx_count++]));
}
}
}
break;
}
case 0x4:
{ /* rx data available; at least one, more is uncertain */
if (dev->rx_data == NULL) {
if (dev->rx_cb != 0) {
dev->rx_cb(dev_id);
} else {
REG_READ(UART_RBR);
}
} else {
if (dev->fifo_depth == 0) {
dev->rx_data[dev->rx_count++] = REG_READ(UART_RBR);
} else {
cnt = dev->rx_size - dev->rx_count;
if (cnt < dev->rx_threshold) {
dev->rx_data[dev->rx_count++] = REG_READ(UART_RBR);
} else {
for (h = 0; h != dev->rx_threshold; h++) {
dev->rx_data[dev->rx_count++] =
REG_READ(UART_RBR);
}
cnt -= dev->rx_threshold;
if (cnt < dev->rx_threshold) {
/* temporary reset the rx_threshold to 1 */
REG_WRITE(UART_FCR,
(((dev->
fcr_mirror & ~0xC) << 4) | 0x01));
}
}
}
if (dev->rx_count == dev->rx_size) { /* disable ERBFI and ELSI interrupt */
val = REG_READ(UART_IER) & ~0x5;
REG_WRITE(UART_IER, val);
if (dev->fifo_depth != 0) { /* restore threshold to user defined value */
REG_WRITE(UART_FCR,
((dev->fcr_mirror << 4) | 0x01));
}
/* call user callback function, if any */
if (dev->rx_cb != 0) {
dev->rx_cb(dev_id);
}
}
}
break;
}
case 0x0: // Modem control status
{
val = REG_READ(UART_MSR);
if ((val & 0x10) != 0) {
dev->nCTS_state = nCTS_LOW;
// If there is a data buffer, it is time to start sending - nCTS turns low
if (dev->tx_size > 0) {
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* enable ETBEI interrupt - starting TX */
val = REG_READ(UART_IER) | 0x2;
REG_WRITE(UART_IER, val);
#ifdef __Xdmac
} else {
_dma_chan_enable((0x1 << dev->dmatxchanid), 1); // !!!!!
}
#endif
}
} else {
// nCTS was switched high back
dev->nCTS_state = nCTS_HIGH;
}
break;
}
case 0x6:
{
val = REG_READ(UART_LSR);
if (val & (0x1 << 4)) {
/* line break detected; complete read immediately */
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
*(dev->p_rxsize) = dev->rx_count;
REG_READ(UART_RBR);
#ifdef __Xdmac
} else {
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc_get_ctrl(dev->dmarxchanid,
&val);
} else {
_dma_chan_desc_aux_get_ctrl(dev->dmarxchanid,
&val);
}
*(dev->p_rxsize) =
dev->rx_count - 1 - ((val >> 8) & 0x1fff);
*(dev->p_rxsize) -= 1;
}
#endif
/* disable (ERBFI and) ELSI interrupt */
val = REG_READ(UART_IER) & ~0x5;
REG_WRITE(UART_IER, val);
if (dev->fifo_depth != 0) { /* restore threshold to user defined value */
REG_WRITE(UART_FCR,
((dev->fcr_mirror << 4) | 0x01));
}
/* call user callback function, if any */
if (dev->rx_cb != 0) {
dev->rx_cb(dev_id);
}
}
break;
}
case 0x7:
{
val = REG_READ(UART_USR);// update IIR busy status by read Uart Status Register
break;
}
default:
{ /* something wrong; at least, disable interrupts */
REG_WRITE(UART_IER, 0x0);
if (dev->err_cb != 0) {
dev->err_cb(dev_id);
}
break;
}
}
intid = REG_READ(UART_IIR) & 0x0f;
}
}
static void uart_dmatx_isr_proc(uint32_t dev_id)
{
#ifdef __Xdmac
uart_info_pt dev = uart_handles[dev_id];
uint32_t cnt = 0;
volatile uint32_t val = 0;
if (dev->tx_count == dev->tx_size) {
/* DMA TX xfer done */
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
/* enable ETBEI interrupt, to detect FIFO empty for end of tx */
val = REG_READ(UART_IER) | 0x2;
REG_WRITE(UART_IER, val);
} else {
/* clear DMA interrupt */
_dma_int_clear((0x1 << dev->dmatxchanid));
if (dev->fifo_depth == 0) { /* fifos are not available */
cnt = 1;
} else {
cnt = dev->fifo_depth - dev->tx_threshold;
}
create_dma_descriptor_tx(dev, cnt, dev->dmatxidx);
dev->dmatxidx = 4 - dev->dmatxidx;
}
#endif
}
static void uart_dmarx_isr_proc(uint32_t dev_id)
{
#ifdef __Xdmac
uart_info_pt dev = uart_handles[dev_id];
uint32_t val = 0;
if (dev->rx_count == dev->rx_size) {
/* Buffer transfer completed. Assert RTS line back if flow control is enabled */
if (dev->flow_control == FLOW_CONTROL_ON) {
val = REG_READ(UART_MCR) & ~0x2;
REG_WRITE(UART_MCR, val);
}
/* DMA RX xfer done */
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_int_clear((0x1 << dev->dmarxchanid));
/* call user callback function, if any */
if (dev->rx_cb != NULL) {
dev->rx_cb(dev_id);
}
} else {
/* clear DMA interrupt */
_dma_int_clear((0x1 << dev->dmarxchanid));
if (dev->fifo_depth == 0) { /* fifos are not available */
val = 1;
} else {
val = dev->rx_threshold;
}
create_dma_descriptor_rx(dev, val, dev->dmarxidx);
dev->dmarxidx = 4 - dev->dmarxidx;
}
#endif
}
#ifdef __Xdmac
#define UART_DMA_RX_END_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b000, dtt=b10, r=b1, op=b01 */
#define UART_DMA_RX_CTRL (0x801fff17) /* am=b10, i=b0, size=h1fff, dw/inc=b000, dtt=b10, r=b1, op=b11 */
#define UART_DMA_RX_INT_CTRL (0xa01fff17) /* am=b10, i=b1, size=h1fff, dw/inc=b000, dtt=b10, r=b1, op=b11 */
#define UART_DMA_TX_END_CTRL (0x6000000d) /* am=b01, i=b1, dw/inc=b000, dtt=b01, r=b1, op=b01 */
#define UART_DMA_TX_CTRL (0x401fff0f) /* am=b01, i=b0, size=h1fff, dw/inc=b000, dtt=b01, r=b1, op=b11 */
#define UART_DMA_TX_INT_CTRL (0x601fff0f) /* am=b01, i=b1, size=h1fff, dw/inc=b000, dtt=b01, r=b1, op=b11 */
#define UART_DMA_CTRL_SIZE_POS (8)
#define UART_DMA_CTRL_XFER_POS (21)
/* use maximum block size of 4kB per DMA transfer */
static void create_dma_descriptor_rx(uart_info_pt dev, uint32_t burst,
uint8_t idx)
{
dev->dmarxdescriptor[idx + 0] = (burst << UART_DMA_CTRL_XFER_POS);
if ((dev->rx_size - dev->rx_count) <= 8 * 1024) {
dev->dmarxdescriptor[idx + 0] |=
UART_DMA_RX_END_CTRL | (((dev->rx_size - dev->rx_count) - 1) <<
UART_DMA_CTRL_SIZE_POS);
dev->rx_count = dev->rx_size;
} else {
dev->dmarxdescriptor[idx + 0] |=
((dev->rx_size - dev->rx_count) <=
2 * 8 * 1024 ? UART_DMA_RX_CTRL : UART_DMA_RX_INT_CTRL);
dev->rx_count += 8 * 1024;
}
dev->dmarxdescriptor[idx + 2] =
(uint32_t) dev->rx_data + (dev->rx_count - 1);
}
static void create_dma_descriptor_tx(uart_info_pt dev, uint32_t burst,
uint8_t idx)
{
dev->dmatxdescriptor[idx + 0] = (burst << UART_DMA_CTRL_XFER_POS);
if ((dev->tx_size - dev->tx_count) <= 8 * 1024) {
dev->dmatxdescriptor[idx + 0] |=
UART_DMA_TX_END_CTRL | (((dev->tx_size - dev->tx_count) - 1) <<
UART_DMA_CTRL_SIZE_POS);
dev->tx_count = dev->tx_size;
} else {
dev->dmatxdescriptor[idx + 0] |=
((dev->tx_size - dev->tx_count) <=
2 * 8 * 1024 ? UART_DMA_TX_CTRL : UART_DMA_TX_INT_CTRL);
dev->tx_count += 8 * 1024;
}
dev->dmatxdescriptor[idx + 1] =
(uint32_t) dev->tx_data + (dev->tx_count - 1);
}
#endif
#endif

View File

@@ -1,119 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
// ADC088S022 is ADC on EMSDP board
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "board.h"
// #define DBG_MORE
#include "embARC_debug.h"
#include "adc088s022.h"
#define ADC_CHECK_EXP_NORTN(EXPR) CHECK_EXP_NOERCD(EXPR, error_exit)
/**
* @brief Initialize adc088s022
* @param[in] obj adc088s022 object
* @retval E_OK Initialize adc088s022 successfully
* @retval !E_OK Initialize adc088s022 failed
*/
int32_t adc088s022_adc_init(ADC088S022_DEF_PTR obj)
{
int32_t ercd = E_OK;
DEV_SPI_PTR spi_obj = spi_get_dev(obj->dev_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: spi_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, spi_obj, *spi_obj);
ADC_CHECK_EXP_NORTN(spi_obj != NULL);
ercd = spi_obj->spi_open(DEV_MASTER_MODE, BOARD_ADC_SPI_HZ);
if ((ercd == E_OPNED) || (ercd == E_OK)) {
ercd = spi_obj->spi_control(SPI_CMD_SET_CLK_MODE, CONV2VOID(SPI_CLK_MODE_0));
}
error_exit:
return ercd;
}
/**
* @brief Deinitialize adc088s022
* @param[in] obj adc088s022 object
* @retval E_OK Deinitialize adc088s022 successfully
* @retval !E_OK Deinitialize adc088s022 failed
*/
int32_t adc088s022_adc_deinit(ADC088S022_DEF_PTR obj)
{
int32_t ercd = E_OK;
DEV_SPI_PTR spi_obj = spi_get_dev(obj->dev_id);
ercd = spi_obj->spi_close();
return ercd;
}
/**
* @brief Read adc088s022 channel
* @param[in] obj adc088s022 object
* @param[out] val Pointer to the return value (Unit is mV)
* @param[in] channel ADC channel
* @retval E_OK Read adc088s022 channel successfully
* @retval !E_OK Read adc088s022 channel failed
*/
int32_t adc088s022_adc_read(ADC088S022_DEF_PTR obj, float *val, int8_t channel)
{
int32_t ercd = E_OK;
DEV_SPI_PTR spi_obj = spi_get_dev(obj->dev_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: spi_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, spi_obj, *spi_obj);
ADC_CHECK_EXP_NORTN(spi_obj != NULL);
uint8_t adc_value = 0;
uint8_t spi_buffer_rx[2];
uint8_t spi_buffer_tx[2];
DEV_SPI_TRANSFER spi_xfer;
/* Master and Slave transmit */
DEV_SPI_XFER_SET_TXBUF(&spi_xfer, spi_buffer_tx, 0, 2);
DEV_SPI_XFER_SET_RXBUF(&spi_xfer, spi_buffer_rx, 0, 2);
DEV_SPI_XFER_SET_NEXT(&spi_xfer, NULL);
spi_buffer_tx[1] = ((channel & 0x07) << 3); // Select channel
ercd = spi_obj->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(0));
ercd = spi_obj->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&spi_xfer));
// Read it again to have valid number (otherwise you might get value from previous channel)
ercd = spi_obj->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&spi_xfer));
ercd = spi_obj->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(0));
adc_value = (spi_buffer_rx[1] << 4) | (spi_buffer_rx[0] >> 4);
dbg_printf(DBG_MORE_INFO, "ADC-Channel(%d) = %d (0x%x)\r\n", channel, adc_value, adc_value);
*val = adc_value * ADC_REF_VDD / 256.0; // adc088s022 is an 8-bit ADC
error_exit:
return ercd;
}

View File

@@ -1,68 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_ADC088S022
#define H_ADC088S022
// ADC088S022 (a low-power, eight-channel. 23• Eight Input Channels. CMOS 8-bit analog-to-digital converter) is on EMSDP board
#define ADC_REF_VDD 3300 /*< power supply voltage is 3300mV, used as V_ref*/
#define ADC_FCLK_MIN 800000 // 0.8MHz
#define ADC_FLCK_MAX 3200000 // 3.2MHz
#define EMSDP_ADC_SPI_ID DFSS_SPI_2_ID
#define BOARD_ADC_SPI_HZ 1000000 // 1.0MHz
#if BOARD_ADC_SPI_HZ < ADC_FCLK_MIN || BOARD_ADC_SPI_HZ > ADC_FLCK_MAX
#error "BOARD_ADC_SPI_HZ should be within range of [ADC_FCLK_MIN, ADC_FLCK_MAX]"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** ADC088S022 object type */
typedef struct {
uint32_t dev_id;
} ADC088S022_DEF, *ADC088S022_DEF_PTR;
#define ADC088S022_DEFINE(NAME, DEVICE_ID) \
ADC088S022_DEF __ ## NAME = { \
.dev_id = DEVICE_ID, \
}; \
ADC088S022_DEF_PTR NAME = &__ ## NAME
extern int32_t adc088s022_adc_init(ADC088S022_DEF_PTR obj);
extern int32_t adc088s022_adc_deinit(ADC088S022_DEF_PTR obj);
extern int32_t adc088s022_adc_read(ADC088S022_DEF_PTR obj, float *val, int8_t channel);
#ifdef __cplusplus
}
#endif
#endif /* H_ADC088S022 */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/adc/adc088s022
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/adc/adc088s022

View File

@@ -1,728 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC.h"
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "board.h"
#include "max9880a.h"
#define DBG_LESS
#include "embARC_debug.h"
#define MAX9880A_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
// Register names
typedef enum {
MAX9880A_STATUS = 0x00, // RO 0x00
MAX9880A_JACKSTATUS, // RO 0x01
MAX9880A_AUXHIGH, // RO 0x02
MAX9880A_AUXLOW, // RO 0x03
MAX9880A_INTERRUPT_ENABLE, // RW 0x04
MAX9880A_SYSTEM_CLOCK, // RW 0x05
// DAI1-Clock Control
MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, // RW 0x06
MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, // RW 0x07
// DAI1-Configuration
MAX9880A_DAI1_INTERFACE_MODE_A, // RW 0x08
MAX9880A_DAI1_INTERFACE_MODE_B, // RW 0x09
MAX9880A_DAI1_TIME_DIVISION_MUL, // RW 0x0A
// DAI2-Clock Control
MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, // RW 0x0B
MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, // RW 0x0C
// DAI2-Configuration
MAX9880A_DAI2_INTERFACE_MODE_A, // RW 0x0D
MAX9880A_DAI2_INTERFACE_MODE_B, // RW 0x0E
MAX9880A_DAI2_TIME_DIVISION_MUL, // RW 0x0F
// Digital Mixers
MAX9880A_DAC_LR_MIXER, // RW 0x10
// Digital Filtering
MAX9880A_CODEC_FILTERS, // RW 0x11
// SPDM Outputs
MAX9880A_SPDM_CONFIGURATIONS, // RW 0x12
MAX9880A_SPDM_INPUT, // RW 0x13
MAX9880A_REV_ID, // RO 0x14
// LEVEL control
MAX9880A_SIDETONE, // RW 0x15
MAX9880A_STEREO_DAC_LEVEL, // RW 0x16
MAX9880A_VOICE_DAC_LEVEL, // RW 0x17
MAX9880A_LEFT_ADC_LEVEL, // RW 0x18
MAX9880A_RIGHT_ADC_LEVEL, // RW 0x19
MAX9880A_LEFT_LINE_INPUT_LEVEL, // RW 0x1A
MAX9880A_RIGHT_LINE_INPUT_LEVEL, // RW 0x1B
MAX9880A_LEFT_VOLUME_CTRL, // RW 0x1C
MAX9880A_RIGHT_VOLUME_CTRL, // RW 0x1D
MAX9880A_LEFT_LINE_OUTPUT_LEVEL, // RW 0x1E
MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, // RW 0x1F
MAX9880A_LEFT_MIC_GAIN, // RW 0x20
MAX9880A_RIGHT_MIC_GAIN, // RW 0x21
// Configuration
MAX9880A_INPUT, // RW 0x22
MAX9880A_MICROPHONE, // RW 0x23
MAX9880A_MODE, // RW 0x24
MAX9880A_JACK_DETECT, // RW 0x25
// Power Management
MAX9880A_ENABLE, // RW 0x26
MAX9880A_SYSTEM_SHUTDOWN, // RW 0x27
MAX9880A_REVISION_ID = 0xFF, // RO 0xFF
} max9880a_reg_t;
typedef struct max9880a_settings {
max9880a_reg_t reg;
uint8_t val;
} max9880a_settings_t;
/******************************************************************************/
/*********** MAX9880A Configs **************************************/
/******************************************************************************/
/**
* MAX9880A_I2SIN_LINEOUT_13MHZ
*
* Playback: I2S In -> LineOut, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
* => I2S data from FPGA-HSDK to MAX: 16 bit
*
* => MCLK on MAX9880 board is not from FPGA-HSDK but a on board Chrystal of 13.00 MHz.
*/
const max9880a_settings_t settings_i2sin_lineout_13mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x10 }, // 0x05, MCLK between 10-20 Mhz (PCLK=MCLK)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0x9E }, // 0x06, PLL=enabled, Ni=0x1E3F, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=13 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x3F }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0x9E }, // 0x0B, PLL=enabled, Ni=0x1E3F, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=13 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x3F }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0x00 }, // 0x22, No input selected
{ MAX9880A_ENABLE, 0x3C }, // 0x26, LineOut-Enable, LineIn-Disable, Left/Right DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk prescaler, disable internal clk osc
};
#define SETTINGS_I2SIN_LINEOUT_13MHZ_LENGTH (sizeof(settings_i2sin_lineout_13mhz) / sizeof(settings_i2sin_lineout_13mhz[0]))
/**
* MAX9880A_LINEIN_I2SOUT_13MHZ
*
* Recording: LineIn -> I2S out, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from HSDK to MAX: 16 KHz.
*
* => MCLK on MAX9880 board is not from FPGA-HSDK but a on board Chrystal of 13.00 MHz.
*/
const max9880a_settings_t settings_linein_i2sout_13mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27
{ MAX9880A_SYSTEM_CLOCK, 0x10 }, // 0x05, MCLK between 10-20 Mhz (PCLK=MCLK)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0x9E }, // 0x06, PLL=enabled, Ni=0x1E3F, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=13 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x3F }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0x9E }, // 0x0B, PLL=enabled, Ni=0x1E3F, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=13 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x3F }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, Select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1E, muted
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1F, muted
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xC3 }, // 0x26, LineIn-Enable, LineOut-Disable, Left/Right ADC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk prescaler, disable internal clk osc
};
#define SETTINGS_LINEIN_I2SOUT_13MHZ_LENGTH (sizeof(settings_linein_i2sout_13mhz) / sizeof(settings_linein_i2sout_13mhz[0]))
/**
* MAX9880A_I2SIN_LINEOUT_12DOT288MHZ
*
* Playback: I2S In -> LineOut, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
* => I2S data from FPGA-HSDK to MAX: 16 bit
*
* => MCLK disconnected, route 12.288 XTAL to clk-prescaler (JU12 on max9880a board)
*
* Difference with 13 Mhz settings above is "*" regs
*/
const max9880a_settings_t settings_i2sin_lineout_12_288mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x10 }, // 0x05, MCLK between 10-20 Mhz (PCLK=MCLK)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06*, PLL=enabled, Ni=0x2000, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07*
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B*, PLL=enabled, Ni=0x2000, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C*
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0x00 }, // 0x22, No input selected
{ MAX9880A_ENABLE, 0x3C }, // 0x26, LineOut-Enable, LineIn-Disable, Left/Right DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x88 }, // 0x27*, Power On, Xtal to clk-prescaler
};
#define SETTINGS_I2SIN_LINEOUT_12_288MHZ_LENGTH (sizeof(settings_i2sin_lineout_12_288mhz) / sizeof(settings_i2sin_lineout_12_288mhz[0]))
/**
* MAX9880A_LINEIN_I2SOUT_12DOT288MHZ
*
* Recording: LineIn -> I2S out, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
*
* => MCLK disconnected, route 12.288 XTAL to clk-prescaler
*
* Difference with 13 Mhz settings above is "*" regs
*/
const max9880a_settings_t settings_linein_i2sout_12_288mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27
{ MAX9880A_SYSTEM_CLOCK, 0x10 }, // 0x05, MCLK between 10-20 Mhz (PCLK=MCLK)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06*, PLL=enabled, Ni=0x2000, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07*
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B*, PLL=enabled, Ni=0x2000, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C*
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, Select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1E, muted
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1F, muted
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xC3 }, // 0x26, LineIn-Enable, LineOut-Disable, Left/Right ADC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x88 }, // 0x27*, Power On, Xtal to clk-prescaler
};
#define SETTINGS_LINEIN_I2SOUT_12_288MHZ_LENGTH (sizeof(settings_linein_i2sout_12_288mhz) / sizeof(settings_linein_i2sout_12_288mhz[0]))
/**
* MAX9880A_I2SIN_LINEOUT_24DOT567MHZ
*
* Playback: I2S In -> LineOut, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
* => I2S data from FPGA-HSDK to MAX: 16 bit
*
* => MCLK from FPGA-HSDK of 24.567 MHz
*
* Difference with 13 Mhz settings above is "*" regs
*/
const max9880a_settings_t settings_i2sin_lineout_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05*, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06*, PLL=enabled, Ni=0x2000, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07*
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B*, PLL=enabled, Ni=0x2000, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C*
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0x00 }, // 0x22, No input selected
{ MAX9880A_ENABLE, 0x3C }, // 0x26, LineOut-Enable, LineIn-Disable, Left/Right DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_I2SIN_LINEOUT_24_567MHZ_LENGTH (sizeof(settings_i2sin_lineout_24_567mhz) / sizeof(settings_i2sin_lineout_24_567mhz[0]))
/**
* MAX9880A_LINEIN_I2SOUT_24DOT567MHZ
*
* Recording: LineIn -> I2S out, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
*
* => MCLK from HSDK of 24.567 MHz
*
* Difference with 13 Mhz settings above is "*" regs
*/
const max9880a_settings_t settings_linein_i2sout_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05*, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06*, PLL=enabled, Ni=0x2000, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07*
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B*, PLL=enabled, Ni=0x2000, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C*
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, Select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1E, muted
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1F, muted
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xC3 }, // 0x26, LineIn-Enable, LineOut-Disable, Left/Right ADC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_LINEIN_I2SOUT_24_567MHZ_LENGTH (sizeof(settings_linein_i2sout_24_567mhz) / sizeof(settings_linein_i2sout_24_567mhz[0]))
/**
* MAX9880A_DAI2_I2SIN_LINEOUT_24DOT567MHZ
*
* Playback: I2S In -> LineOut, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
* But now we have PLAYBACK on DAI2 (input I2S on S1 BCLKS1, LRCLKS1, SDINS1 from I2S-TX)
*
* Measured with scope:
* => I2S clk from IC-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from IC-HSDK to MAX: 16 KHz.
* => I2S data from IC-HSDK to MAX: 16 bit
*
* => MCLK from HSDK of 24.567 MHz
*
*/
const max9880a_settings_t settings_dai2_i2sin_lineout_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S2 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x50 }, // 0x09, SEL1 = 1, Map S1 to DAI2, SDIEN1=1, SDOEN1=0
// For playback (S1 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x30 }, // 0x0E, SEL2 = 0, Map S2 to DAI1, SDIEN2=1, SDOEN2=1
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (i2s in)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0x00 }, // 0x22, No input selected
{ MAX9880A_ENABLE, 0x3C }, // 0x26, LineOut-Enable, LineIn-Disable, Left/Right DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_DAI2_I2SIN_LINEOUT_24_567MHZ_LENGTH (sizeof(settings_dai2_i2sin_lineout_24_567mhz) / sizeof(settings_dai2_i2sin_lineout_24_567mhz[0]))
/**
* MAX9880A_LINEIN_DAI1_I2SOUT_24DOT567MHZ
*
* Recording: LineIn -> I2S out, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
* But now we have RECORDING on DAI1 (output I2S on S2 BCLKS2, LRCLKS2, SDOUTS2 to I2S-RX)
*
* Measured with scope:
* => I2S clk from IC-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from IC-HSDK to MAX: 16 KHz.
*
* => MCLK from IC-HSDK of 24.567 MHz
*/
const max9880a_settings_t settings_linein_dai1_i2sout_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S2 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x50 }, // 0x09, SEL1 = 1, Map S1 to DAI2, SDIEN1=1, SDOEN1=0
// For playback (S1 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x30 }, // 0x0E, SEL2 = 0, Map S2 to DAI1, SDIEN2=1, SDOEN2=1
{ MAX9880A_DAC_LR_MIXER, 0x84 }, // 0x10, DAi1 left channel, DAi1 right channel (i2s out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, Select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1E, muted
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1F, muted
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xC3 }, // 0x26, LineIn-Enable, LineOut-Disable, Left/Right ADC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_LINEIN_DAI1_I2SOUT_24_567MHZ_LENGTH (sizeof(settings_linein_dai1_i2sout_24_567mhz) / sizeof(settings_linein_dai1_i2sout_24_567mhz[0]))
/**
* MAX9880A_24DOT567MHZ
*
* Playback & Recording (both tables mixed)
*/
const max9880a_settings_t settings_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S2 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x50 }, // 0x09, SEL1 = 1, Map S1 to DAI2, SDIEN1=1, SDOEN1=0
// For playback (S1 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x30 }, // 0x0E, SEL2 = 0, Map S2 to DAI1, SDIEN2=1, SDOEN2=1
{ MAX9880A_DAC_LR_MIXER, 0xA5 }, // 0x10, DAi2 left channel, DAi2 right channel (i2s in/out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xFF }, // 0x26, LineOut-Enable, LineIn-Enable, Left/Right ADC/DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_24_567MHZ_LENGTH (sizeof(settings_24_567mhz) / sizeof(settings_24_567mhz[0]))
/******************************************************************************/
/*********** END of MAX9880A Configs ********************************/
/******************************************************************************/
// Max9880a register name list
typedef struct max9880a_reg_table {
char str[10];
max9880a_reg_t reg;
} max9880a_reg_table_t;
const max9880a_reg_table_t max9880a_reg_table[] =
{
{ "STS ", MAX9880A_STATUS },
{ "JACK STS ", MAX9880A_JACKSTATUS },
{ "AUX HIGH ", MAX9880A_AUXHIGH },
{ "AUX LOW ", MAX9880A_AUXLOW },
{ "INT ENA ", MAX9880A_INTERRUPT_ENABLE },
{ "SYS CLK ", MAX9880A_SYSTEM_CLOCK },
// DAI1-Clock Control
{ "DAI1 CLKH", MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH },
{ "DAI1 CLKL", MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW },
// DAI1-Configuration
{ "INTMODE A", MAX9880A_DAI1_INTERFACE_MODE_A },
{ "INTMODE B", MAX9880A_DAI1_INTERFACE_MODE_B },
{ "TIME DIV ", MAX9880A_DAI1_TIME_DIVISION_MUL },
// DAI2-Clock Control
{ "DAI2 CLKH", MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH },
{ "DAI2 CLKL", MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW },
// DAI2-Configuration
{ "INTMODE A", MAX9880A_DAI2_INTERFACE_MODE_A },
{ "INTMODE B", MAX9880A_DAI2_INTERFACE_MODE_B },
{ "TIME DIV ", MAX9880A_DAI2_TIME_DIVISION_MUL },
// Digital Mixers
{ "DAC-LRMIX", MAX9880A_DAC_LR_MIXER },
// Digital Filtering
{ "CODEC ", MAX9880A_CODEC_FILTERS },
// SPDM Outputs
{ "SPDM CONF", MAX9880A_SPDM_CONFIGURATIONS },
{ "SPDM INP ", MAX9880A_SPDM_INPUT },
{ "REV ID ", MAX9880A_REV_ID },
// LEVEL control
{ "SIDE TONE", MAX9880A_SIDETONE },
{ "STDAC LVL", MAX9880A_STEREO_DAC_LEVEL },
{ "V-DAC LVL", MAX9880A_VOICE_DAC_LEVEL },
{ "ADC LVL L", MAX9880A_LEFT_ADC_LEVEL },
{ "ADC LVL R", MAX9880A_RIGHT_ADC_LEVEL },
{ "LIINLVL L", MAX9880A_LEFT_LINE_INPUT_LEVEL },
{ "LIINLVL R", MAX9880A_RIGHT_LINE_INPUT_LEVEL },
{ "VOLCTRL L", MAX9880A_LEFT_VOLUME_CTRL },
{ "VOLCTRL R", MAX9880A_RIGHT_VOLUME_CTRL },
{ "LIOULVL L", MAX9880A_LEFT_LINE_OUTPUT_LEVEL },
{ "LIOULVL R", MAX9880A_RIGHT_LINE_OUTPUT_LEVEL },
{ "MICGAIN L", MAX9880A_LEFT_MIC_GAIN },
{ "MICGAIN R", MAX9880A_RIGHT_MIC_GAIN },
// Configuration
{ "INPUT ", MAX9880A_INPUT },
{ "MIC ", MAX9880A_MICROPHONE },
{ "MODE ", MAX9880A_MODE },
{ "JACK DET ", MAX9880A_JACK_DETECT },
// Power Management
{ "ENABLE ", MAX9880A_ENABLE },
{ "SHUTDOWN ", MAX9880A_SYSTEM_SHUTDOWN },
{ "REV ID ", MAX9880A_REVISION_ID },
};
#define MAX9880A_REG_LENGTH (sizeof(max9880a_reg_table) / sizeof(max9880a_reg_table[0]))
uint32_t max9880a_dump_reg(MAX9880A_DEF_PTR obj)
{
int32_t ercd;
uint8_t buffer_rx[MAX9880A_REG_LENGTH - 1];// ignore last register (rev id)
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
MAX9880A_CHECK_EXP(iic_obj != NULL, E_OBJ);
ercd = iic_obj->iic_read((void *)buffer_rx, MAX9880A_REG_LENGTH - 1);
for (int i = 0; i < MAX9880A_REG_LENGTH - 1; i++) {
dbg_printf(DBG_LESS_INFO, " %s (0x%x) = 0x%x\n\r", max9880a_reg_table[i].str, max9880a_reg_table[i].reg, buffer_rx[i]);
}
error_exit:
return ercd;
}
uint32_t max9880a_config(MAX9880A_DEF_PTR obj, max9880a_config_t config)
{
int32_t ercd;
max9880a_settings_t *ptr;
uint32_t length;
uint8_t value[2];
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
MAX9880A_CHECK_EXP(iic_obj != NULL, E_OBJ);
switch (config) {
case MAX9880A_I2SIN_LINEOUT_13MHZ:
ptr = (max9880a_settings_t *)settings_i2sin_lineout_13mhz;
length = SETTINGS_I2SIN_LINEOUT_13MHZ_LENGTH;
break;
break;
case MAX9880A_LINEIN_I2SOUT_13MHZ:
ptr = (max9880a_settings_t *)settings_linein_i2sout_13mhz;
length = SETTINGS_LINEIN_I2SOUT_13MHZ_LENGTH;
break;
break;
case MAX9880A_I2SIN_LINEOUT_12DOT288MHZ:
ptr = (max9880a_settings_t *)settings_i2sin_lineout_12_288mhz;
length = SETTINGS_I2SIN_LINEOUT_12_288MHZ_LENGTH;
break;
break;
case MAX9880A_LINEIN_I2SOUT_12DOT288MHZ:
ptr = (max9880a_settings_t *)settings_linein_i2sout_12_288mhz;
length = SETTINGS_LINEIN_I2SOUT_12_288MHZ_LENGTH;
break;
break;
case MAX9880A_I2SIN_LINEOUT_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_i2sin_lineout_24_567mhz;
length = SETTINGS_I2SIN_LINEOUT_24_567MHZ_LENGTH;
break;
break;
case MAX9880A_LINEIN_I2SOUT_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_linein_i2sout_24_567mhz;
length = SETTINGS_LINEIN_I2SOUT_24_567MHZ_LENGTH;
break;
break;
case MAX9880A_DAI2_I2SIN_LINEOUT_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_dai2_i2sin_lineout_24_567mhz;
length = SETTINGS_DAI2_I2SIN_LINEOUT_24_567MHZ_LENGTH;
break;
break;
case MAX9880A_LINEIN_DAI1_I2SOUT_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_linein_dai1_i2sout_24_567mhz;
length = SETTINGS_LINEIN_DAI1_I2SOUT_24_567MHZ_LENGTH;
break;
break;
case MAX9880A_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_24_567mhz;
length = SETTINGS_24_567MHZ_LENGTH;
break;
default:
ptr = NULL;
length = 0;
break;
}
for (int i = 0; i < length; i++) {
value[0] = (uint8_t)(ptr[i].reg);
value[1] = (uint8_t)(ptr[i].val);
ercd = iic_obj->iic_write(value, 2);
dbg_printf(DBG_MORE_INFO, "[%d]iic_write 0x%x 0x%x ret %d\r\n", i, value[0], value[1], ercd);
MAX9880A_CHECK_EXP(ercd == 2, E_SYS);
}
ercd = E_OK;
error_exit:
return ercd;
}
uint32_t max9880a_init(MAX9880A_DEF_PTR obj)
{
int32_t ercd;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
MAX9880A_CHECK_EXP(iic_obj != NULL, E_OBJ);
ercd = iic_obj->iic_open(DEV_MASTER_MODE, IIC_SPEED_STANDARD);
dbg_printf(DBG_MORE_INFO, "[%s]iic_open ret %d\r\n", __FUNCTION__, ercd);// should return E_OK
MAX9880A_CHECK_EXP(ercd == E_OK, E_SYS);
ercd = iic_obj->iic_control(IIC_CMD_ENA_DEV, (void *)obj->slvaddr);
dbg_printf(DBG_MORE_INFO, "[%s]iic_control IIC_CMD_ENA_DEV ret %d\r\n", __FUNCTION__, ercd);// should return E_OK
MAX9880A_CHECK_EXP(ercd == E_OK, E_SYS);
ercd = iic_obj->iic_control(IIC_CMD_SET_ADDR_MODE, IIC_7BIT_ADDRESS);
dbg_printf(DBG_MORE_INFO, "[%s]iic_control IIC_CMD_SET_ADDR_MODE ret %d\r\n", __FUNCTION__, ercd);// should return E_OK
MAX9880A_CHECK_EXP(ercd == E_OK, E_SYS);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, (void *)obj->slvaddr);
dbg_printf(DBG_MORE_INFO, "[%s]iic_control IIC_CMD_MST_SET_TAR_ADDR ret %d\r\n", __FUNCTION__, ercd);// should return E_OK
MAX9880A_CHECK_EXP(ercd == E_OK, E_SYS);
// dbg_printf(DBG_LESS_INFO, "max9880a_init\n\r");
error_exit:
return ercd;
}
uint32_t max9880a_deinit(MAX9880A_DEF_PTR obj)
{
int32_t ercd;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
MAX9880A_CHECK_EXP(iic_obj != NULL, E_OBJ);
ercd = iic_obj->iic_close();
error_exit:
return ercd;
}

View File

@@ -1,94 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_MAX9880A
#define H_MAX9880A
// MAX9800A (Low-Power, High-Performance, Dual I²S, Stereo Audio Codec) is on EMSDP board
#define I2C_DEVICE_ADDRESS_MAX9880A (0x10)
typedef enum {
/**
* Use external MCLK of 13 MHz
* S1 pins are mapped on DAI1
* S2 pins are mapped on DAI2
*/
MAX9880A_I2SIN_LINEOUT_13MHZ = 0, // Playback
MAX9880A_LINEIN_I2SOUT_13MHZ, // Recording
/**
* Use no external MCLK, but route Xtal to clk-prescaler
* S1 pins are mapped on DAI1
* S2 pins are mapped on DAI2
*/
MAX9880A_I2SIN_LINEOUT_12DOT288MHZ, // Playback
MAX9880A_LINEIN_I2SOUT_24DOT567MHZ, // Recording
/**
* Use external MCLK of 24.567 MHz
* S1 pins are mapped on DAI1
* S2 pins are mapped on DAI2
*/
MAX9880A_I2SIN_LINEOUT_24DOT567MHZ, // Playback
MAX9880A_LINEIN_I2SOUT_24DOT567MHZ, // Recording
/**
* !!!! Use these settings for HSDK-IC on BOARD !!!!
*
* Mapping is now different
* S1 pins are mapped on DAI2
* S2 pins are mapped on DAI1
*
* Use external MCLK of 24.567 MHz
* Use DAI2 (S1) for playback (I2S-TX), Use DAI1 (S2) for recording (I2S-RX)
*/
MAX9880A_DAI2_I2SIN_LINEOUT_24DOT567MHZ, // Playback
MAX9880A_LINEIN_DAI1_I2SOUT_24DOT567MHZ, // Recording
MAX9880A_24DOT567MHZ, // PlayBack and Recording (Regression)
} max9880a_config_t;
/* temperature sensor object type*/
typedef struct {
uint32_t i2c_id;
uint32_t slvaddr;
} MAX9880A_DEF, *MAX9880A_DEF_PTR;
#define MAX9880A_DEFINE(NAME, I2C_ID, SLAVE_ADDRESS) \
MAX9880A_DEF __ ## NAME = { \
.i2c_id = I2C_ID, \
.slvaddr = SLAVE_ADDRESS, \
}; \
MAX9880A_DEF_PTR NAME = &__ ## NAME
extern uint32_t max9880a_dump_reg(MAX9880A_DEF_PTR obj);
extern uint32_t max9880a_config(MAX9880A_DEF_PTR obj, max9880a_config_t config);
extern uint32_t max9880a_init(MAX9880A_DEF_PTR obj);
extern uint32_t max9880a_deinit(MAX9880A_DEF_PTR obj);
#endif /* H_MAX9880A */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/audio/max9880a
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/audio/max9880a

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/flash/fl256s
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/flash/fl256s

View File

@@ -1,507 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "embARC.h"
#include "spi_flash_fl256s.h"
// #define DBG_MORE
#include "embARC_debug.h"
#define RDID 0x9F /*!<read chip ID */
#define RDSR1 0x05 /*!< read status register-1 */
#define WRSR1 0x01 /*!< write status registe-1 */
#define RDSR2 0x07 /*!< read status register-2 */
#define RDCR 0x35 /*!< read config register */
#define WREN 0x06 /*!< write enablewaitDeviceReady */
#define WRDI 0x04 /*!< write disable */
#define READ 0x03 /*!< read data bytes */
#define QORD 0x6B
#define SE 0x20 /*!< sector erase */
#define PP 0x02 /*!< page program */
#define QPP 0x32 /*!< page program */
#define FL256S_NOT_VALID (0xFFFFFFFF)
/**
* @fn int32_t _spi_send_cmd(FL256S_DEF_PTR dev, DEV_SPI_TRANSFER *xfer)
*/
Inline int32_t _spi_send_cmd(FL256S_DEF_PTR dev, DEV_SPI_TRANSFER *xfer)
{
uint32_t cpu_status;
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
spi_flash = spi_get_dev(dev->spi_master);
// cpu_status = cpu_lock_save();
/* select device */
spi_flash->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID((uint32_t)dev->cs));
spi_flash->spi_control(SPI_CMD_MST_SET_FREQ, CONV2VOID(dev->spi_freq));
spi_flash->spi_control(SPI_CMD_SET_CLK_MODE, CONV2VOID(SPI_CLK_MODE_0));
ercd = spi_flash->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(xfer));
/* deselect device */
spi_flash->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID((uint32_t)dev->cs));
// cpu_unlock_restore(cpu_status);
return ercd;
}
/**
* @fn int32_t _spi_send_cmd_quad(FL256S_DEF_PTR dev, DEV_SPI_PAK_PTR pak_ptr)
*/
Inline int32_t _spi_send_cmd_quad(FL256S_DEF_PTR dev, DEV_SPI_PAK_PTR pak_ptr)
{
uint32_t cpu_status;
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
spi_flash = spi_get_dev(dev->spi_master);
// cpu_status = cpu_lock_save();
/* select device */
spi_flash->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID((uint32_t)dev->cs));
spi_flash->spi_control(SPI_CMD_MST_SET_FREQ, CONV2VOID(dev->spi_freq));
spi_flash->spi_control(SPI_CMD_SET_CLK_MODE, CONV2VOID(SPI_CLK_MODE_0));
ercd = spi_flash->spi_control(SPI_CMD_QUAD_READ, CONV2VOID(pak_ptr));
/* deselect device */
spi_flash->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID((uint32_t)dev->cs));
// cpu_unlock_restore(cpu_status);
return ercd;
}
uint32_t fl256s_read_reg(FL256S_DEF_PTR dev, uint8_t reg, uint8_t *data, uint32_t len)
{
DEV_SPI_TRANSFER cmd_xfer = { 0 };
DEV_SPI_TRANSFER data_xfer = { 0 };
DEV_SPI_XFER_SET_TXBUF(&data_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_RXBUF(&data_xfer, data, 0, len);
DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, &reg, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, &data_xfer);
if (_spi_send_cmd(dev, &cmd_xfer) == 0) {
return len;
} else {
return FL256S_NOT_VALID;
}
}
uint32_t fl256s_write_reg(FL256S_DEF_PTR dev, uint8_t reg, uint8_t *data, uint32_t len)
{
DEV_SPI_TRANSFER cmd_xfer = { 0 };
DEV_SPI_TRANSFER data_xfer = { 0 };
DEV_SPI_XFER_SET_TXBUF(&data_xfer, data, 0, len);
DEV_SPI_XFER_SET_RXBUF(&data_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, &reg, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, &data_xfer);
if (_spi_send_cmd(dev, &cmd_xfer) == 0) {
return len;
} else {
return FL256S_NOT_VALID;
}
}
int32_t fl256s_quad_enable(FL256S_DEF_PTR dev)
{
uint32_t status = 0;
uint8_t w_data[2] = { 0 };
uint8_t r_data = 0;
status = fl256s_read_reg(dev, RDCR, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
if (!(r_data & 0x02)) {
w_data[1] = r_data | 0x02;
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
w_data[0] = r_data;
if (fl256s_write_enable(dev) != 0) {
return -1;
}
status = fl256s_write_reg(dev, WRSR1, w_data, 2);
if (status == FL256S_NOT_VALID) {
return -1;
}
dev->quad_en = 1;
} else {
dev->quad_en = 1;
}
return 0;
}
int32_t fl256s_quad_disable(FL256S_DEF_PTR dev)
{
uint32_t status = 0;
uint8_t w_data[2] = { 0 };
uint8_t r_data = 0;
status = fl256s_read_reg(dev, RDCR, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
if (r_data & 0x02) {
w_data[1] = r_data & 0xFD;
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
w_data[0] = r_data;
if (fl256s_write_enable(dev) != 0) {
return -1;
}
status = fl256s_write_reg(dev, WRSR1, w_data, 2);
if (status == FL256S_NOT_VALID) {
return -1;
}
dev->quad_en = 0;
} else {
dev->quad_en = 0;
}
return 0;
}
uint32_t fl256s_read_id(FL256S_DEF_PTR dev)
{
uint32_t id = 0;
uint8_t local_buf[5];
DEV_SPI_TRANSFER cmd_xfer;
local_buf[0] = RDID;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, local_buf, 0, 5);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (_spi_send_cmd(dev, &cmd_xfer) == 0) {
id = (local_buf[1] << 24) | (local_buf[2] << 16) | (local_buf[3] << 8) | local_buf[4];
} else {
id = FL256S_NOT_VALID;
}
dbg_printf(DBG_MORE_INFO, "fl256s_read_id buf: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\r\n", local_buf[0], local_buf[1], local_buf[2], local_buf[3], local_buf[4]);
return id;
}
int32_t fl256s_wait_ready(FL256S_DEF_PTR dev)
{
uint32_t status = 0x01;
uint8_t r_data = 0;
do {
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
} while (r_data & 0x01);// Status Register 1 Bit 0
return 0;
}
int32_t fl256s_init(FL256S_DEF_PTR dev, uint32_t freq)
{
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
dev->spi_freq = freq;
spi_flash = spi_get_dev(dev->spi_master);
ercd = spi_flash->spi_open(DEV_MASTER_MODE, freq);
if (ercd != E_OK && ercd != E_OPNED) {
return ercd;
}
// spi_flash->spi_control(SPI_CMD_SET_DUMMY_DATA, CONV2VOID(0xFF));
ercd = fl256s_wait_ready(dev);
dbg_printf(DBG_MORE_INFO, "fl256s_wait_ready ret %d\r\n", ercd);
return E_OK;
}
int32_t fl256s_write_enable(FL256S_DEF_PTR dev)
{
uint32_t status = 0;
uint8_t w_data, r_data = 0;
do {
status = fl256s_write_reg(dev, WREN, &w_data, 0);
if (status == FL256S_NOT_VALID) {
return -1;
}
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
// clear protection bits
// Write Protect. and Write Enable.
if ((r_data & 0xfc) && (r_data & 0x02)) {
w_data = 0;
status = fl256s_write_reg(dev, WRSR1, &w_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
r_data = 0;
}
} while (r_data != 0x02);
return 0;
}
int32_t fl256s_write_disable(FL256S_DEF_PTR dev)
{
uint32_t status = 0;
uint8_t w_data, r_data = 0;
do {
status = fl256s_write_reg(dev, WRDI, &w_data, 0);
if (status == FL256S_NOT_VALID) {
return -1;
}
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
dbg_printf(DBG_MORE_INFO, "fl256s_write_disable status = 0x%x\r\n", r_data);
if (status == FL256S_NOT_VALID) {
return -1;
}
} while (r_data & 0x02);// Status Register 1 Bit 1
return 0;
}
int32_t fl256s_erase(FL256S_DEF_PTR dev, uint32_t address, uint32_t size)
{
uint32_t last_address;
uint32_t count = 0;
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
// start address of last sector
last_address = (address + size) & (~(dev->sector_sz - 1));
// start address of first sector
address &= ~(dev->sector_sz - 1);
do {
if (fl256s_write_enable(dev) != 0) {
return -1;
}
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
local_buf[0] = SE;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (_spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
address += dev->sector_sz;
count++;
} while (address <= last_address);
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
if (fl256s_write_disable(dev) != 0) {
return -1;
}
return (int32_t)count;
}
int32_t fl256s_write(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, const void *data)
{
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
DEV_SPI_TRANSFER data_xfer;
uint32_t first = 0;
uint32_t size_orig = size;
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
first = FLASH_PAGE_SIZE - (address & (FLASH_PAGE_SIZE - 1));
do {
// send write enable command to flash
if (fl256s_write_enable(dev) != 0) {
return -1;
}
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
first = first < size ? first : size;
local_buf[0] = PP;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&data_xfer, data, 0, first);
DEV_SPI_XFER_SET_RXBUF(&data_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, &data_xfer);
if (_spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
size -= first;
address += first;
data += first;
first = FLASH_PAGE_SIZE;
} while (size);
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
if (fl256s_write_disable(dev) != 0) {
return -1;
}
return (int32_t)(size_orig);
}
int32_t fl256s_read(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, void *data)
{
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
DEV_SPI_TRANSFER data_xfer;
uint32_t first = 0;
uint32_t size_orig = size;
first = FLASH_PAGE_SIZE - (address & (FLASH_PAGE_SIZE - 1));
do {
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
first = first < size ? first : size;
local_buf[0] = READ;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&data_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_RXBUF(&data_xfer, data, 0, first);
DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, &data_xfer);
if (_spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
size -= first;
address += first;
data += first;
first = FLASH_PAGE_SIZE;
} while (size);
return (int32_t)(size_orig);
}
int32_t fl256s_quad_read(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, void *data)
{
DEV_SPI_PAK spi_pak;
uint32_t first = 0;
uint32_t size_orig = size;
uint32_t per_read_size = 32;
first = per_read_size - (address & (per_read_size - 1));
do {
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
first = first < size ? first : size;
spi_pak.cmd = QORD;
spi_pak.addr32 = address;
spi_pak.data_len = first;
spi_pak.data_ptr = data;
if (_spi_send_cmd_quad(dev, &spi_pak) != 0) {
return -1;
}
size -= first;
address += first;
data += first;
first = per_read_size;
} while (size);
return (int32_t)(size_orig);
}

View File

@@ -1,93 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_SPI_FLASH_FL256S
#define H_SPI_FLASH_FL256S
// Manufacturer: 0x01, DeviceId: 0x0219, ID-CFI: 0x4D
#define FLASH_ID 0x0102194D
#define FLASH_SECTOR_SIZE 0x00001000
#define FLASH_PAGE_SIZE 0x00000100
#include "embARC_toolchain.h"
#include "embARC_error.h"
/** flash data type */
typedef struct {
uint32_t head; /*!< 0x68656164 ='head' */
uint32_t cpu_type; /*!< = 0 - all images, reserved for future */
uint32_t start; /*!< start address of application image in spi flash */
uint32_t size; /*!< size of image in bytes */
uint32_t ramaddr; /*!< address of ram for loading image */
uint32_t ramstart; /*!< start address of application in RAM !!!! */
uint32_t checksum; /*!< checksum of all bytes in image */
} image_t;
/** fl256s object type */
typedef struct {
uint8_t spi_master;
uint8_t cs;
uint8_t quad_en;
uint32_t spi_freq;
uint32_t page_sz;
uint32_t sector_sz;
} FL256S_DEF, *FL256S_DEF_PTR;
#define FL256S_DEF(name, spi_master_id, cs_line, page, sector) \
FL256S_DEF __ ## name = { \
.spi_master = spi_master_id, \
.cs = cs_line, \
.page_sz = page, \
.sector_sz = sector \
}; \
FL256S_DEF_PTR name = &__ ## name \
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t fl256s_read_status(FL256S_DEF_PTR dev);
extern uint32_t fl256s_read_id(FL256S_DEF_PTR dev);
extern int32_t fl256s_read(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, void *data);
extern int32_t fl256s_quad_read(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, void *data);
extern int32_t fl256s_write_enable(FL256S_DEF_PTR dev);
extern int32_t fl256s_write_disable(FL256S_DEF_PTR dev);
extern int32_t fl256s_erase(FL256S_DEF_PTR dev, uint32_t address, uint32_t size);
extern int32_t fl256s_write(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, const void *data);
extern int32_t fl256s_wait_ready(FL256S_DEF_PTR dev);
extern int32_t fl256s_init(FL256S_DEF_PTR dev, uint32_t freq);
extern int32_t fl256s_quad_enable(FL256S_DEF_PTR dev);
extern int32_t fl256s_quad_disable(FL256S_DEF_PTR dev);
#ifdef __cplusplus
}
#endif
#endif /* H_SPI_FLASH_FL256S */

View File

@@ -1,371 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "spi_flash_w25qxx.h"
#include "embARC_error.h"
#include "board.h"
#include "device/ip_hal/dev_spi.h"
#include "arc/arc_exception.h"
#include "string.h"
/**
* @name W25QXX SPI Flash Commands
* @{
*/
#define RDID 0x9F /*!<read chip ID */
#define RDSR 0x05 /*!< read status register */
#define WRSR 0x01 /*!< write status register */
#define WREN 0x06 /*!< write enablewaitDeviceReady */
#define WRDI 0x04 /*!< write disable */
#define READ 0x03 /*!< read data bytes */
#define SE 0x20 /*!< sector erase */
#define PP 0x02 /*!< page program */
/** @} end of name */
#define W25QXX_NOT_VALID (0xFFFFFFFF)
/**
* @fn int32_t spi_send_cmd(W25QXX_DEF_PTR dev, DEV_SPI_TRANSFER *xfer)
* @brief SPI flash spi send command to operate spi flash
* @param[in] xfer SPI transfer that need to transfer to spi device
* @retval 0 success
* @retval -1 fail
*/
Inline int32_t spi_send_cmd(W25QXX_DEF_PTR dev, DEV_SPI_TRANSFER *xfer)
{
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
spi_flash = spi_get_dev(dev->spi_master);
/* select device */
spi_flash->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID((uint32_t)dev->cs));
spi_flash->spi_control(SPI_CMD_MST_SET_FREQ, CONV2VOID(dev->spi_freq));
spi_flash->spi_control(SPI_CMD_SET_CLK_MODE, CONV2VOID(SPI_CLK_MODE_0));
ercd = spi_flash->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(xfer));
/* deselect device */
spi_flash->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID((uint32_t)dev->cs));
return ercd;
}
/**
* @brief Read the status of spi flash
* @return Current status of spi flash
*/
uint32_t w25qxx_read_status(W25QXX_DEF_PTR dev)
{
uint8_t local_buf[2];
DEV_SPI_TRANSFER cmd_xfer;
local_buf[0] = RDSR;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, local_buf, 1, 1);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) == 0) {
return (uint32_t)local_buf[0];
} else {
return W25QXX_NOT_VALID;
}
}
/**
* @brief Enable to write flash
* @retval 0 Enable operation successfully
* @retval -1 Enable operation failed
*/
int32_t w25qxx_write_enable(W25QXX_DEF_PTR dev)
{
uint8_t local_buf[3];
DEV_SPI_TRANSFER cmd_xfer;
uint32_t status = 0;
do {
local_buf[0] = WREN;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
status = w25qxx_read_status(dev);
if (status == W25QXX_NOT_VALID) {
return -1;
}
// clear protection bits
// Write Protect. and Write Enable.
if ((status & 0xfc) && (status & 0x02)) {
local_buf[0] = WRSR; // write status
local_buf[1] = 0x00; // write status
local_buf[2] = 0x00; // write status
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 3);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
status = 0;
}
} while (status != 0x02);
return 0;
}
/**
* @brief Initialize spi flash interface
* @retval 0 Initialize successfully
* @retval -1 Initialize failed
*/
int32_t w25qxx_init(W25QXX_DEF_PTR dev, uint32_t freq)
{
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
dev->spi_freq = freq;
spi_flash = spi_get_dev(dev->spi_master);
ercd = spi_flash->spi_open(DEV_MASTER_MODE, freq);
if (ercd != E_OK && ercd != E_OPNED) {
return ercd;
}
spi_flash->spi_control(SPI_CMD_SET_DUMMY_DATA, CONV2VOID(0xFF));
return E_OK;
}
/**
* @brief Read spi flash identification ID
* @return The id of the spi flash
*/
uint32_t w25qxx_read_id(W25QXX_DEF_PTR dev)
{
uint32_t id = 0;
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
local_buf[0] = RDID;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, local_buf, 1, 3);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) == 0) {
id = (local_buf[0] << 16) | (local_buf[1] << 8) | local_buf[2];
} else {
id = W25QXX_NOT_VALID;
}
return id;
}
/**
* @brief Read status and wait while busy flag is set
* @retval 0 Success
* @retval -1 Fail
*/
int32_t w25qxx_wait_ready(W25QXX_DEF_PTR dev)
{
uint32_t status = 0x01;
do {
status = w25qxx_read_status(dev);
if (status == W25QXX_NOT_VALID) {
return -1;
}
} while (status & 0x01);
return 0;
}
/**
* @brief Read data from flash
* @param[in] address Start address
* @param[in] size Data size
* @param[out] data Pointer to the return data
*
* @retval -1 Read failed
* @retval >= 0 Data size
*/
int32_t w25qxx_read(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size, void *data)
{
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
local_buf[0] = READ;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, data, 4, size);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) == 0) {
return size;
} else {
return -1;
}
}
/**
* @brief Flash erase in sectors
*
* @param[in] address Erase start address of spi flash
* @param[in] size Erase size
*
* @retval -1 Erase failed
* @retval >= 0 Sector count erased
*/
int32_t w25qxx_erase(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size)
{
uint32_t last_address;
uint32_t count = 0;
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
// start address of last sector
last_address = (address + size) & (~(dev->sector_sz - 1));
// start address of first sector
address &= ~(dev->sector_sz - 1);
do {
if (w25qxx_write_enable(dev) != 0) {
return -1;
}
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
local_buf[0] = SE;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
address += dev->sector_sz;
count++;
} while (address <= last_address);
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
return (int32_t)count;
}
/**
* @brief Write data to spi flash
*
* @param[in] address Start address
* @param[in] size Data size
* @param[in] data Pointer to data
*
* @retval >= 0 Written bytes number
* @retval < 0 Write data failed
*/
int32_t w25qxx_write(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size, const void *data)
{
DEV_SPI_TRANSFER cmd_xfer;
uint32_t first = 0;
uint32_t size_orig = size;
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
first = FLASH_PAGE_SIZE - (address & (FLASH_PAGE_SIZE - 1));
do {
// send write enable command to flash
if (w25qxx_write_enable(dev) != 0) {
return -1;
}
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
first = first < size ? first : size;
dev->write_buf[0] = PP;
dev->write_buf[1] = (address >> 16) & 0xff;
dev->write_buf[2] = (address >> 8) & 0xff;
dev->write_buf[3] = address & 0xff;
memcpy(&(dev->write_buf[4]), data, first);
// DEV_SPI_XFER_SET_TXBUF(&data_xfer, data, 0, first);
// DEV_SPI_XFER_SET_RXBUF(&data_xfer, NULL, 0, 0);
// DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, dev->write_buf, 0, 4 + first);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
size -= first;
address += first;
data += first;
first = FLASH_PAGE_SIZE;
} while (size);
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
return (int32_t)(size_orig);
}

View File

@@ -1,87 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_SPI_FLASH_W25QXX
#define H_SPI_FLASH_W25QXX
#define FLASH_PAGE_SIZE 0x100
#define FLASH_SECTOR_SIZE 0x1000
#include "embARC_toolchain.h"
#include "embARC_error.h"
/** flash data type */
typedef struct {
uint32_t head; /*!< 0x68656164 ='head' */
uint32_t cpu_type; /*!< = 0 - all images, reserved for future */
uint32_t start; /*!< start address of application image in spi flash */
uint32_t size; /*!< size of image in bytes */
uint32_t ramaddr; /*!< address of ram for loading image */
uint32_t ramstart; /*!< start address of application in RAM !!!! */
uint32_t checksum; /*!< checksum of all bytes in image */
} image_t;
/** w25qxx object type */
typedef struct {
uint8_t spi_master;
uint8_t cs;
uint32_t spi_freq;
uint32_t page_sz;
uint32_t sector_sz;
uint8_t write_buf[4 + FLASH_PAGE_SIZE];
} W25QXX_DEF, *W25QXX_DEF_PTR;
#define W25QXX_DEF(name, spi_master_id, cs_line, page, sector) \
W25QXX_DEF __ ## name = { \
.spi_master = spi_master_id, \
.cs = cs_line, \
.page_sz = page, \
.sector_sz = sector \
}; \
W25QXX_DEF_PTR name = &__ ## name \
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t w25qxx_read_status(W25QXX_DEF_PTR dev);
extern uint32_t w25qxx_read_id(W25QXX_DEF_PTR dev);
extern int32_t w25qxx_read(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size, void *data);
extern int32_t w25qxx_write_enable(W25QXX_DEF_PTR dev);
extern int32_t w25qxx_erase(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size);
extern int32_t w25qxx_write(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size, const void *data);
extern int32_t w25qxx_wait_ready(W25QXX_DEF_PTR dev);
extern int32_t w25qxx_init(W25QXX_DEF_PTR dev, uint32_t freq);
#ifdef __cplusplus
}
#endif
#endif /* H_SPI_FLASH_W25QXX */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/flash/w25qxx
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/flash/w25qxx

View File

@@ -1,138 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include <stdint.h>
#include "embARC_error.h"
#include "embARC_debug.h"
#include "board.h"
#include "cy8c95xx.h"
#define CY8C95XX_CHECK_EXP_NORTN(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
int32_t cy8c95xx_reg_write(CY8C95XX_DEF_PTR obj, uint8_t dev, uint8_t regaddr, uint8_t *val, uint8_t len)
{
int32_t ercd = E_OK;
uint8_t data[1];
uint32_t slvaddr;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_LESS_INFO, "[%s]%d: obj 0x%x, regaddr 0x%x, val 0x%x\r\n", __FUNCTION__, __LINE__, obj, regaddr, *val);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
CY8C95XX_CHECK_EXP_NORTN(iic_obj != NULL, E_PAR);
CY8C95XX_CHECK_EXP_NORTN((dev == 0) || (dev == 1), E_PAR);
if (dev == 0) {
slvaddr = obj->slvaddr_io;
} else {
slvaddr = obj->slvaddr_eep;
}
data[0] = (uint8_t)(regaddr & 0xff);
/** make sure set the temp sensor's slave address */
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slvaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_write(val, len);
error_exit:
return ercd;
}
int32_t cy8c95xx_reg_read(CY8C95XX_DEF_PTR obj, uint8_t dev, uint8_t regaddr, uint8_t *val, uint8_t len)
{
int32_t ercd = E_OK;
uint8_t data[1];
uint32_t slvaddr;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
CY8C95XX_CHECK_EXP_NORTN(iic_obj != NULL, E_PAR);
CY8C95XX_CHECK_EXP_NORTN((dev == 0) || (dev == 1), E_PAR);
if (dev == 0) {
slvaddr = obj->slvaddr_io;
} else {
slvaddr = obj->slvaddr_eep;
}
data[0] = (uint8_t)(regaddr & 0xff);
/** make sure set the temp sensor's slave address */
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slvaddr));
/** write register address then read register value */
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_read(val, len);
error_exit:
return ercd;
}
int32_t cy8c95xx_readid(CY8C95XX_DEF_PTR obj, uint8_t *value)
{
int32_t ercd = E_OK;
uint8_t buffer_rx[1];
CY8C95XX_CHECK_EXP_NORTN(value != NULL, E_PAR);
CY8C95XX_CHECK_EXP_NORTN(cy8c95xx_reg_read(obj, CY8C95XX_DEV_IO, CY8C95XX_DEVICE_ID_REG, buffer_rx, 1) == E_OK, E_SYS);
*value = buffer_rx[0];
error_exit:
return ercd;
}
int32_t cy8c95xx_writeport(CY8C95XX_DEF_PTR obj, uint8_t port, uint8_t value)
{
int32_t ercd = E_OK;
uint8_t buffer_tx[1];
uint8_t val = 0;
CY8C95XX_CHECK_EXP_NORTN(port < CY8C95XX_PORT_NONE, E_PAR);
// Set port [0..7]
buffer_tx[0] = value;
CY8C95XX_CHECK_EXP_NORTN(cy8c95xx_reg_write(obj, CY8C95XX_DEV_IO, CY8C95XX_OUTPUT_PORT0_REG + port, buffer_tx, 1) == E_OK, E_SYS);
CY8C95XX_CHECK_EXP_NORTN(cy8c95xx_reg_read(obj, CY8C95XX_DEV_IO, CY8C95XX_OUTPUT_PORT0_REG + port, &val, 1) == E_OK, E_SYS);
CY8C95XX_CHECK_EXP_NORTN(val == value, E_OBJ);
error_exit:
return ercd;
}
int32_t cy8c95xx_readport(CY8C95XX_DEF_PTR obj, uint8_t port, uint8_t *value)
{
int32_t ercd = E_OK;
CY8C95XX_CHECK_EXP_NORTN(port < CY8C95XX_PORT_NONE, E_PAR);
CY8C95XX_CHECK_EXP_NORTN(cy8c95xx_reg_read(obj, CY8C95XX_DEV_IO, CY8C95XX_INPUT_PORT0_REG + port, value, 1) == E_OK, E_SYS);
error_exit:
return ercd;
}

View File

@@ -1,149 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_CY8C95XX
#define H_CY8C95XX
#define CY8C95XX_I2C_TIMEOUT (5000000)
// CY8C95xx Series Interface is a multi-port IO expander using I2C bus, on HSDK board
typedef enum {
CY8C95XX_DEV_IO = 0,
CY8C95XX_DEV_EEP
} CY8C95XX_DEV_T;
typedef enum {
CY8C95XX_PORT_0 = 0,
CY8C95XX_PORT_1,
CY8C95XX_PORT_2,
CY8C95XX_PORT_NONE
} CY8C95XX_PORT_T;
typedef enum {
CY8C95XX_PIN_0 = 0,
CY8C95XX_PIN_1,
CY8C95XX_PIN_2,
CY8C95XX_PIN_3,
CY8C95XX_PIN_4,
CY8C95XX_PIN_5,
CY8C95XX_PIN_6,
CY8C95XX_PIN_7,
CY8C95XX_PIN_NONE
} CY8C95XX_PIN_T;
typedef enum {
CY8C95XX_PWM_0 = 0,
CY8C95XX_PWM_1,
CY8C95XX_PWM_2,
CY8C95XX_PWM_3,
CY8C95XX_PWM_NONE
} CY8C95XX_PWM_T;
typedef enum {
CY8C95XX_PWMFREQ_100HZ = 0,
CY8C95XX_PWMFREQ_300HZ,
CY8C95XX_PWMFREQ_500HZ,
CY8C95XX_PWMFREQ_700HZ,
CY8C95XX_PWMFREQ_900HZ,
CY8C95XX_PWMFREQ_NONE
} CY8C95XX_PWMFREQ_T;
typedef enum {
CY8C95XX_ENABLE_WDE = 0,
CY8C95XX_ENABLE_EEE,
CY8C95XX_ENABLE_EERO,
CY8C95XX_ENABLE_NONE
} CY8C95XX_ENABLE_T;
typedef struct {
uint32_t i2c_id;
uint32_t slvaddr_io;
uint32_t slvaddr_eep;
} CY8C95XX_DEF, *CY8C95XX_DEF_PTR;
#define CY8C95XX_INPUT_PORT0_REG 0x00
#define CY8C95XX_INPUT_PORT1_REG 0x01
#define CY8C95XX_INPUT_PORT2_REG 0x02
#define CY8C95XX_INPUT_PORT3_REG 0x03
#define CY8C95XX_INPUT_PORT4_REG 0x04
#define CY8C95XX_INPUT_PORT5_REG 0x05
#define CY8C95XX_INPUT_PORT6_REG 0x06
#define CY8C95XX_INPUT_PORT7_REG 0x07
#define CY8C95XX_OUTPUT_PORT0_REG 0x08
#define CY8C95XX_OUTPUT_PORT1_REG 0x09
#define CY8C95XX_OUTPUT_PORT2_REG 0x0A
#define CY8C95XX_OUTPUT_PORT3_REG 0x0B
#define CY8C95XX_OUTPUT_PORT4_REG 0x0C
#define CY8C95XX_OUTPUT_PORT5_REG 0x0D
#define CY8C95XX_OUTPUT_PORT6_REG 0x0E
#define CY8C95XX_OUTPUT_PORT7_REG 0x0F
#define CY8C95XX_INTSTS_PORT0_REG 0x10
#define CY8C95XX_INTSTS_PORT1_REG 0x11
#define CY8C95XX_INTSTS_PORT2_REG 0x12
#define CY8C95XX_INTSTS_PORT3_REG 0x13
#define CY8C95XX_INTSTS_PORT4_REG 0x14
#define CY8C95XX_INTSTS_PORT5_REG 0x15
#define CY8C95XX_INTSTS_PORT6_REG 0x16
#define CY8C95XX_INTSTS_PORT7_REG 0x17
#define CY8C95XX_PORT_SELECT_REG 0x18
#define CY8C95XX_INTMSK_REG 0x19
#define CY8C95XX_PORT_SELECT_PWM 0x1A
#define CY8C95XX_PIN_DIRECTION_REG 0x1C
#define CY8C95XX_DRIVE_MODE_PU_REG 0x1D
#define CY8C95XX_DRIVE_MODE_PD_REG 0x1E
#define CY8C95XX_DRIVE_MODE_ODH_REG 0x1F
#define CY8C95XX_DRIVE_MODE_ODL_REG 0x20
#define CY8C95XX_DRIVE_MODE_S_REG 0x21
#define CY8C95XX_DRIVE_MODE_SS_REG 0x22
#define CY8C95XX_DRIVE_MODE_HZ_REG 0x23
#define CY8C95XX_PWM_SELECT 0x28
#define CY8C95XX_PWM_CONFIG 0x29
#define CY8C95XX_PWM_PERIOD 0x2A
#define CY8C95XX_PWM_PULSEWIDTH 0x2B
#define CY8C95XX_PWM_DIVIDER 0x2C
#define CY8C95XX_ENABLE_REG 0x2D
#define CY8C95XX_DEVICE_ID_REG 0x2E
#define CY8C95XX_COMMAND_REG 0x30
extern int32_t cy8c95xx_readid(CY8C95XX_DEF_PTR obj, uint8_t *value);
extern int32_t cy8c95xx_writeport(CY8C95XX_DEF_PTR obj, uint8_t port, uint8_t value);
extern int32_t cy8c95xx_readport(CY8C95XX_DEF_PTR obj, uint8_t port, uint8_t *value);
extern int32_t cy8c95xx_reg_write(CY8C95XX_DEF_PTR obj, uint8_t dev, uint8_t regaddr, uint8_t *val, uint8_t len);
extern int32_t cy8c95xx_reg_read(CY8C95XX_DEF_PTR obj, uint8_t dev, uint8_t regaddr, uint8_t *val, uint8_t len);
#endif /* H_CY8C95XX */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/io/cy8c95xx
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/io/cy8c95xx

View File

@@ -1,519 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/*
$License:
Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
$
*/
#ifndef DMPKEY_H__
#define DMPKEY_H__
#define KEY_CFG_25 (0)
#define KEY_CFG_24 (KEY_CFG_25 + 1)
#define KEY_CFG_26 (KEY_CFG_24 + 1)
#define KEY_CFG_27 (KEY_CFG_26 + 1)
#define KEY_CFG_21 (KEY_CFG_27 + 1)
#define KEY_CFG_20 (KEY_CFG_21 + 1)
#define KEY_CFG_TAP4 (KEY_CFG_20 + 1)
#define KEY_CFG_TAP5 (KEY_CFG_TAP4 + 1)
#define KEY_CFG_TAP6 (KEY_CFG_TAP5 + 1)
#define KEY_CFG_TAP7 (KEY_CFG_TAP6 + 1)
#define KEY_CFG_TAP0 (KEY_CFG_TAP7 + 1)
#define KEY_CFG_TAP1 (KEY_CFG_TAP0 + 1)
#define KEY_CFG_TAP2 (KEY_CFG_TAP1 + 1)
#define KEY_CFG_TAP3 (KEY_CFG_TAP2 + 1)
#define KEY_CFG_TAP_QUANTIZE (KEY_CFG_TAP3 + 1)
#define KEY_CFG_TAP_JERK (KEY_CFG_TAP_QUANTIZE + 1)
#define KEY_CFG_DR_INT (KEY_CFG_TAP_JERK + 1)
#define KEY_CFG_AUTH (KEY_CFG_DR_INT + 1)
#define KEY_CFG_TAP_SAVE_ACCB (KEY_CFG_AUTH + 1)
#define KEY_CFG_TAP_CLEAR_STICKY (KEY_CFG_TAP_SAVE_ACCB + 1)
#define KEY_CFG_FIFO_ON_EVENT (KEY_CFG_TAP_CLEAR_STICKY + 1)
#define KEY_FCFG_ACCEL_INPUT (KEY_CFG_FIFO_ON_EVENT + 1)
#define KEY_FCFG_ACCEL_INIT (KEY_FCFG_ACCEL_INPUT + 1)
#define KEY_CFG_23 (KEY_FCFG_ACCEL_INIT + 1)
#define KEY_FCFG_1 (KEY_CFG_23 + 1)
#define KEY_FCFG_3 (KEY_FCFG_1 + 1)
#define KEY_FCFG_2 (KEY_FCFG_3 + 1)
#define KEY_CFG_3D (KEY_FCFG_2 + 1)
#define KEY_CFG_3B (KEY_CFG_3D + 1)
#define KEY_CFG_3C (KEY_CFG_3B + 1)
#define KEY_FCFG_5 (KEY_CFG_3C + 1)
#define KEY_FCFG_4 (KEY_FCFG_5 + 1)
#define KEY_FCFG_7 (KEY_FCFG_4 + 1)
#define KEY_FCFG_FSCALE (KEY_FCFG_7 + 1)
#define KEY_FCFG_AZ (KEY_FCFG_FSCALE + 1)
#define KEY_FCFG_6 (KEY_FCFG_AZ + 1)
#define KEY_FCFG_LSB4 (KEY_FCFG_6 + 1)
#define KEY_CFG_12 (KEY_FCFG_LSB4 + 1)
#define KEY_CFG_14 (KEY_CFG_12 + 1)
#define KEY_CFG_15 (KEY_CFG_14 + 1)
#define KEY_CFG_16 (KEY_CFG_15 + 1)
#define KEY_CFG_18 (KEY_CFG_16 + 1)
#define KEY_CFG_6 (KEY_CFG_18 + 1)
#define KEY_CFG_7 (KEY_CFG_6 + 1)
#define KEY_CFG_4 (KEY_CFG_7 + 1)
#define KEY_CFG_5 (KEY_CFG_4 + 1)
#define KEY_CFG_2 (KEY_CFG_5 + 1)
#define KEY_CFG_3 (KEY_CFG_2 + 1)
#define KEY_CFG_1 (KEY_CFG_3 + 1)
#define KEY_CFG_EXTERNAL (KEY_CFG_1 + 1)
#define KEY_CFG_8 (KEY_CFG_EXTERNAL + 1)
#define KEY_CFG_9 (KEY_CFG_8 + 1)
#define KEY_CFG_ORIENT_3 (KEY_CFG_9 + 1)
#define KEY_CFG_ORIENT_2 (KEY_CFG_ORIENT_3 + 1)
#define KEY_CFG_ORIENT_1 (KEY_CFG_ORIENT_2 + 1)
#define KEY_CFG_GYRO_SOURCE (KEY_CFG_ORIENT_1 + 1)
#define KEY_CFG_ORIENT_IRQ_1 (KEY_CFG_GYRO_SOURCE + 1)
#define KEY_CFG_ORIENT_IRQ_2 (KEY_CFG_ORIENT_IRQ_1 + 1)
#define KEY_CFG_ORIENT_IRQ_3 (KEY_CFG_ORIENT_IRQ_2 + 1)
#define KEY_FCFG_MAG_VAL (KEY_CFG_ORIENT_IRQ_3 + 1)
#define KEY_FCFG_MAG_MOV (KEY_FCFG_MAG_VAL + 1)
#define KEY_CFG_LP_QUAT (KEY_FCFG_MAG_MOV + 1)
/* MPU6050 keys */
#define KEY_CFG_ACCEL_FILTER (KEY_CFG_LP_QUAT + 1)
#define KEY_CFG_MOTION_BIAS (KEY_CFG_ACCEL_FILTER + 1)
#define KEY_TEMPLABEL (KEY_CFG_MOTION_BIAS + 1)
#define KEY_D_0_22 (KEY_TEMPLABEL + 1)
#define KEY_D_0_24 (KEY_D_0_22 + 1)
#define KEY_D_0_36 (KEY_D_0_24 + 1)
#define KEY_D_0_52 (KEY_D_0_36 + 1)
#define KEY_D_0_96 (KEY_D_0_52 + 1)
#define KEY_D_0_104 (KEY_D_0_96 + 1)
#define KEY_D_0_108 (KEY_D_0_104 + 1)
#define KEY_D_0_163 (KEY_D_0_108 + 1)
#define KEY_D_0_188 (KEY_D_0_163 + 1)
#define KEY_D_0_192 (KEY_D_0_188 + 1)
#define KEY_D_0_224 (KEY_D_0_192 + 1)
#define KEY_D_0_228 (KEY_D_0_224 + 1)
#define KEY_D_0_232 (KEY_D_0_228 + 1)
#define KEY_D_0_236 (KEY_D_0_232 + 1)
#define KEY_DMP_PREVPTAT (KEY_D_0_236 + 1)
#define KEY_D_1_2 (KEY_DMP_PREVPTAT + 1)
#define KEY_D_1_4 (KEY_D_1_2 + 1)
#define KEY_D_1_8 (KEY_D_1_4 + 1)
#define KEY_D_1_10 (KEY_D_1_8 + 1)
#define KEY_D_1_24 (KEY_D_1_10 + 1)
#define KEY_D_1_28 (KEY_D_1_24 + 1)
#define KEY_D_1_36 (KEY_D_1_28 + 1)
#define KEY_D_1_40 (KEY_D_1_36 + 1)
#define KEY_D_1_44 (KEY_D_1_40 + 1)
#define KEY_D_1_72 (KEY_D_1_44 + 1)
#define KEY_D_1_74 (KEY_D_1_72 + 1)
#define KEY_D_1_79 (KEY_D_1_74 + 1)
#define KEY_D_1_88 (KEY_D_1_79 + 1)
#define KEY_D_1_90 (KEY_D_1_88 + 1)
#define KEY_D_1_92 (KEY_D_1_90 + 1)
#define KEY_D_1_96 (KEY_D_1_92 + 1)
#define KEY_D_1_98 (KEY_D_1_96 + 1)
#define KEY_D_1_100 (KEY_D_1_98 + 1)
#define KEY_D_1_106 (KEY_D_1_100 + 1)
#define KEY_D_1_108 (KEY_D_1_106 + 1)
#define KEY_D_1_112 (KEY_D_1_108 + 1)
#define KEY_D_1_128 (KEY_D_1_112 + 1)
#define KEY_D_1_152 (KEY_D_1_128 + 1)
#define KEY_D_1_160 (KEY_D_1_152 + 1)
#define KEY_D_1_168 (KEY_D_1_160 + 1)
#define KEY_D_1_175 (KEY_D_1_168 + 1)
#define KEY_D_1_176 (KEY_D_1_175 + 1)
#define KEY_D_1_178 (KEY_D_1_176 + 1)
#define KEY_D_1_179 (KEY_D_1_178 + 1)
#define KEY_D_1_218 (KEY_D_1_179 + 1)
#define KEY_D_1_232 (KEY_D_1_218 + 1)
#define KEY_D_1_236 (KEY_D_1_232 + 1)
#define KEY_D_1_240 (KEY_D_1_236 + 1)
#define KEY_D_1_244 (KEY_D_1_240 + 1)
#define KEY_D_1_250 (KEY_D_1_244 + 1)
#define KEY_D_1_252 (KEY_D_1_250 + 1)
#define KEY_D_2_12 (KEY_D_1_252 + 1)
#define KEY_D_2_96 (KEY_D_2_12 + 1)
#define KEY_D_2_108 (KEY_D_2_96 + 1)
#define KEY_D_2_208 (KEY_D_2_108 + 1)
#define KEY_FLICK_MSG (KEY_D_2_208 + 1)
#define KEY_FLICK_COUNTER (KEY_FLICK_MSG + 1)
#define KEY_FLICK_LOWER (KEY_FLICK_COUNTER + 1)
#define KEY_CFG_FLICK_IN (KEY_FLICK_LOWER + 1)
#define KEY_FLICK_UPPER (KEY_CFG_FLICK_IN + 1)
#define KEY_CGNOTICE_INTR (KEY_FLICK_UPPER + 1)
#define KEY_D_2_224 (KEY_CGNOTICE_INTR + 1)
#define KEY_D_2_244 (KEY_D_2_224 + 1)
#define KEY_D_2_248 (KEY_D_2_244 + 1)
#define KEY_D_2_252 (KEY_D_2_248 + 1)
#define KEY_D_GYRO_BIAS_X (KEY_D_2_252 + 1)
#define KEY_D_GYRO_BIAS_Y (KEY_D_GYRO_BIAS_X + 1)
#define KEY_D_GYRO_BIAS_Z (KEY_D_GYRO_BIAS_Y + 1)
#define KEY_D_ACC_BIAS_X (KEY_D_GYRO_BIAS_Z + 1)
#define KEY_D_ACC_BIAS_Y (KEY_D_ACC_BIAS_X + 1)
#define KEY_D_ACC_BIAS_Z (KEY_D_ACC_BIAS_Y + 1)
#define KEY_D_GYRO_ENABLE (KEY_D_ACC_BIAS_Z + 1)
#define KEY_D_ACCEL_ENABLE (KEY_D_GYRO_ENABLE + 1)
#define KEY_D_QUAT_ENABLE (KEY_D_ACCEL_ENABLE + 1)
#define KEY_D_OUTPUT_ENABLE (KEY_D_QUAT_ENABLE + 1)
#define KEY_D_CR_TIME_G (KEY_D_OUTPUT_ENABLE + 1)
#define KEY_D_CR_TIME_A (KEY_D_CR_TIME_G + 1)
#define KEY_D_CR_TIME_Q (KEY_D_CR_TIME_A + 1)
#define KEY_D_CS_TAX (KEY_D_CR_TIME_Q + 1)
#define KEY_D_CS_TAY (KEY_D_CS_TAX + 1)
#define KEY_D_CS_TAZ (KEY_D_CS_TAY + 1)
#define KEY_D_CS_TGX (KEY_D_CS_TAZ + 1)
#define KEY_D_CS_TGY (KEY_D_CS_TGX + 1)
#define KEY_D_CS_TGZ (KEY_D_CS_TGY + 1)
#define KEY_D_CS_TQ0 (KEY_D_CS_TGZ + 1)
#define KEY_D_CS_TQ1 (KEY_D_CS_TQ0 + 1)
#define KEY_D_CS_TQ2 (KEY_D_CS_TQ1 + 1)
#define KEY_D_CS_TQ3 (KEY_D_CS_TQ2 + 1)
/* Compass keys */
#define KEY_CPASS_BIAS_X (KEY_D_CS_TQ3 + 1)
#define KEY_CPASS_BIAS_Y (KEY_CPASS_BIAS_X + 1)
#define KEY_CPASS_BIAS_Z (KEY_CPASS_BIAS_Y + 1)
#define KEY_CPASS_MTX_00 (KEY_CPASS_BIAS_Z + 1)
#define KEY_CPASS_MTX_01 (KEY_CPASS_MTX_00 + 1)
#define KEY_CPASS_MTX_02 (KEY_CPASS_MTX_01 + 1)
#define KEY_CPASS_MTX_10 (KEY_CPASS_MTX_02 + 1)
#define KEY_CPASS_MTX_11 (KEY_CPASS_MTX_10 + 1)
#define KEY_CPASS_MTX_12 (KEY_CPASS_MTX_11 + 1)
#define KEY_CPASS_MTX_20 (KEY_CPASS_MTX_12 + 1)
#define KEY_CPASS_MTX_21 (KEY_CPASS_MTX_20 + 1)
#define KEY_CPASS_MTX_22 (KEY_CPASS_MTX_21 + 1)
/* Gesture Keys */
#define KEY_DMP_TAPW_MIN (KEY_CPASS_MTX_22 + 1)
#define KEY_DMP_TAP_THR_X (KEY_DMP_TAPW_MIN + 1)
#define KEY_DMP_TAP_THR_Y (KEY_DMP_TAP_THR_X + 1)
#define KEY_DMP_TAP_THR_Z (KEY_DMP_TAP_THR_Y + 1)
#define KEY_DMP_SH_TH_Y (KEY_DMP_TAP_THR_Z + 1)
#define KEY_DMP_SH_TH_X (KEY_DMP_SH_TH_Y + 1)
#define KEY_DMP_SH_TH_Z (KEY_DMP_SH_TH_X + 1)
#define KEY_DMP_ORIENT (KEY_DMP_SH_TH_Z + 1)
#define KEY_D_ACT0 (KEY_DMP_ORIENT + 1)
#define KEY_D_ACSX (KEY_D_ACT0 + 1)
#define KEY_D_ACSY (KEY_D_ACSX + 1)
#define KEY_D_ACSZ (KEY_D_ACSY + 1)
#define KEY_X_GRT_Y_TMP (KEY_D_ACSZ + 1)
#define KEY_SKIP_X_GRT_Y_TMP (KEY_X_GRT_Y_TMP + 1)
#define KEY_SKIP_END_COMPARE (KEY_SKIP_X_GRT_Y_TMP + 1)
#define KEY_END_COMPARE_Y_X_TMP2 (KEY_SKIP_END_COMPARE + 1)
#define KEY_CFG_ANDROID_ORIENT_INT (KEY_END_COMPARE_Y_X_TMP2 + 1)
#define KEY_NO_ORIENT_INTERRUPT (KEY_CFG_ANDROID_ORIENT_INT + 1)
#define KEY_END_COMPARE_Y_X_TMP (KEY_NO_ORIENT_INTERRUPT + 1)
#define KEY_END_ORIENT_1 (KEY_END_COMPARE_Y_X_TMP + 1)
#define KEY_END_COMPARE_Y_X (KEY_END_ORIENT_1 + 1)
#define KEY_END_ORIENT (KEY_END_COMPARE_Y_X + 1)
#define KEY_X_GRT_Y (KEY_END_ORIENT + 1)
#define KEY_NOT_TIME_MINUS_1 (KEY_X_GRT_Y + 1)
#define KEY_END_COMPARE_Y_X_TMP3 (KEY_NOT_TIME_MINUS_1 + 1)
#define KEY_X_GRT_Y_TMP2 (KEY_END_COMPARE_Y_X_TMP3 + 1)
/* Authenticate Keys */
#define KEY_D_AUTH_OUT (KEY_X_GRT_Y_TMP2 + 1)
#define KEY_D_AUTH_IN (KEY_D_AUTH_OUT + 1)
#define KEY_D_AUTH_A (KEY_D_AUTH_IN + 1)
#define KEY_D_AUTH_B (KEY_D_AUTH_A + 1)
/* Pedometer standalone only keys */
#define KEY_D_PEDSTD_BP_B (KEY_D_AUTH_B + 1)
#define KEY_D_PEDSTD_HP_A (KEY_D_PEDSTD_BP_B + 1)
#define KEY_D_PEDSTD_HP_B (KEY_D_PEDSTD_HP_A + 1)
#define KEY_D_PEDSTD_BP_A4 (KEY_D_PEDSTD_HP_B + 1)
#define KEY_D_PEDSTD_BP_A3 (KEY_D_PEDSTD_BP_A4 + 1)
#define KEY_D_PEDSTD_BP_A2 (KEY_D_PEDSTD_BP_A3 + 1)
#define KEY_D_PEDSTD_BP_A1 (KEY_D_PEDSTD_BP_A2 + 1)
#define KEY_D_PEDSTD_INT_THRSH (KEY_D_PEDSTD_BP_A1 + 1)
#define KEY_D_PEDSTD_CLIP (KEY_D_PEDSTD_INT_THRSH + 1)
#define KEY_D_PEDSTD_SB (KEY_D_PEDSTD_CLIP + 1)
#define KEY_D_PEDSTD_SB_TIME (KEY_D_PEDSTD_SB + 1)
#define KEY_D_PEDSTD_PEAKTHRSH (KEY_D_PEDSTD_SB_TIME + 1)
#define KEY_D_PEDSTD_TIML (KEY_D_PEDSTD_PEAKTHRSH + 1)
#define KEY_D_PEDSTD_TIMH (KEY_D_PEDSTD_TIML + 1)
#define KEY_D_PEDSTD_PEAK (KEY_D_PEDSTD_TIMH + 1)
#define KEY_D_PEDSTD_TIMECTR (KEY_D_PEDSTD_PEAK + 1)
#define KEY_D_PEDSTD_STEPCTR (KEY_D_PEDSTD_TIMECTR + 1)
#define KEY_D_PEDSTD_WALKTIME (KEY_D_PEDSTD_STEPCTR + 1)
#define KEY_D_PEDSTD_DECI (KEY_D_PEDSTD_WALKTIME + 1)
/*Host Based No Motion*/
#define KEY_D_HOST_NO_MOT (KEY_D_PEDSTD_DECI + 1)
/* EIS keys */
#define KEY_P_EIS_FIFO_FOOTER (KEY_D_HOST_NO_MOT + 1)
#define KEY_P_EIS_FIFO_YSHIFT (KEY_P_EIS_FIFO_FOOTER + 1)
#define KEY_P_EIS_DATA_RATE (KEY_P_EIS_FIFO_YSHIFT + 1)
#define KEY_P_EIS_FIFO_XSHIFT (KEY_P_EIS_DATA_RATE + 1)
#define KEY_P_EIS_FIFO_SYNC (KEY_P_EIS_FIFO_XSHIFT + 1)
#define KEY_P_EIS_FIFO_ZSHIFT (KEY_P_EIS_FIFO_SYNC + 1)
#define KEY_P_EIS_FIFO_READY (KEY_P_EIS_FIFO_ZSHIFT + 1)
#define KEY_DMP_FOOTER (KEY_P_EIS_FIFO_READY + 1)
#define KEY_DMP_INTX_HC (KEY_DMP_FOOTER + 1)
#define KEY_DMP_INTX_PH (KEY_DMP_INTX_HC + 1)
#define KEY_DMP_INTX_SH (KEY_DMP_INTX_PH + 1)
#define KEY_DMP_AINV_SH (KEY_DMP_INTX_SH + 1)
#define KEY_DMP_A_INV_XH (KEY_DMP_AINV_SH + 1)
#define KEY_DMP_AINV_PH (KEY_DMP_A_INV_XH + 1)
#define KEY_DMP_CTHX_H (KEY_DMP_AINV_PH + 1)
#define KEY_DMP_CTHY_H (KEY_DMP_CTHX_H + 1)
#define KEY_DMP_CTHZ_H (KEY_DMP_CTHY_H + 1)
#define KEY_DMP_NCTHX_H (KEY_DMP_CTHZ_H + 1)
#define KEY_DMP_NCTHY_H (KEY_DMP_NCTHX_H + 1)
#define KEY_DMP_NCTHZ_H (KEY_DMP_NCTHY_H + 1)
#define KEY_DMP_CTSQ_XH (KEY_DMP_NCTHZ_H + 1)
#define KEY_DMP_CTSQ_YH (KEY_DMP_CTSQ_XH + 1)
#define KEY_DMP_CTSQ_ZH (KEY_DMP_CTSQ_YH + 1)
#define KEY_DMP_INTX_H (KEY_DMP_CTSQ_ZH + 1)
#define KEY_DMP_INTY_H (KEY_DMP_INTX_H + 1)
#define KEY_DMP_INTZ_H (KEY_DMP_INTY_H + 1)
// #define KEY_DMP_HPX_H (KEY_DMP_INTZ_H + 1)
// #define KEY_DMP_HPY_H (KEY_DMP_HPX_H + 1)
// #define KEY_DMP_HPZ_H (KEY_DMP_HPY_H + 1)
/* Stream keys */
#define KEY_STREAM_P_GYRO_Z (KEY_DMP_INTZ_H + 1)
#define KEY_STREAM_P_GYRO_Y (KEY_STREAM_P_GYRO_Z + 1)
#define KEY_STREAM_P_GYRO_X (KEY_STREAM_P_GYRO_Y + 1)
#define KEY_STREAM_P_TEMP (KEY_STREAM_P_GYRO_X + 1)
#define KEY_STREAM_P_AUX_Y (KEY_STREAM_P_TEMP + 1)
#define KEY_STREAM_P_AUX_X (KEY_STREAM_P_AUX_Y + 1)
#define KEY_STREAM_P_AUX_Z (KEY_STREAM_P_AUX_X + 1)
#define KEY_STREAM_P_ACCEL_Y (KEY_STREAM_P_AUX_Z + 1)
#define KEY_STREAM_P_ACCEL_X (KEY_STREAM_P_ACCEL_Y + 1)
#define KEY_STREAM_P_FOOTER (KEY_STREAM_P_ACCEL_X + 1)
#define KEY_STREAM_P_ACCEL_Z (KEY_STREAM_P_FOOTER + 1)
#define NUM_KEYS (KEY_STREAM_P_ACCEL_Z + 1)
typedef struct {
unsigned short key;
unsigned short addr;
} tKeyLabel;
#define DINA0A 0x0a
#define DINA22 0x22
#define DINA42 0x42
#define DINA5A 0x5a
#define DINA06 0x06
#define DINA0E 0x0e
#define DINA16 0x16
#define DINA1E 0x1e
#define DINA26 0x26
#define DINA2E 0x2e
#define DINA36 0x36
#define DINA3E 0x3e
#define DINA46 0x46
#define DINA4E 0x4e
#define DINA56 0x56
#define DINA5E 0x5e
#define DINA66 0x66
#define DINA6E 0x6e
#define DINA76 0x76
#define DINA7E 0x7e
#define DINA00 0x00
#define DINA08 0x08
#define DINA10 0x10
#define DINA18 0x18
#define DINA20 0x20
#define DINA28 0x28
#define DINA30 0x30
#define DINA38 0x38
#define DINA40 0x40
#define DINA48 0x48
#define DINA50 0x50
#define DINA58 0x58
#define DINA60 0x60
#define DINA68 0x68
#define DINA70 0x70
#define DINA78 0x78
#define DINA04 0x04
#define DINA0C 0x0c
#define DINA14 0x14
#define DINA1C 0x1C
#define DINA24 0x24
#define DINA2C 0x2c
#define DINA34 0x34
#define DINA3C 0x3c
#define DINA44 0x44
#define DINA4C 0x4c
#define DINA54 0x54
#define DINA5C 0x5c
#define DINA64 0x64
#define DINA6C 0x6c
#define DINA74 0x74
#define DINA7C 0x7c
#define DINA01 0x01
#define DINA09 0x09
#define DINA11 0x11
#define DINA19 0x19
#define DINA21 0x21
#define DINA29 0x29
#define DINA31 0x31
#define DINA39 0x39
#define DINA41 0x41
#define DINA49 0x49
#define DINA51 0x51
#define DINA59 0x59
#define DINA61 0x61
#define DINA69 0x69
#define DINA71 0x71
#define DINA79 0x79
#define DINA25 0x25
#define DINA2D 0x2d
#define DINA35 0x35
#define DINA3D 0x3d
#define DINA4D 0x4d
#define DINA55 0x55
#define DINA5D 0x5D
#define DINA6D 0x6d
#define DINA75 0x75
#define DINA7D 0x7d
#define DINADC 0xdc
#define DINAF2 0xf2
#define DINAAB 0xab
#define DINAAA 0xaa
#define DINAF1 0xf1
#define DINADF 0xdf
#define DINADA 0xda
#define DINAB1 0xb1
#define DINAB9 0xb9
#define DINAF3 0xf3
#define DINA8B 0x8b
#define DINAA3 0xa3
#define DINA91 0x91
#define DINAB6 0xb6
#define DINAB4 0xb4
#define DINC00 0x00
#define DINC01 0x01
#define DINC02 0x02
#define DINC03 0x03
#define DINC08 0x08
#define DINC09 0x09
#define DINC0A 0x0a
#define DINC0B 0x0b
#define DINC10 0x10
#define DINC11 0x11
#define DINC12 0x12
#define DINC13 0x13
#define DINC18 0x18
#define DINC19 0x19
#define DINC1A 0x1a
#define DINC1B 0x1b
#define DINC20 0x20
#define DINC21 0x21
#define DINC22 0x22
#define DINC23 0x23
#define DINC28 0x28
#define DINC29 0x29
#define DINC2A 0x2a
#define DINC2B 0x2b
#define DINC30 0x30
#define DINC31 0x31
#define DINC32 0x32
#define DINC33 0x33
#define DINC38 0x38
#define DINC39 0x39
#define DINC3A 0x3a
#define DINC3B 0x3b
#define DINC40 0x40
#define DINC41 0x41
#define DINC42 0x42
#define DINC43 0x43
#define DINC48 0x48
#define DINC49 0x49
#define DINC4A 0x4a
#define DINC4B 0x4b
#define DINC50 0x50
#define DINC51 0x51
#define DINC52 0x52
#define DINC53 0x53
#define DINC58 0x58
#define DINC59 0x59
#define DINC5A 0x5a
#define DINC5B 0x5b
#define DINC60 0x60
#define DINC61 0x61
#define DINC62 0x62
#define DINC63 0x63
#define DINC68 0x68
#define DINC69 0x69
#define DINC6A 0x6a
#define DINC6B 0x6b
#define DINC70 0x70
#define DINC71 0x71
#define DINC72 0x72
#define DINC73 0x73
#define DINC78 0x78
#define DINC79 0x79
#define DINC7A 0x7a
#define DINC7B 0x7b
#define DIND40 0x40
#define DINA80 0x80
#define DINA90 0x90
#define DINAA0 0xa0
#define DINAC9 0xc9
#define DINACB 0xcb
#define DINACD 0xcd
#define DINACF 0xcf
#define DINAC8 0xc8
#define DINACA 0xca
#define DINACC 0xcc
#define DINACE 0xce
#define DINAD8 0xd8
#define DINADD 0xdd
#define DINAF8 0xf0
#define DINAFE 0xfe
#define DINBF8 0xf8
#define DINAC0 0xb0
#define DINAC1 0xb1
#define DINAC2 0xb4
#define DINAC3 0xb5
#define DINAC4 0xb8
#define DINAC5 0xb9
#define DINBC0 0xc0
#define DINBC2 0xc2
#define DINBC4 0xc4
#define DINBC6 0xc6
#endif // DMPKEY_H__

View File

@@ -1,293 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/*
$License:
Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
$
*/
#ifndef DMPMAP_H
#define DMPMAP_H
#ifdef __cplusplus
extern "C"
{
#endif
#define DMP_PTAT 0
#define DMP_XGYR 2
#define DMP_YGYR 4
#define DMP_ZGYR 6
#define DMP_XACC 8
#define DMP_YACC 10
#define DMP_ZACC 12
#define DMP_ADC1 14
#define DMP_ADC2 16
#define DMP_ADC3 18
#define DMP_BIASUNC 20
#define DMP_FIFORT 22
#define DMP_INVGSFH 24
#define DMP_INVGSFL 26
#define DMP_1H 28
#define DMP_1L 30
#define DMP_BLPFSTCH 32
#define DMP_BLPFSTCL 34
#define DMP_BLPFSXH 36
#define DMP_BLPFSXL 38
#define DMP_BLPFSYH 40
#define DMP_BLPFSYL 42
#define DMP_BLPFSZH 44
#define DMP_BLPFSZL 46
#define DMP_BLPFMTC 48
#define DMP_SMC 50
#define DMP_BLPFMXH 52
#define DMP_BLPFMXL 54
#define DMP_BLPFMYH 56
#define DMP_BLPFMYL 58
#define DMP_BLPFMZH 60
#define DMP_BLPFMZL 62
#define DMP_BLPFC 64
#define DMP_SMCTH 66
#define DMP_0H2 68
#define DMP_0L2 70
#define DMP_BERR2H 72
#define DMP_BERR2L 74
#define DMP_BERR2NH 76
#define DMP_SMCINC 78
#define DMP_ANGVBXH 80
#define DMP_ANGVBXL 82
#define DMP_ANGVBYH 84
#define DMP_ANGVBYL 86
#define DMP_ANGVBZH 88
#define DMP_ANGVBZL 90
#define DMP_BERR1H 92
#define DMP_BERR1L 94
#define DMP_ATCH 96
#define DMP_BIASUNCSF 98
#define DMP_ACT2H 100
#define DMP_ACT2L 102
#define DMP_GSFH 104
#define DMP_GSFL 106
#define DMP_GH 108
#define DMP_GL 110
#define DMP_0_5H 112
#define DMP_0_5L 114
#define DMP_0_0H 116
#define DMP_0_0L 118
#define DMP_1_0H 120
#define DMP_1_0L 122
#define DMP_1_5H 124
#define DMP_1_5L 126
#define DMP_TMP1AH 128
#define DMP_TMP1AL 130
#define DMP_TMP2AH 132
#define DMP_TMP2AL 134
#define DMP_TMP3AH 136
#define DMP_TMP3AL 138
#define DMP_TMP4AH 140
#define DMP_TMP4AL 142
#define DMP_XACCW 144
#define DMP_TMP5 146
#define DMP_XACCB 148
#define DMP_TMP8 150
#define DMP_YACCB 152
#define DMP_TMP9 154
#define DMP_ZACCB 156
#define DMP_TMP10 158
#define DMP_DZH 160
#define DMP_DZL 162
#define DMP_XGCH 164
#define DMP_XGCL 166
#define DMP_YGCH 168
#define DMP_YGCL 170
#define DMP_ZGCH 172
#define DMP_ZGCL 174
#define DMP_YACCW 176
#define DMP_TMP7 178
#define DMP_AFB1H 180
#define DMP_AFB1L 182
#define DMP_AFB2H 184
#define DMP_AFB2L 186
#define DMP_MAGFBH 188
#define DMP_MAGFBL 190
#define DMP_QT1H 192
#define DMP_QT1L 194
#define DMP_QT2H 196
#define DMP_QT2L 198
#define DMP_QT3H 200
#define DMP_QT3L 202
#define DMP_QT4H 204
#define DMP_QT4L 206
#define DMP_CTRL1H 208
#define DMP_CTRL1L 210
#define DMP_CTRL2H 212
#define DMP_CTRL2L 214
#define DMP_CTRL3H 216
#define DMP_CTRL3L 218
#define DMP_CTRL4H 220
#define DMP_CTRL4L 222
#define DMP_CTRLS1 224
#define DMP_CTRLSF1 226
#define DMP_CTRLS2 228
#define DMP_CTRLSF2 230
#define DMP_CTRLS3 232
#define DMP_CTRLSFNLL 234
#define DMP_CTRLS4 236
#define DMP_CTRLSFNL2 238
#define DMP_CTRLSFNL 240
#define DMP_TMP30 242
#define DMP_CTRLSFJT 244
#define DMP_TMP31 246
#define DMP_TMP11 248
#define DMP_CTRLSF2_2 250
#define DMP_TMP12 252
#define DMP_CTRLSF1_2 254
#define DMP_PREVPTAT 256
#define DMP_ACCZB 258
#define DMP_ACCXB 264
#define DMP_ACCYB 266
#define DMP_1HB 272
#define DMP_1LB 274
#define DMP_0H 276
#define DMP_0L 278
#define DMP_ASR22H 280
#define DMP_ASR22L 282
#define DMP_ASR6H 284
#define DMP_ASR6L 286
#define DMP_TMP13 288
#define DMP_TMP14 290
#define DMP_FINTXH 292
#define DMP_FINTXL 294
#define DMP_FINTYH 296
#define DMP_FINTYL 298
#define DMP_FINTZH 300
#define DMP_FINTZL 302
#define DMP_TMP1BH 304
#define DMP_TMP1BL 306
#define DMP_TMP2BH 308
#define DMP_TMP2BL 310
#define DMP_TMP3BH 312
#define DMP_TMP3BL 314
#define DMP_TMP4BH 316
#define DMP_TMP4BL 318
#define DMP_STXG 320
#define DMP_ZCTXG 322
#define DMP_STYG 324
#define DMP_ZCTYG 326
#define DMP_STZG 328
#define DMP_ZCTZG 330
#define DMP_CTRLSFJT2 332
#define DMP_CTRLSFJTCNT 334
#define DMP_PVXG 336
#define DMP_TMP15 338
#define DMP_PVYG 340
#define DMP_TMP16 342
#define DMP_PVZG 344
#define DMP_TMP17 346
#define DMP_MNMFLAGH 352
#define DMP_MNMFLAGL 354
#define DMP_MNMTMH 356
#define DMP_MNMTML 358
#define DMP_MNMTMTHRH 360
#define DMP_MNMTMTHRL 362
#define DMP_MNMTHRH 364
#define DMP_MNMTHRL 366
#define DMP_ACCQD4H 368
#define DMP_ACCQD4L 370
#define DMP_ACCQD5H 372
#define DMP_ACCQD5L 374
#define DMP_ACCQD6H 376
#define DMP_ACCQD6L 378
#define DMP_ACCQD7H 380
#define DMP_ACCQD7L 382
#define DMP_ACCQD0H 384
#define DMP_ACCQD0L 386
#define DMP_ACCQD1H 388
#define DMP_ACCQD1L 390
#define DMP_ACCQD2H 392
#define DMP_ACCQD2L 394
#define DMP_ACCQD3H 396
#define DMP_ACCQD3L 398
#define DMP_XN2H 400
#define DMP_XN2L 402
#define DMP_XN1H 404
#define DMP_XN1L 406
#define DMP_YN2H 408
#define DMP_YN2L 410
#define DMP_YN1H 412
#define DMP_YN1L 414
#define DMP_YH 416
#define DMP_YL 418
#define DMP_B0H 420
#define DMP_B0L 422
#define DMP_A1H 424
#define DMP_A1L 426
#define DMP_A2H 428
#define DMP_A2L 430
#define DMP_SEM1 432
#define DMP_FIFOCNT 434
#define DMP_SH_TH_X 436
#define DMP_PACKET 438
#define DMP_SH_TH_Y 440
#define DMP_FOOTER 442
#define DMP_SH_TH_Z 444
#define DMP_TEMP29 448
#define DMP_TEMP30 450
#define DMP_XACCB_PRE 452
#define DMP_XACCB_PREL 454
#define DMP_YACCB_PRE 456
#define DMP_YACCB_PREL 458
#define DMP_ZACCB_PRE 460
#define DMP_ZACCB_PREL 462
#define DMP_TMP22 464
#define DMP_TAP_TIMER 466
#define DMP_TAP_THX 468
#define DMP_TAP_THY 472
#define DMP_TAP_THZ 476
#define DMP_TAPW_MIN 478
#define DMP_TMP25 480
#define DMP_TMP26 482
#define DMP_TMP27 484
#define DMP_TMP28 486
#define DMP_ORIENT 488
#define DMP_THRSH 490
#define DMP_ENDIANH 492
#define DMP_ENDIANL 494
#define DMP_BLPFNMTCH 496
#define DMP_BLPFNMTCL 498
#define DMP_BLPFNMXH 500
#define DMP_BLPFNMXL 502
#define DMP_BLPFNMYH 504
#define DMP_BLPFNMYL 506
#define DMP_BLPFNMZH 508
#define DMP_BLPFNMZL 510
#ifdef __cplusplus
}
#endif
#endif // DMPMAP_H

View File

@@ -1,161 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/*
$License:
Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
See included License.txt for License information.
$
*/
/**
* @addtogroup DRIVERS Sensor Driver Layer
* @brief Hardware drivers to communicate with sensors via I2C.
*
* @{
* @file inv_mpu.h
* @brief An I2C-based driver for Invensense gyroscopes.
* @details This driver currently works for the following devices:
* MPU6050
* MPU6500
* MPU9150 (or MPU6050 w/ AK8975 on the auxiliary bus)
* MPU9250 (or MPU6500 w/ AK8963 on the auxiliary bus)
*/
#ifndef _INV_MPU_H_
#define _INV_MPU_H_
#define INV_X_GYRO (0x40)
#define INV_Y_GYRO (0x20)
#define INV_Z_GYRO (0x10)
#define INV_XYZ_GYRO (INV_X_GYRO | INV_Y_GYRO | INV_Z_GYRO)
#define INV_XYZ_ACCEL (0x08)
#define INV_XYZ_COMPASS (0x01)
struct int_param_s {
#if defined EMPL_TARGET_MSP430 || defined MOTION_DRIVER_TARGET_MSP430
void (*cb)(void);
unsigned short pin;
unsigned char lp_exit;
unsigned char active_low;
#elif defined EMPL_TARGET_UC3L0
unsigned long pin;
void (*cb)(volatile void *);
void *arg;
#endif
};
#define MPU_INT_STATUS_DATA_READY (0x0001)
#define MPU_INT_STATUS_DMP (0x0002)
#define MPU_INT_STATUS_PLL_READY (0x0004)
#define MPU_INT_STATUS_I2C_MST (0x0008)
#define MPU_INT_STATUS_FIFO_OVERFLOW (0x0010)
#define MPU_INT_STATUS_ZMOT (0x0020)
#define MPU_INT_STATUS_MOT (0x0040)
#define MPU_INT_STATUS_FREE_FALL (0x0080)
#define MPU_INT_STATUS_DMP_0 (0x0100)
#define MPU_INT_STATUS_DMP_1 (0x0200)
#define MPU_INT_STATUS_DMP_2 (0x0400)
#define MPU_INT_STATUS_DMP_3 (0x0800)
#define MPU_INT_STATUS_DMP_4 (0x1000)
#define MPU_INT_STATUS_DMP_5 (0x2000)
/* Set up APIs */
// int mpu_init(struct int_param_s *int_param);
int mpu_init();// struct int_param_s *int_param);
int mpu_init_slave(void);
int mpu_set_bypass(unsigned char bypass_on);
/* Configuration APIs */
int mpu_lp_accel_mode(unsigned short rate);
int mpu_lp_motion_interrupt(unsigned short thresh, unsigned char time,
unsigned char lpa_freq);
int mpu_set_int_level(unsigned char active_low);
int mpu_set_int_latched(unsigned char enable);
int mpu_set_dmp_state(unsigned char enable);
int mpu_get_dmp_state(unsigned char *enabled);
int mpu_get_lpf(unsigned short *lpf);
int mpu_set_lpf(unsigned short lpf);
int mpu_get_gyro_fsr(unsigned short *fsr);
int mpu_set_gyro_fsr(unsigned short fsr);
int mpu_get_accel_fsr(unsigned char *fsr);
int mpu_set_accel_fsr(unsigned char fsr);
int mpu_get_compass_fsr(unsigned short *fsr);
int mpu_get_gyro_sens(float *sens);
int mpu_get_accel_sens(unsigned short *sens);
int mpu_get_sample_rate(unsigned short *rate);
int mpu_set_sample_rate(unsigned short rate);
int mpu_get_compass_sample_rate(unsigned short *rate);
int mpu_set_compass_sample_rate(unsigned short rate);
int mpu_get_fifo_config(unsigned char *sensors);
int mpu_configure_fifo(unsigned char sensors);
int mpu_get_power_state(unsigned char *power_on);
int mpu_set_sensors(unsigned char sensors);
int mpu_read_6500_accel_bias(long *accel_bias);
int mpu_set_gyro_bias_reg(long *gyro_bias);
int mpu_set_accel_bias_6500_reg(const long *accel_bias);
int mpu_read_6050_accel_bias(long *accel_bias);
int mpu_set_accel_bias_6050_reg(const long *accel_bias);
/* Data getter/setter APIs */
int mpu_get_gyro_reg(short *data, unsigned long *timestamp);
int mpu_get_accel_reg(short *data, unsigned long *timestamp);
int mpu_get_compass_reg(short *data, unsigned long *timestamp);
int mpu_get_temperature(long *data, unsigned long *timestamp);
int mpu_get_int_status(short *status);
int mpu_read_fifo(short *gyro, short *accel, unsigned long *timestamp,
unsigned char *sensors, unsigned char *more);
int mpu_read_fifo_stream(unsigned short length, unsigned char *data,
unsigned char *more);
int mpu_reset_fifo(void);
int mpu_write_mem(unsigned short mem_addr, unsigned short length,
unsigned char *data);
int mpu_read_mem(unsigned short mem_addr, unsigned short length,
unsigned char *data);
int mpu_load_firmware(unsigned short length, const unsigned char *firmware,
unsigned short start_addr, unsigned short sample_rate);
int mpu_reg_dump(void);
int mpu_read_reg(unsigned char reg, unsigned char *data);
int mpu_run_self_test(long *gyro, long *accel);
int mpu_run_6500_self_test(long *gyro, long *accel, unsigned char debug);
int mpu_register_tap_cb(void (*func)(unsigned char, unsigned char));
#endif /* #ifndef _INV_MPU_H_ */

View File

@@ -1,126 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/*
$License:
Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
See included License.txt for License information.
$
*/
/**
* @addtogroup DRIVERS Sensor Driver Layer
* @brief Hardware drivers to communicate with sensors via I2C.
*
* @{
* @file inv_mpu_dmp_motion_driver.h
* @brief DMP image and interface functions.
* @details All functions are preceded by the dmp_ prefix to
* differentiate among MPL and general driver function calls.
*/
#ifndef _INV_MPU_DMP_MOTION_DRIVER_H_
#define _INV_MPU_DMP_MOTION_DRIVER_H_
#define TAP_X (0x01)
#define TAP_Y (0x02)
#define TAP_Z (0x04)
#define TAP_XYZ (0x07)
#define TAP_X_UP (0x01)
#define TAP_X_DOWN (0x02)
#define TAP_Y_UP (0x03)
#define TAP_Y_DOWN (0x04)
#define TAP_Z_UP (0x05)
#define TAP_Z_DOWN (0x06)
#define ANDROID_ORIENT_PORTRAIT (0x00)
#define ANDROID_ORIENT_LANDSCAPE (0x01)
#define ANDROID_ORIENT_REVERSE_PORTRAIT (0x02)
#define ANDROID_ORIENT_REVERSE_LANDSCAPE (0x03)
#define DMP_INT_GESTURE (0x01)
#define DMP_INT_CONTINUOUS (0x02)
#define DMP_FEATURE_TAP (0x001)
#define DMP_FEATURE_ANDROID_ORIENT (0x002)
#define DMP_FEATURE_LP_QUAT (0x004)
#define DMP_FEATURE_PEDOMETER (0x008)
#define DMP_FEATURE_6X_LP_QUAT (0x010)
#define DMP_FEATURE_GYRO_CAL (0x020)
#define DMP_FEATURE_SEND_RAW_ACCEL (0x040)
#define DMP_FEATURE_SEND_RAW_GYRO (0x080)
#define DMP_FEATURE_SEND_CAL_GYRO (0x100)
#define INV_WXYZ_QUAT (0x100)
/* Set up functions. */
int dmp_load_motion_driver_firmware(void);
int dmp_set_fifo_rate(unsigned short rate);
int dmp_get_fifo_rate(unsigned short *rate);
int dmp_enable_feature(unsigned short mask);
int dmp_get_enabled_features(unsigned short *mask);
int dmp_set_interrupt_mode(unsigned char mode);
int dmp_set_orientation(unsigned short orient);
int dmp_set_gyro_bias(long *bias);
int dmp_set_accel_bias(long *bias);
/* Tap functions. */
int dmp_register_tap_cb(void (*func)(unsigned char, unsigned char));
int dmp_set_tap_thresh(unsigned char axis, unsigned short thresh);
int dmp_set_tap_axes(unsigned char axis);
int dmp_set_tap_count(unsigned char min_taps);
int dmp_set_tap_time(unsigned short time);
int dmp_set_tap_time_multi(unsigned short time);
int dmp_set_shake_reject_thresh(long sf, unsigned short thresh);
int dmp_set_shake_reject_time(unsigned short time);
int dmp_set_shake_reject_timeout(unsigned short time);
/* Android orientation functions. */
int dmp_register_android_orient_cb(void (*func)(unsigned char));
/* LP quaternion functions. */
int dmp_enable_lp_quat(unsigned char enable);
int dmp_enable_6x_lp_quat(unsigned char enable);
/* Pedometer functions. */
int dmp_get_pedometer_step_count(unsigned long *count);
int dmp_set_pedometer_step_count(unsigned long count);
int dmp_get_pedometer_walk_time(unsigned long *time);
int dmp_set_pedometer_walk_time(unsigned long time);
/* DMP gyro calibration functions. */
int dmp_enable_gyro_cal(unsigned char enable);
/* Read function. This function should be called whenever the MPU interrupt is
* detected.
*/
int dmp_read_fifo(short *gyro, short *accel, long *quat,
unsigned long *timestamp, short *sensors, unsigned char *more);
#endif /* #ifndef _INV_MPU_DMP_MOTION_DRIVER_H_ */

View File

@@ -1,473 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#include "arc/arc.h"
#include "arc/arc_builtin.h"
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "embARC_debug.h"
#include "device/ip_hal/dev_iic.h"
#include "mpu9250.h"
#include "board.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
#include <math.h>
#define DEFAULT_MPU_HZ 200
// ****************************************
#define SMPLRT_DIV 0x19
#define CONFIG 0x1A
#define GYRO_CONFIG 0x1B
#define ACCEL_CONFIG 0x1C
#define ACCEL_CONFIG_2 0x1D
#define INT_PIN_CFG 0x37
#define INT_ENABLE 0x38
#define USER_CTRL 0x6A
#define PWR_MGMT_1 0x6B
#define PWR_MGMT_2 0x6C
#define MAG_CTRL 0x0A
#define MPU_WIM 0x75
#define MPU_ID 0x71
#define MAG_WIM 0x00
#define MAG_ID 0x48
#define ACCEL_XOUT_H 0x3B
#define GYRO_XOUT_H 0x43
#define MAG_XOUT_L 0x03
#ifdef MPU9250_USE_DMP
MPU9250_DEF_PTR mpu9250_ptr;
static signed char gyro_orientation[9] = { 1, 0, 0,
0, 1, 0,
0, 0, 1 };
static inline unsigned short inv_row_2_scale(const signed char *row)
{
unsigned short b;
if (row[0] > 0) {
b = 0;
} else if (row[0] < 0) {
b = 4;
} else if (row[1] > 0) {
b = 1;
} else if (row[1] < 0) {
b = 5;
} else if (row[2] > 0) {
b = 2;
} else if (row[2] < 0) {
b = 6;
} else {
b = 7; // error
}
return b;
}
static inline unsigned short inv_orientation_matrix_to_scalar(const signed char *mtx)
{
unsigned short scalar;
/*
XYZ 010_001_000 Identity Matrix
XZY 001_010_000
YXZ 010_000_001
YZX 000_010_001
ZXY 001_000_010
ZYX 000_001_010
*/
scalar = inv_row_2_scale(mtx);
scalar |= inv_row_2_scale(mtx + 3) << 3;
scalar |= inv_row_2_scale(mtx + 6) << 6;
return scalar;
}
static inline void run_self_test(void)
{
int result;
long gyro[3], accel[3];
unsigned char i = 0;
result = mpu_run_6500_self_test(gyro, accel, 1);
EMBARC_PRINTF("mpu run self test, result = %d\r\n");
if (result == 0x7) {
for (i = 0; i < 3; i++) {
gyro[i] = (long)(gyro[i] * 32.8f); // convert to +-1000dps
accel[i] *= 2048.f; // convert to +-16G
accel[i] = accel[i] >> 16;
gyro[i] = (long)(gyro[i] >> 16);
}
mpu_set_gyro_bias_reg(gyro);
mpu_set_accel_bias_6500_reg(accel);
}
}
#endif
#define MPU9250_CHECK_EXP_NORTN(EXPR) CHECK_EXP_NOERCD(EXPR, error_exit)
static int32_t _mpu_reg_write(MPU9250_DEF_PTR obj, uint32_t slaveaddr, uint8_t regaddr, uint8_t *val, uint8_t len)
{
int32_t ercd = E_PAR;
uint8_t data[1];
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_LESS_INFO, "[%s]%d: obj 0x%x, regaddr 0x%x, val 0x%x\r\n", __FUNCTION__, __LINE__, obj, regaddr, *val);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
data[0] = (uint8_t)(regaddr & 0xff);
iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slaveaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_write(val, len);
error_exit:
return ercd;
}
static int32_t _mpu_reg_read(MPU9250_DEF_PTR obj, uint32_t slaveaddr, uint8_t regaddr, uint8_t *val, uint8_t len)
{
int32_t ercd = E_PAR;
uint8_t data[1];
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
data[0] = (uint8_t)(regaddr & 0xff);
iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slaveaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_read(val, len);
error_exit:
return ercd;
}
int32_t mpu9250_sensor_init(MPU9250_DEF_PTR obj)
{
int32_t ercd = E_OK;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
ercd = iic_obj->iic_open(DEV_MASTER_MODE, IIC_SPEED_STANDARD);
if ((ercd == E_OK) || (ercd == E_OPNED)) {
#ifndef MPU9250_USE_DMP
uint8_t config;
uint8_t data[0];
config = 0x80;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, PWR_MGMT_1, &config, 1);// 0x6B
board_delay_ms(100);
/*
* get stable time source; Auto select clock source to be PLL gyroscope reference if ready
* else use the internal oscillator
*/
config = 0x01;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, PWR_MGMT_1, &config, 1);
config = 0x00;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, PWR_MGMT_2, &config, 1);
/* no i2c master */
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, USER_CTRL, &config, 1);
board_delay_ms(200);
ercd = _mpu_reg_read(obj, obj->mpu_slvaddr, MPU_WIM, data, 1);
if (data[0] != MPU_ID) {
dbg_printf(DBG_MORE_INFO, "mpu init failed\r\n");
return E_SYS;
}
config = 0x07; // SAMPLE_RATE=Internal_Sample_Rate(1khz) / (1 + SMPLRT_DIV)
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, SMPLRT_DIV, &config, 1); // Sample Rate Divider
config = 0x06;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, CONFIG, &config, 1);// DLPF config: 5Hz
config = 0x18;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, GYRO_CONFIG, &config, 1);// +2000dps
config = 0x00;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, ACCEL_CONFIG, &config, 1);// +-2g
config = 0x08;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, ACCEL_CONFIG_2, &config, 1); // 1.13kHz
config = 0x2; // set passby
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, INT_PIN_CFG, &config, 1);
board_delay_ms(100);
ercd = _mpu_reg_read(obj, obj->mag_slvaddr, MAG_WIM, data, 1);// read mag who i am;
if (data[0] != MAG_ID) {
dbg_printf(DBG_MORE_INFO, "mpu init failed\r\n");
return E_SYS;
}
config = 0x01;
ercd = _mpu_reg_write(obj, obj->mag_slvaddr, MAG_CTRL, &config, 1);// mag single measurement mode
#else
mpu9250_ptr = obj;
if (!mpu_init()) {
if (!mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL)) {
EMBARC_PRINTF("mpu_set_sensor complete ......\r\n");
}
mpu_delay_ms(50);
if (!mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL)) {
EMBARC_PRINTF("mpu_configure_fifo complete ......\r\n");
}
mpu_delay_ms(50);
if (!mpu_set_sample_rate(DEFAULT_MPU_HZ)) {
EMBARC_PRINTF("mpu_set_sample_rate complete ......\r\n");
}
mpu_delay_ms(50);
// if(!mpu_set_gyro_bias_reg(gyroZero))
// EMBARC_PRINTF("mpu_set_gyro_bias_reg complete ......\r\n");
mpu_delay_ms(50);
if (!dmp_load_motion_driver_firmware()) {
EMBARC_PRINTF("dmp_load_motion_driver_firmware complete ......\r\n");
}
mpu_delay_ms(50);
if (!dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation))) {
EMBARC_PRINTF("dmp_set_orientation complete ......\r\n");
}
mpu_delay_ms(50);
if (!dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_SEND_RAW_ACCEL |
DMP_FEATURE_SEND_RAW_GYRO)) {
// DMP_FEATURE_SEND_CAL_GYRO | DMP_FEATURE_GYRO_CAL))
EMBARC_PRINTF("dmp_enable_feature complete ......\r\n");
}
mpu_delay_ms(50);
if (!dmp_set_fifo_rate(DEFAULT_MPU_HZ)) {
EMBARC_PRINTF("dmp_set_fifo_rate complete ......\r\n");
}
mpu_delay_ms(50);
// run_self_test();
mpu_delay_ms(50);
if (!mpu_set_dmp_state(1)) {
EMBARC_PRINTF("mpu_set_dmp_state complete ......\r\n");
}
mpu_delay_ms(50);
}
#endif
}
error_exit:
return ercd;
}
int32_t mpu9250_sensor_deinit(MPU9250_DEF_PTR obj)
{
int32_t ercd = E_OK;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
ercd = iic_obj->iic_close();
MPU9250_CHECK_EXP_NORTN(ercd == E_OK);
error_exit:
return ercd;
}
int32_t mpu9250_sensor_read(MPU9250_DEF_PTR obj, MPU9250_DATA_PTR mp_data)
{
int32_t ercd = E_OK;
MPU9250_CHECK_EXP_NORTN(mp_data != NULL);
#ifndef MPU9250_USE_DMP
uint8_t data[6];
uint8_t config;
ercd = _mpu_reg_read(obj, obj->mpu_slvaddr, GYRO_XOUT_H, data, 6);
if (ercd != 6) {
ercd = E_OBJ;
goto error_exit;
} else {
ercd = E_OK;
mp_data->gyro_x = ((int16_t)data[0] << 8) + ((int16_t)data[1]);
mp_data->gyro_y = ((int16_t)data[2] << 8) + ((int16_t)data[3]);
mp_data->gyro_z = ((int16_t)data[4] << 8) + ((int16_t)data[5]);
}
ercd = _mpu_reg_read(obj, obj->mpu_slvaddr, ACCEL_XOUT_H, data, 6);
if (ercd != 6) {
ercd = E_OBJ;
goto error_exit;
} else {
ercd = E_OK;
mp_data->accel_x = ((int16_t)data[0] << 8) + ((int16_t)data[1]);
mp_data->accel_y = ((int16_t)data[2] << 8) + ((int16_t)data[3]);
mp_data->accel_z = ((int16_t)data[4] << 8) + ((int16_t)data[5]);
}
ercd = _mpu_reg_read(obj, obj->mag_slvaddr, MAG_XOUT_L, data, 6);
if (ercd != 6) {
ercd = E_OBJ;
} else {
ercd = E_OK;
mp_data->mag_x = ((int16_t)data[1] << 8) + ((int16_t)data[0]);
mp_data->mag_y = ((int16_t)data[3] << 8) + ((int16_t)data[2]);
mp_data->mag_z = ((int16_t)data[5] << 8) + ((int16_t)data[4]);
}
config = 0x01;
ercd = _mpu_reg_write(obj, obj->mag_slvaddr, MAG_CTRL, &config, 1);// mag single measurement mode
#else
short gyro[3], accel[3], sensors;
float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f;
unsigned long sensor_timestamp;
unsigned char more;
long quat[4];
float q30 = (float)(1 << 30);
if (dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, &more) == 0) {
mp_data->gyro_x = gyro[0];
mp_data->gyro_y = gyro[1];
mp_data->gyro_z = gyro[2];
mp_data->accel_x = accel[0];
mp_data->accel_y = accel[1];
mp_data->accel_z = accel[2];
if (sensors & INV_WXYZ_QUAT) {
q0 = quat[0] / q30;
q1 = quat[1] / q30;
q2 = quat[2] / q30;
q3 = quat[3] / q30;
mp_data->pitch = (float)asin(-2 * q1 * q3 + 2 * q0 * q2) * 57.3f;
mp_data->roll = (float)atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2 * q2 + 1) * 57.3f;
mp_data->yaw = (float)atan2(2 * (q1 * q2 + q0 * q3), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3) * 57.3f;
return 0;
}
}
#endif
error_exit:
return ercd;
}
#ifdef MPU9250_USE_DMP
int32_t mpu_iic_write(uint32_t slaveaddr, uint8_t regaddr, uint8_t len, uint8_t *val)
{
int32_t ercd = E_PAR;
uint8_t data[1];
DEV_IIC_PTR iic_obj = iic_get_dev(mpu9250_ptr->i2c_id);
dbg_printf(DBG_LESS_INFO, "[%s]%d: obj 0x%x, regaddr 0x%x, val 0x%x\r\n", __FUNCTION__, __LINE__, obj, regaddr, *val);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
data[0] = (uint8_t)(regaddr & 0xff);
iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slaveaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_write(val, len);
if (ercd == len) {
ercd = E_OK;
}
error_exit:
return ercd;
}
int32_t mpu_iic_read(uint32_t slaveaddr, uint8_t regaddr, uint8_t len, uint8_t *val)
{
int32_t ercd = E_PAR;
uint8_t data[1];
DEV_IIC_PTR iic_obj = iic_get_dev(mpu9250_ptr->i2c_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
data[0] = (uint8_t)(regaddr & 0xff);
iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slaveaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_read(val, len);
if (ercd == len) {
ercd = E_OK;
}
error_exit:
return ercd;
}
int mpu_get_ms(unsigned long *count)
{
*count = (unsigned long)OSP_GET_CUR_MS();
return 0;
}
void mpu_delay_ms(uint32_t ms)
{
board_delay_ms(ms);
}
#endif

View File

@@ -1,87 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_MPU9250
#define H_MPU9250
// MPU9250 (Nine-Axis (Gyro + Accelerometer + Compass) sensor using I2C bus) is on IOTDK board
#include "device/ip_hal/dev_iic.h"
#define MPU9250_USE_DMP
#define MPU9250_AD0_PIN 0 /*!< I2C Serial Bus Address Selection Pin */
#define MPU9250_IIC_ADDRESS (0x68 + (MPU9250_AD0_PIN << 1))
#define MAG_IIC_ADDRESS 0x0C
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int16_t accel_x;
int16_t accel_y;
int16_t accel_z;
int16_t gyro_x;
int16_t gyro_y;
int16_t gyro_z;
int16_t mag_x;
int16_t mag_y;
int16_t mag_z;
float pitch;
float roll;
float yaw;
} MPU9250_DATA, *MPU9250_DATA_PTR;
typedef struct {
uint32_t i2c_id;
uint32_t mpu_slvaddr;
uint32_t mag_slvaddr;
} MPU9250_DEF, *MPU9250_DEF_PTR;
#define MPU9250_DEFINE(NAME, I2C_ID, SLAVE_ADDRESS) \
MPU9250_DEF __ ## NAME = { \
.i2c_id = I2C_ID, \
.mpu_slvaddr = SLAVE_ADDRESS, \
.mag_slvaddr = MAG_IIC_ADDRESS \
}; \
MPU9250_DEF_PTR NAME = &__ ## NAME
extern int32_t mpu9250_sensor_init(MPU9250_DEF_PTR obj);
extern int32_t mpu9250_sensor_deinit(MPU9250_DEF_PTR obj);
extern int32_t mpu9250_sensor_read(MPU9250_DEF_PTR obj, MPU9250_DATA_PTR mp_data);
extern int32_t mpu_iic_read(uint32_t slaveaddr, uint8_t regaddr, uint8_t len, uint8_t *val);
extern int32_t mpu_iic_write(uint32_t slaveaddr, uint8_t regaddr, uint8_t len, uint8_t *val);
int mpu_get_ms(unsigned long *count);
void mpu_delay_ms(uint32_t ms);
#ifdef __cplusplus
}
#endif
#endif /* H_MPU9250 */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/sensor/imu/mpu9250
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/sensor/imu/mpu9250

View File

@@ -1,490 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_CORE_COMM
* @brief Header file for common core definitions
*/
/**
* @addtogroup ARC_HAL_CORE_COMM
* @{
*/
#ifndef H_ARC_CORE
#define H_ARC_CORE
#include "arc/arc_feature_config.h"
/**
* @name exception number definitions
* @{
*/
/* ARC exception number */
#define EXC_NO_RESET (0) /*!< reset vector, the entry of power up and reset */
#define EXC_NO_MEM_ERR (1) /*!< external memory bus error */
#define EXC_NO_INS_ERR (2) /*!< illegal instruction or illegal instruction sequence */
#define EXC_NO_MAC_CHK (3) /*!< machine check error */
#define EXC_NO_TLB_MISS_I (4) /*!< instruction TLB missing exception, useless without MMU */
#define EXC_NO_TLB_MISS_D (5) /*!< data TLB missing exception, useless without MMU */
#define EXC_NO_PRO_VIO (6) /*!< protection violation */
#define EXC_NO_PRI_VIO (7) /*!< privilege violation */
#define EXC_NO_SWI (8) /*!< software interrupt */
#define EXC_NO_TRAP (9) /*!< trap */
#define EXC_NO_EXT (10) /*!< extension exception */
#define EXC_NO_DIV_ZER0 (11) /*!< divide by zero */
#define EXC_NO_DC_ERR (12) /*!< data cache consistency error */
#define EXC_NO_MAL_ALIGN (13) /*!< misaligned data access */
#define EXC_NO_VEC_UNIT (14) /*!< vector unit exception (Vector stack pointer check violation is detected in the vector unit.) */
#define EXC_NO_RESERVE0 (15) /*!< reserved */
/* extension interrupts */
#define EXC_NO_16 (16) /*!< interrupt vector 16 */
#define EXC_NO_17 (17) /*!< interrupt vector 17 */
#define EXC_NO_18 (18) /*!< interrupt vector 18 */
#define EXC_NO_19 (19) /*!< interrupt vector 19 */
#define EXC_NO_20 (20) /*!< interrupt vector 20 */
#define EXC_NO_21 (21) /*!< interrupt vector 21 */
#define EXC_NO_22 (22) /*!< interrupt vector 22 */
#define EXC_NO_23 (23) /*!< interrupt vector 23 */
#define EXC_NO_24 (24) /*!< interrupt vector 24 */
#define EXC_NO_25 (25) /*!< interrupt vector 25 */
#define EXC_NO_26 (26) /*!< interrupt vector 26 */
#define EXC_NO_27 (27) /*!< interrupt vector 27 */
#define EXC_NO_28 (28) /*!< interrupt vector 28 */
#define EXC_NO_29 (29) /*!< interrupt vector 29 */
#define EXC_NO_30 (30) /*!< interrupt vector 30 */
#define EXC_NO_31 (31) /*!< interrupt vector 31 */
/* ... ARC supports 255 interrupt vectors at most */
#define EXC_NO_255 (255 /*!< interrupt vector 255 */
/** @} */
/**
* @name exception vector offset
* @{
*/
#define EXC_NO_TO_OFFSET(no) (no << 2)
/* ARC exception vector offset */
#define EXC_VECTOR_RESET (0x00) /*!< EXC_NO_RESET offset */
#define EXC_VECTOR_MEM_ERR (0x04) /*!< EXC_NO_MEM_ERR offset */
#define EXC_VECTOR_INS_ERR (0x08) /*!< EXC_NO_INS_ERR offset */
#define EXC_VECTOR_MAC_CHK (0x0c) /*!< EXC_NO_MAC_CHK offset */
#define EXC_VECTOR_TLB_MISS_I (0x10) /*!< EXC_NO_TLB_MISS_I offset */
#define EXC_VECTOR_TLB_MISS_D (0x14) /*!< EXC_NO_TLB_MISS_D offset */
#define EXC_VECTOR_PRO_VIO (0x18) /*!< EXC_NO_PRO_VIO offset */
#define EXC_VECTOR_PRI_VIO (0x1c) /*!< EXC_NO_PRI_VIO offset */
#define EXC_VECTOR_SWI (0x20) /*!< EXC_NO_SWI offset */
#define EXC_VECTOR_TRAP (0x24) /*!< EXC_NO_TRAP offset */
#define EXC_VECTOR_EXT (0x28) /*!< EXC_NO_EXT offset */
#define EXC_VECTOR_DIV_ZER0 (0x2c) /*!< EXC_NO_DIV_ZER0 offset */
#define EXC_VECTOR_DC_ERR (0x30) /*!< EXC_NO_DC_ERR offset */
#define EXC_VECTOR_MAL_ALIGN (0x34) /*!< EXC_NO_MAL_ALIGN offset */
#define EXC_VECTOR_VEC_UNIT (0x38) /*!< EXC_NO_VEC_UNIT offset */
#define EXC_VECTOR_RESERVE0 (0x3c) /*!< EXC_NO_RESERVE0 offset */
/** @} */
/**
* @name build configuration register
* @{
*/
#define AUX_BCR_VER (0x60) /*!< build configuration register version */
#define AUX_BCR_BTA (0x63) /*!< build configuration for BTA LINK */
#define AUX_BCR_VECBASE (0x68) /*!< build configuration for interrupt vector base */
#define AUX_BCR_MPU (0x6d) /*!< build configuration for memory protection unit */
#define AUX_BCR_RF (0x6e) /*!< build configuration for core registers */
#define AUX_BCR_D_CACHE (0x72) /*!< build configuration for data cache */
#define AUX_BCR_DCCM (0x74) /*!< build configuration for DCCM */
#define AUX_BCR_TIMERS (0x75) /*!< build configuration for processor timers */
#define AUX_BCR_AP (0x76) /*!< build configuration for actionpoints */
#define AUX_BCR_I_CACHE (0x77) /*!< build configuration for instruction cache */
#define AUX_BCR_ICCM (0x78) /*!< build configuration for ICCM */
#define AUX_BCR_DSP (0x7a) /*!< build configuration for DSP */
#define AUX_BCR_MUL (0x7b) /*!< build configuration for multiply */
#define AUX_BCR_SWAP (0x7c) /*!< build configuration for swap */
#define AUX_BCR_NORM (0x7d) /*!< build configuration for normalize */
#define AUX_BCR_MIXMAX (0x7e) /*!< build configuration for MIN/MAX */
#define AUX_BCR_BARREL (0x7f) /*!< build configuration for barrel shift */
#define AUX_BCR_ISA (0xc1) /*!< build configuration for ISA configuration */
#define AUX_BCR_STACK (0xc5) /*!< build configuration for stack region */
#define AUX_BCR_ERP (0xc7) /*!< build configuration for error protection */
#define AUX_BCR_FPU (0xc8) /*!< build configuration for floating-point unit */
#define AUX_BCR_CPORT (0xc9) /*!< build configuration for code protection */
#define AUX_BCR_BS (0xcb) /*!< build configuration for bitstream */
#define AUX_BCR_AGU (0xcc) /*!< build configuration for address generate unit */
#define AUX_BCR_DMAC (0xcd) /*!< build configuration for DMA */
#define AUX_BCR_CONNECT_SYSTEM (0xd0) /*!< build configuration for arc connect */
#define AUX_BCR_CONNECT_SEMA (0xd1) /*!< build configuration for inter-core semaphore */
#define AUX_BCR_CONNECT_MESSAGE (0xd2) /*!< build configuration for inter-code message */
#define AUX_BCR_CONNECT_PMU (0xd3) /*!< build configuration for power management unit */
#define AUX_BCR_CONNECT_GFRC (0xd6) /*!< build configuration for global free running counter */
#define AUX_BCR_CAL_STORE (0xd9) /*!< build configuration for calibration parameter storage */
#define AUX_BCR_CONNECT_ICI (0xe0) /*!< build configuration for inter-core interrupt unit */
#define AUX_BCR_CONNECT_ICD (0xe1) /*!< build configuration for inter-core debug unit */
#define AUX_BCR_CONNECT_PDM (0xe3) /*!< build configuration for power domain management unit*/
#define AUX_BCR_RTT (0xf2) /*!< build configuration for real-time trace */
#define AUX_BCR_IRQ (0xf3) /*!< build configuration for interrupt */
#define AUX_BCR_PCT (0xf5) /*!< build configuration for performance counters */
#define AUX_BCR_CC (0xf6) /*!< build configuration for performance counters */
#define AUX_BCR_PDM_DVFS (0xf7) /*!< build configuration for PDM and DVFS */
#define AUX_BCR_SEC_BUILD (0xdb)
/* from 0xF5 and 0xF6 */
#define AUX_BCR_IFQUEUE (0xfe) /*!< build configuration for instruction fetch queue */
#define AUX_BCR_SMART (0xff) /*!< build configuration for SmaRT debug feature */
/** @} */
#define AUX_SEC_STAT (0x9)
#define AUX_SEC_STAT_BIT_SSC (0)
#define AUX_SEC_STAT_BIT_NSRT (1)
#define AUX_SEC_STAT_BIT_NSRU (2)
#define AUX_SEC_STAT_BIT_IRM (3)
#define AUX_SEC_STAT_BIT_SUE (4)
#define AUX_SEC_STAT_BIT_NIC (5)
#define AUX_SEC_STAT_BIT_ERM (31)
/**
* @name status register STATUS32
* @{
*/
#define AUX_STATUS32 (0xa)
#define AUX_STATUS32_P0 (0xb)
/* STATUS32 bit-field definition */
#define AUX_STATUS_BIT_AE (5) /*!< processor is in an exception */
#define AUX_STATUS_BIT_DE (6) /*!< delayed branch is pending */
#define AUX_STATUS_BIT_U (7) /*!< user mode */
#define AUX_STATUS_BIT_L (12) /*!< zero-overhead loop enable */
#define AUX_STATUS_BIT_IE (31) /*!< interrupt enable */
#define AUX_STATUS_BIT_HALT (0) /*!< halt bit */
#define AUX_STATUS_BIT_SC (14) /*!< stack check bit */
#define AUX_STATUS_BIT_AD (19) /*!< alignment check bit */
#define AUX_STATUS_BIT_US (20) /*!< user sleep mode enable bit */
#define AUX_STATUS_RB(x) ((x) << 16) /*!< register bank */
/* masks correspond to STATUS32 bit-field */
#define AUX_STATUS_MASK_AE (1 << AUX_STATUS_BIT_AE) /*!< mask of AUX_STATUS_BIT_AE */
#define AUX_STATUS_MASK_DE (1 << AUX_STATUS_BIT_DE) /*!< mask of AUX_STATUS_BIT_DE */
#define AUX_STATUS_MASK_U (1 << AUX_STATUS_BIT_U) /*!< mask of AUX_STATUS_BIT_U */
#define AUX_STATUS_MASK_L (1 << AUX_STATUS_BIT_L) /*!< mask of AUX_STATUS_BIT_L */
#define AUX_STATUS_MASK_IE (1 << AUX_STATUS_BIT_IE) /*!< mask of AUX_STATUS_BIT_IE */
#define AUX_STATUS_MASK_HALT (1 << AUX_STATUS_BIT_HALT) /*!< mask of AUX_STATUS_BIT_HALT */
#define AUX_STATUS_MASK_SC (1 << AUX_STATUS_BIT_SC) /*!< mask of AUX_STATUS_BIT_SC */
#define AUX_STATUS_MASK_AD (1 << AUX_STATUS_BIT_AD) /*!< mask of AUX_STATUS_BIT_AD */
#define AUX_STATUS_MASK_US (1 << AUX_STATUS_BIT_US) /*!< mask of AUX_STATUS_BIT_US */
#ifdef ARC_FEATURE_UNALIGNED
#define STATUS32_RESET_VALUE (AUX_STATUS_MASK_AD | AUX_STATUS_MASK_US)
#else
#define STATUS32_RESET_VALUE (AUX_STATUS_MASK_US)
#endif
/** @} */
/**
* @name zero overhead loop auxiliary register
* @{
*/
#define AUX_LP_START (0x2) /*!< loop start address (32-bit) */
#define AUX_LP_END (0x3) /*!< loop end address (32-bit) */
/** @} */
#define AUX_USER_SP (0xd) /*!< user-mode stack pointer */
/* added in secure mode */
#define AUX_KERNEL_SP (0x38) /*!< kernel-mode stack pointer */
#define AUX_SEC_U_SP (0x39) /*!< secure user-mode stack pointer */
#define AUX_SEC_K_SP (0x3a) /*!< secure kernel-mode stack pointer */
/* additional stack checking registers for secure mode */
#define AUX_S_USTACK_BASE (0x263)
#define AUX_S_USTACK_TOP (0x262)
#define AUX_S_KSTACK_BASE (0x267)
#define AUX_S_KSTACK_TOP (0x266)
#define AUX_KSTACK_TOP (0x264)
#define AUX_KSTACK_BASE (0x265)
#define AUX_USTACK_TOP (0x260)
#define AUX_USTACK_BASE (0x261)
/**
* @name auxiliary register for hardware counter 0 and 1
* @{
*/
#define AUX_TIMER0_LIMIT (0x23) /*!< timer 0 limit value */
#define AUX_TIMER0_CTRL (0x22) /*!< timer 0 control value */
#define AUX_TIMER0_CNT (0x21) /*!< timer 0 count value */
#define AUX_TIMER1_LIMIT (0x102) /*!< timer 1 limit value */
#define AUX_TIMER1_CTRL (0x101) /*!< timer 1 control value */
#define AUX_TIMER1_CNT (0x100) /*!< timer 1 count value */
/** @} */
#define AUX_SECURE_TIMER0_CNT (0x106) /*!< secure timer 0 count value */
#define AUX_SECURE_TIMER0_CTRL (0x107) /*!< secure timer 0 control value */
#define AUX_SECURE_TIMER0_LIMIT (0x108) /*!< secure timer 0 limit value */
#define AUX_SECURE_TIMER1_CNT (0x109) /*!< secure timer 1 count value */
#define AUX_SECURE_TIMER1_CTRL (0x10a) /*!< secure timer 1 control value */
#define AUX_SECURE_TIMER1_LIMIT (0x10b) /*!< secure timer 1 limit value */
/**
* @name auxiliary register for real-time counter
* @{
*/
#define AUX_RTC_CTRL (0x103) /*!< real-time counter control register */
#define AUX_RTC_LOW (0x104) /*!< real-time counter count low register */
#define AUX_RTC_HIGH (0x105) /*!< real-time counter count high register */
/** @} */
/**
* @name indexed table auxiliary register
* @{
*/
#define AUX_JLI_BASE (0x290) /*!< jump and link indexed base address */
#define AUX_LDI_BASE (0x291) /*!< load indexed base address */
#define AUX_EI_BASE (0x292) /*!< execute indexed base address */
/** @} */
/**
* @name baseline auxiliary register set
* @{
*/
/* exception related aux regs */
#define AUX_ERRET (0x400) /*!< exception return address */
#define AUX_ERBTA (0x401) /*!< BTA saved on exception entry */
#define AUX_ERSTATUS (0x402) /*!< STATUS32 saved on exception */
#define AUX_ECR (0x403) /*!< exception cause register */
#define AUX_EFA (0x404) /*!< exception fault address */
#define AUX_BTA (0x412) /*!< branch target address */
/** @} */
/* New register to control which exceptions can be handled in NS mode */
#define AUX_ERSEC_STAT (0x406)
#define AUX_ERSEC_STAT_BIT_ERM (31)
#define AUX_SEC_EXCEPT (0x407)
/**
* @name MPU register set
* @{
*/
#define AUX_MPU_EN (0x409) /*!< MPU enable register */
#define AUX_MPU_ECR (0x420) /*!< MPU exception cause */
#define AUX_MPU_RDB0 (0x422) /*!< MPU region descriptor base 0 */
#define AUX_MPU_RDP0 (0x423) /*!< MPU region descriptor permission 0 */
/* MPU register set in silverstone */
#define AUX_MPU_INDEX (0x448)
#define AUX_MPU_INDEX_BIT_D (31)
#define AUX_MPU_RSTART (0x449)
#define AUX_MPU_REND (0x44a)
#define AUX_MPU_RPER (0x44b)
#define AUX_MPU_RPER_BIT_S (15)
#define AUX_MPU_PROBE (0x44c)
#define AUX_NSC_TABLE_BASE (0x269)
#define AUX_NSC_TABLE_TOP (0x268)
/** @} */
/**
* @name exception cause register (ECR) bit-field definition
* @{
*/
#define AUX_ECR_VEC_MASK (0xff0000) /*!< [23:16] = exception vector */
#define AUX_ECR_CODE_MASK (0x00ff00) /*!< [15: 8] = exception cause code */
#define AUX_ECR_PARAM_MASK (0x0000ff) /*!< [ 7: 0] = exception parameters */
/** @} */
/**
* @name exception vector number and cause code
* @{
*/
#define AUX_ECR_V_INSN_ERR (0x02) /*!< vector number of illegal instruction */
#define AUX_ECR_V_MACH_CHK (0x03) /*!< vector number of machine check */
#define AUX_ECR_V_ITLB_MISS (0x04) /*!< vector number of instruction TLB missing exception */
#define AUX_ECR_V_DTLB_MISS (0x05) /*!< vector number of data TLB missing exception */
#define AUX_ECR_V_PROTV (0x06) /*!< vector number of protection violation */
#define AUX_ECR_V_PRIV (0x07) /*!< vector number of privilege violation */
#define AUX_ECR_V_SWI (0x08) /*!< vector number of software interrupt */
#define AUX_ECR_V_TRAP (0x09) /*!< vector number of trap */
#define AUX_ECR_V_EXT (0x0a) /*!< vector number of extension */
#define AUX_ECR_V_DIV_ZERO (0x0b) /*!< vector number of divide by zero*/
#define AUX_ECR_V_DC_ERR (0x0c) /*!< vector number of data cache consistency error */
#define AUX_ECR_V_MISALIG_DATA (0x0d) /*!< vector number of misaligned data access */
#define AUX_ECR_C_PROTV_INST_FETCH (0x00) /*!< cause code of instruction fetch (protection violation) */
#define AUX_ECR_C_PROTV_LOAD (0x01) /*!< cause code of memory read related (protection violation) */
#define AUX_ECR_C_PROTV_STORE (0x02) /*!< cause code of memory write related (protection violation) */
#define AUX_ECR_C_PROTV_XCHG (0x03) /*!< cause code of read-modify-write related (protection violation) */
#define AUX_ECR_C_PROTV_NS_VECT_IN_S (0x10) /*!< cause code of NS vector table in S memory (protection violation) */
#define AUX_ECR_C_PROTV_NS_HANDLER_IN_S (0x11) /*!< cause code of NS handler in S memory (protection violation) */
#define AUX_ECR_C_PROTV_NSC_RANGE (0x12) /*!< cause code of NSC table range violation (protection violation) */
#define AUX_ECR_C_PRIV_PRIV (0x00) /*!< cause code of privilege violation (privilege violation) */
#define AUX_ECR_C_PRIV_DIS_EXT (0x01) /*!< cause code of disabled extension (privilege violation) */
#define AUX_ECR_C_PRIV_ACT_HIT (0x02) /*!< cause code of action point hit (privilege violation) */
#define AUX_ECR_C_PRIV_ACT_SECURE (0x10) /*!< cause code of secure related operation (privilege violation) */
#define AUX_ECR_C_MCHK_DUP_TLB (0x01) /*!< @todo definition is to be added. */
#define AUX_ECR_C_BIT_DTLB_LD_MISS (8) /*!< @todo definition is to be added. */
#define AUX_ECR_C_BIT_DTLB_ST_MISS (9) /*!< @todo definition is to be added. */
/** @} */
/**
* @name interrupt related auxiliary register
* @{
*/
#define AUX_IRQ_CTRL (0xe) /*!< interrupt context saving control register */
#define AUX_INT_VECT_BASE (0x25) /*!< interrupt vector base register */
#define AUX_INT_VECT_BASE_S (0x26) /*!< secure interrupt vector based register */
#define AUX_IRQ_ACT (0x43) /*!< active interrupts register */
#define AUX_IRQ_CAUSE (0x40a) /*!< interrupt cause register */
#define AUX_IRQ_SELECT (0x40b) /*!< interrupt select register */
#define AUX_IRQ_PRIORITY (0x206) /*!< interrupt priority register */
#define AUX_IRQ_PRIORITY_BIT_S (0x8) /*!< S bit offset in interrupt priority register */
#define AUX_IRQ_ENABLE (0x40c) /*!< interrupt enable register */
#define AUX_IRQ_TRIGGER (0x40d) /*!< interrupt trigger: level or pulse */
#define AUX_IRQ_PENDING (0x416) /*!< interrupt pending register */
#define AUX_IRQ_PLUSE_CLR (0x415) /*!< interrupt pulse cancel register */
#define AUX_IRQ_STATUS (0x40f) /*!< interrupt status register */
#define AUX_IRQ_PRI_PENDING (0x200) /*!< interrupt priority pending register */
#define AUX_IRQ_HINT (0x201) /*!< software interrupt trigger */
/** @} */
/**
* @name cache related auxiliary register
* @{
*/
#define AUX_IC_IVIC (0x10) /*!< invalidate instruction cache */
#define AUX_IC_CTRL (0x11) /*!< instruction cache control register */
#define AUX_IC_LIL (0x13) /*!< lock instruction cache line */
#define AUX_IC_IVIL (0x19) /*!< invalidate instruction cache line */
#define AUX_IC_RAM_ADDR (0x1a) /*!< instruction cache external access address */
#define AUX_IC_TAG (0x1b) /*!< instruction cache tag access */
#define AUX_IC_XTAG (0x1c) /*!< instruction cache secure bit tag */
#define AUX_IC_DATA (0x1d) /*!< instruction cache data access */
#define AUX_DC_IVDC (0x47) /*!< invalidate data cache */
#define AUX_DC_CTRL (0x48) /*!< data cache control register */
#define AUX_DC_LDL (0x49) /*!< lock data cache line */
#define AUX_DC_IVDL (0x4a) /*!< invalidate data cache line */
#define AUX_DC_FLSH (0x4b) /*!< flush data cache */
#define AUX_DC_FLDL (0x4c) /*!< flush data line */
#define AUX_DC_RAM_ADDR (0x58) /*!< data cache external access address */
#define AUX_DC_TAG (0x59) /*!< data cache tag access */
#define AUX_DC_XTAG (0x5a) /*!< data cache secure bit tag */
#define AUX_DC_DATA (0x5b) /*!< data cache data access */
/** @} */
/**
* @name dmac related auxiliary register
* @{
*/
#define AUX_DMACTRL (0x680) /*!< DMA control register */
#define AUX_DMACENB (0x681) /*!< DMA channel enable register */
#define AUX_DMACDSB (0x682) /*!< DMA channel disable register */
#define AUX_DMACHPRI (0x683) /*!< DMA channel high priority level register */
#define AUX_DMACNPRI (0x684) /*!< DMA channel normal priority level register */
#define AUX_DMACREQ (0x685) /*!< DMA channel transfer request register */
#define AUX_DMACSTAT0 (0x686) /*!< DMA channel status register 0 */
#define AUX_DMACSTAT1 (0x687) /*!< DMA channel status register 1 */
#define AUX_DMACIRQ (0x688) /*!< DMA channel interrupt request status/clear register */
#define AUX_DMACBASE (0x689) /*!< DMA channel structure register base address */
#define AUX_DMACRST (0x68A) /*!< DMA channel reset register base address */
#define AUX_DMACTRL0 (0x690) /*!< DMA channel 0 control register when mapped in aux */
#define AUX_DMASAR0 (0x691) /*!< DMA channel 0 source address register when mapped in aux */
#define AUX_DMADAR0 (0x692) /*!< DMA channel 0 destination register when mapped in aux */
#define AUX_DMACTRLx (AUX_DMACTRL0) /*!< DMA channel 0 control register when mapped in aux */
#define AUX_DMASARx (AUX_DMASAR0) /*!< DMA channel 0 source address register when mapped in aux */
#define AUX_DMADARx (AUX_DMADAR0) /*!< DMA channel 0 destination register when mapped in aux */
/** @} */
/**
* @name fpu related auxiliary register
* @{
*/
#define AUX_FPU_CTRL (0x300) /*!< FPU ctrl register */
#define AUX_FPU_STATUS (0x301) /*!< FPU status register */
#define AUX_FPU_DPFP1L (0x302) /*!< double float D1 register low */
#define AUX_FPU_DPFP1H (0x303) /*!< double float D1 register high */
#define AUX_FPU_DPFP2L (0x304) /*!< double float D2 register low */
#define AUX_FPU_DPFP2H (0x305) /*!< double float D2 register high */
/** @} */
/**
* @name dsp related auxiliary register
* @{
*/
#define AUX_ACC0_LO (0x580)
#define AUX_ACC0_GLO (0x581)
#define AUX_ACC0_HI (0x582)
#define AUX_ACC0_GHI (0x583)
#define AUX_DSP_BFLY0 (0x598)
#define AUX_DSP_FFT_CTRL (0x59e)
#define AUX_DSP_CTRL (0x59f)
/** @} */
/**
* @name other auxiliary register
* @{
*/
#define AUX_IDENTITY (0x4) /*!< identity register */
#define AUX_DMP_PERIPHERAL (0x20a) /*!< peripheral memory region */
#define AUX_XFLAGS (0x44f) /*!< user extension flags register */
#define AUX_CONNECT_CMD (0x600) /*!< ARConnect Command Register, CONNECT_CMD */
#define AUX_CONNECT_WDATA (0x601) /*!< ARConnect Write Data Register, CONNECT_WDATA */
#define AUX_CONNECT_READBACK (0x602) /*!< ARConnect Read Data Register, CONNECT_READBACK */
#define AUX_SMART_CONTROL (0x700) /*!< SmaRT Control Register, SMART_CONTROL */
#define AUX_SMART_DATA (0x701) /*!< SmaRT Data Register, SMART_DATA */
/** @} */
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_CORE */
/** @} */

View File

@@ -1,705 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC
* @brief common macro definitions for assembly file
*/
/** @cond ARC_HAL_ASM_COMMON */
#ifndef H_ARC_ASM_COMMON
#define H_ARC_ASM_COMMON
#include "arc/arc.h"
#ifdef __ASSEMBLY__
/* the assembly macro definitions in ARC GNU and MWDT are
* different, so need different processing
*/
#if defined(__GNU__)
#define MACRO_ARG(x) \ x
#define ASM_MACRO1(name, arg1) name arg1
#define ASM_MACRO2(name, arg1, arg2) name arg1 arg2
#define ASM_MACRO3(name, arg1, arg2, arg3) name arg1 arg, agr3
#define ASM_MACRO4(name, arg1, arg2, arg3, arg4) name arg1 arg2 arg3 arg4
#else
#define MACRO_ARG(x) x
#define ASM_MACRO1(name, arg1) name, arg1
#define ASM_MACRO2(name, arg1, arg2) name, arg1, arg2
#define ASM_MACRO3(name, arg1, arg2, arg3) name, arg1, arg2, agr3
#define ASM_MACRO4(name, arg1, arg2, arg3, arg4) name, arg1, arg2, arg3, arg4
#endif
/* Note on the LD/ST addr modes with addr reg wback
*
* LD.a same as LD.aw
*
* LD.a reg1, [reg2, x] => Pre Incr
* Eff Addr for load = [reg2 + x]
*
* LD.ab reg1, [reg2, x] => Post Incr
* Eff Addr for load = [reg2]
*/
.macro ASM_MACRO1(PUSH, reg)
st.a MACRO_ARG(reg), [sp, -4]
.endm
.macro ASM_MACRO1(PUSHAX, aux)
lr r10, [MACRO_ARG(aux)]
PUSH r10
.endm
.macro ASM_MACRO1(POP, reg)
ld.ab MACRO_ARG(reg), [sp, 4]
.endm
.macro ASM_MACRO1(POPAX, aux)
POP r10
sr r10, [MACRO_ARG(aux)]
.endm
/* macro to get the cpu id */
.macro ASM_MACRO1(GET_CORE_ID, reg)
lr MACRO_ARG(reg), [AUX_IDENTITY]
xbfu MACRO_ARG(reg), MACRO_ARG(reg), 0xe8
.endm
/* macro to save accl regs */
.macro SAVE_R58_R59
#if ARC_FEATURE_FPU || ARC_FEATURE_DSP || ARC_FEATURE_MPU_OPTION_NUM > 6
PUSH r58
PUSH r59
#endif
.endm
/* macro to restore accl regs */
.macro RESTORE_R58_R59
#if ARC_FEATURE_FPU || ARC_FEATURE_DSP || ARC_FEATURE_MPU_OPTION_NUM > 6
POP r59
POP r58
#endif
.endm
/* macro to save fpu related regs */
.macro SAVE_FPU_REGS
#if ARC_FEATURE_FPU
PUSHAX AUX_FPU_CTRL
PUSHAX AUX_FPU_STATUS
#if ARC_FEATURE_FPU_DA
PUSHAX AUX_FPU_DPFP1L
PUSHAX AUX_FPU_DPFP1H
PUSHAX AUX_FPU_DPFP2L
PUSHAX AUX_FPU_DPFP2H
#endif
#endif
.endm
/* macro to restore fpu related regs */
.macro RESTORE_FPU_REGS
#if ARC_FEATURE_FPU
#if ARC_FEATURE_FPU_DA
POPAX AUX_FPU_DPFP2H
POPAX AUX_FPU_DPFP2L
POPAX AUX_FPU_DPFP1H
POPAX AUX_FPU_DPFP1L
#endif
POPAX AUX_FPU_STATUS
POPAX AUX_FPU_CTRL
#endif
.endm
/* macro to save dsp related regs */
.macro SAVE_DSP_REGS
#if ARC_FEATURE_DSP
PUSHAX AUX_DSP_CTRL
PUSHAX AUX_ACC0_LO
PUSHAX AUX_ACC0_GLO
PUSHAX AUX_ACC0_HI
PUSHAX AUX_ACC0_GHI
#if ARC_FEATURE_DSP_COMPLEX
PUSHAX AUX_DSP_BFLY0
PUSHAX AUX_DSP_FFT_CTRL
#endif
#endif
.endm
/* macro to restore dsp related regs */
.macro RESTORE_DSP_REGS
#if ARC_FEATURE_DSP
#if ARC_FEATURE_DSP_COMPLEX
POPAX AUX_DSP_FFT_CTRL
POPAX AUX_DSP_BFLY0
#endif
POPAX AUX_ACC0_GHI
POPAX AUX_ACC0_HI
POPAX AUX_ACC0_GLO
POPAX AUX_ACC0_LO
POPAX AUX_DSP_CTRL
#endif
.endm
/*--------------------------------------------------------------
* Helpers to save/restore callee-saved regs:
* used by several macros below
*-------------------------------------------------------------*/
.macro SAVE_CALLEE_REGS
PUSH r13
PUSH r14
PUSH r15
#ifndef ARC_FEATURE_RF16
PUSH r16
PUSH r17
PUSH r18
PUSH r19
PUSH r20
PUSH r21
PUSH r22
PUSH r23
PUSH r24
PUSH r25
#endif
#if defined(ARC_ENABLE_EXTRA_CALLEE)
#if ARC_FEATURE_SEC_PRESENT
PUSHAX AUX_KERNEL_SP
PUSHAX AUX_SEC_K_SP
#else
PUSHAX AUX_USER_SP
#endif
#endif
#if ARC_FEATURE_FPU_DSP_CONTEXT
SAVE_FPU_REGS
SAVE_DSP_REGS
#endif
.endm
.macro RESTORE_CALLEE_REGS
#if ARC_FEATURE_FPU_DSP_CONTEXT
RESTORE_DSP_REGS
RESTORE_FPU_REGS
#endif
#if defined(ARC_ENABLE_EXTRA_CALLEE)
#if ARC_FEATURE_SEC_PRESENT
POPAX AUX_SEC_K_SP
POPAX AUX_KERNEL_SP
#else
POPAX AUX_USER_SP
#endif
#endif
#ifndef ARC_FEATURE_RF16
POP r25
POP r24
POP r23
POP r22
POP r21
POP r20
POP r19
POP r18
POP r17
POP r16
#endif
POP r15
POP r14
POP r13
.endm
/* macro to clear callee regs */
.macro CLEAR_CALLEE_REGS
#ifndef ARC_FEATURE_RF16
mov r25, 0
mov r24, 0
mov r23, 0
mov r22, 0
mov r21, 0
mov r20, 0
mov r19, 0
mov r18, 0
mov r17, 0
mov r16, 0
#endif
mov r15, 0
mov r14, 0
mov r13, 0
#if ARC_FEATURE_FPU_DSP_CONTEXT
#if ARC_FEATURE_FPU
#if ARC_FEATURE_FPU_DA
sr 0, [AUX_FPU_DPFP2H]
sr 0, [AUX_FPU_DPFP2L]
sr 0, [AUX_FPU_DPFP1H]
sr 0, [AUX_FPU_DPFP1L]
#endif
sr 0, [AUX_FPU_STATUS]
sr 0, [AUX_FPU_CTRL]
#endif /* ARC_FEATURE_FPU */
#if ARC_FEATURE_DSP
#if ARC_FEATURE_DSP_COMPLEX
sr 0, [AUX_DSP_FFT_CTRL]
sr 0, [AUX_DSP_BFLY0]
#endif
sr 0, [AUX_ACC0_GHI]
sr 0, [AUX_ACC0_HI]
sr 0, [AUX_ACC0_GLO]
sr 0, [AUX_ACC0_LO]
sr 0, [AUX_DSP_CTRL]
#endif /* ARC_FEATURE_DSP */
#endif /* ARC_FEATURE_FPU_DSP_CONTEXT */
.endm
/* macro to clear scratch regs */
.macro CLEAR_SCRATCH_REGS
mov r1, 0
mov r2, 0
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r8, 0
mov r9, 0
mov r10, 0
mov r11, 0
mov r12, 0
#if ARC_FEATURE_FPU || ARC_FEATURE_DSP || ARC_FEATURE_MPU_OPTION_NUM > 6
mov r59, 0
mov r58, 0
#endif
mov fp, 0
mov r29, 0
mov r30, 0
.endm
.macro SAVE_LP_REGS
PUSH r60
PUSHAX AUX_LP_START
PUSHAX AUX_LP_END
.endm
.macro RESTORE_LP_REGS
POPAX AUX_LP_END
POPAX AUX_LP_START
POP r10
/* must not use the LP_COUNT register(r60) as the destination of multi-cycle instruction */
mov r60, r10
.endm
/* macro to save r0 to r12 */
.macro SAVE_R0_TO_R12
PUSH r0
PUSH r1
PUSH r2
PUSH r3
#ifndef ARC_FEATURE_RF16
PUSH r4
PUSH r5
PUSH r6
PUSH r7
PUSH r8
PUSH r9
#endif
PUSH r10
PUSH r11
PUSH r12
.endm
/* macro to restore r0 to r12 */
.macro RESTORE_R0_TO_R12
POP r12
POP r11
POP r10
#ifndef ARC_FEATURE_RF16
POP r9
POP r8
POP r7
POP r6
POP r5
POP r4
#endif
POP r3
POP r2
POP r1
POP r0
.endm
/* macro to save code density regs */
.macro SAVE_CODE_DENSITY
PUSHAX AUX_JLI_BASE
PUSHAX AUX_LDI_BASE
PUSHAX AUX_EI_BASE
.endm
/* macro to restore code density regs */
.macro RESTORE_CODE_DENSITY
POPAX AUX_EI_BASE
POPAX AUX_LDI_BASE
POPAX AUX_JLI_BASE
.endm
/* macro to save all non-caller saved regs */
.macro SAVE_NONSCRATCH_REGS
/* caller saved regs are saved by caller function */
PUSH gp
PUSH fp
PUSH blink
SAVE_CALLEE_REGS
.endm
/* macro to restore all non-caller saved regs */
.macro RESTORE_NONSCRATCH_REGS
RESTORE_CALLEE_REGS
POP blink
POP fp
POP gp
.endm
/* macro to save regs in firq */
.macro SAVE_FIQ_EXC_REGS
#ifndef ARC_FEATURE_RGF_BANKED_REGS
SAVE_R0_TO_R12
SAVE_R58_R59
PUSH gp
PUSH fp
PUSH r30 /* general purpose */
PUSH blink
#else
#if ARC_FEATURE_RGF_BANKED_REGS != 4 && ARC_FEATURE_RGF_BANKED_REGS != 8 && \
ARC_FEATURE_RGF_BANKED_REGS != 16 && ARC_FEATURE_RGF_BANKED_REGS != 32
#error "unsupported ARC_FEATURE_RGF_BANKED_REGS"
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8 || \
ARC_FEATURE_RGF_BANKED_REGS == 16
#ifndef ARC_FEATURE_RF16
PUSH r4
PUSH r5
PUSH r6
PUSH r7
PUSH r8
PUSH r9
#endif
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8
PUSH r10
PUSH r11
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4
PUSH r12
#endif
SAVE_R58_R59
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8
PUSH gp
PUSH fp
PUSH r30 /* general purpose */
PUSH blink
#endif
#endif /* #ifndef ARC_FEATURE_RGF_BANKED_REGS */
#if ARC_FEATURE_CODE_DENSITY
SAVE_CODE_DENSITY
#endif
SAVE_LP_REGS
.endm
/* macro to restore reg in firq */
.macro RESTORE_FIQ_EXC_REGS
RESTORE_LP_REGS
#if ARC_FEATURE_CODE_DENSITY
RESTORE_CODE_DENSITY
#endif
#ifndef ARC_FEATURE_RGF_BANKED_REGS
POP blink
POP r30
POP fp
POP gp
RESTORE_R58_R59
RESTORE_R0_TO_R12
#else
#if ARC_FEATURE_RGF_BANKED_REGS != 4 && ARC_FEATURE_RGF_BANKED_REGS != 8 && \
ARC_FEATURE_RGF_BANKED_REGS != 16 && ARC_FEATURE_RGF_BANKED_REGS != 32
#error "unsupported ARC_FEATURE_RGF_BANKED_REGS"
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8
POP blink
POP r30
POP fp
POP gp
#endif
RESTORE_R58_R59
#if ARC_FEATURE_RGF_BANKED_REGS == 4
POP r12
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8
POP r11
POP r10
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8 || \
ARC_FEATURE_RGF_BANKED_REGS == 16
#ifndef ARC_FEATURE_RF16
POP r9
POP r8
POP r7
POP r6
POP r5
POP r4
#endif
#endif
#endif /* #ifndef ARC_FEATURE_RGF_BANKED_REGS */
.endm
/* normal interrupt prologue, pc, status and r0-r11 are saved by hardware */
.macro INTERRUPT_PROLOGUE
PUSH r12
SAVE_R58_R59
PUSH gp
PUSH fp
PUSH ilink
PUSH r30
sub sp, sp, 4 /* skip bta */
.endm
/* normal interrupt epilogue, pc, status and r0-r11 are restored by hardware */
.macro INTERRUPT_EPILOGUE
add sp, sp, 4 /* skip bta */
POP r30
POP ilink
POP fp
POP gp
RESTORE_R58_R59
POP r12
.endm
#if ARC_FEATURE_SEC_PRESENT
/* exception prologue, create the same frame of interrupt manually */
.macro EXCEPTION_PROLOGUE
st.as r10, [sp, -6] /* save r10 first, free up a register*/
PUSHAX AUX_ERSTATUS
sub sp, sp, 4 /* slot for SEC_STAT */
PUSHAX AUX_ERRET
PUSH blink
PUSH r11
sub sp, sp, 4 /* r10 is pushed before */
#ifndef ARC_FEATURE_RF16
PUSH r9
PUSH r8
PUSH r7
PUSH r6
PUSH r5
PUSH r4
#endif
PUSH r3
PUSH r2
PUSH r1
PUSH r0
#if ARC_FEATURE_CODE_DENSITY
SAVE_CODE_DENSITY
#endif
SAVE_LP_REGS
PUSH r12
SAVE_R58_R59
PUSH gp
PUSH fp
PUSH ilink
PUSH r30
PUSHAX AUX_ERBTA
.endm
/* exception epilogue, restore the same frame of interrupt manually */
.macro EXCEPTION_EPILOGUE
POPAX AUX_ERBTA
POP r30
POP ilink
POP fp
POP gp
RESTORE_R58_R59
POP r12
RESTORE_LP_REGS
#if ARC_FEATURE_CODE_DENSITY
RESTORE_CODE_DENSITY
#endif
POP r0
POP r1
POP r2
POP r3
#ifndef ARC_FEATURE_RF16
POP r4
POP r5
POP r6
POP r7
POP r8
POP r9
#endif
add sp, sp, 4 /* r10 will be popped finally */
POP r11
POP blink
POPAX AUX_ERRET
add sp, sp, 4 /* slot for SEC_STAT */
POPAX AUX_ERSTATUS
ld.as r10, [sp, -6] /* restore r10 */
.endm
#else /* normal version */
/* exception prologue, create the same frame of interrupt manually */
.macro EXCEPTION_PROLOGUE
#if ARC_FEATURE_CODE_DENSITY
st.as r10, [sp, -11] /* save r10 first, free up a register*/
#else
st.as r10, [sp, -8]
#endif
PUSHAX AUX_ERSTATUS
PUSHAX AUX_ERRET
#if ARC_FEATURE_CODE_DENSITY
SAVE_CODE_DENSITY
#endif
SAVE_LP_REGS
PUSH blink
PUSH r11
sub sp, sp, 4 /* r10 is pushed before */
#ifndef ARC_FEATURE_RF16
PUSH r9
PUSH r8
PUSH r7
PUSH r6
PUSH r5
PUSH r4
#endif
PUSH r3
PUSH r2
PUSH r1
PUSH r0
PUSH r12
SAVE_R58_R59
PUSH gp
PUSH fp
PUSH ilink
PUSH r30
PUSHAX AUX_ERBTA
.endm
/* exception epilogue, restore the same frame of interrupt manually */
.macro EXCEPTION_EPILOGUE
POPAX AUX_ERBTA
POP r30
POP ilink
POP fp
POP gp
RESTORE_R58_R59
POP r12
POP r0
POP r1
POP r2
POP r3
#ifndef ARC_FEATURE_RF16
POP r4
POP r5
POP r6
POP r7
POP r8
POP r9
#endif
add sp, sp, 4 /* r10 will be popped finally */
POP r11
POP blink
RESTORE_LP_REGS
#if ARC_FEATURE_CODE_DENSITY
RESTORE_CODE_DENSITY
#endif
POPAX AUX_ERRET
POPAX AUX_ERSTATUS
#if ARC_FEATURE_CODE_DENSITY
ld.as r10, [sp, -11] /* restore r10 */
#else
ld.as r10, [sp, -8]
#endif
.endm
#endif /* ARC_FEATURE_SEC_PRESENT */
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_ASM_COMMON */
/** @endcond */

View File

@@ -1,498 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_BUILTIN
* @brief Header file of builtin and helper functions
*
* The Metaware toolchain and the GNU toolchain are supported. The details please go to see the file.
*/
/**
* @addtogroup ARC_HAL_BUILTIN
* @{
*/
#ifndef H_ARC_BUILTIN
#define H_ARC_BUILTIN
#include "embARC_toolchain.h"
#include "arc/arc.h"
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
#if defined (__MW__) /* Metaware toolchain */
#elif defined (__GNU__) /* GNU toolchain */
#endif
/**
* @brief arc_compiler_usually(expr) evaluates expression expr and
* informs the compiler that the value is usually true.
*/
#define arc_compiler_usually(a) __builtin_expect(!!(a), 1)
/**
* @brief arc_compiler_rarely(expr) evaluates expression expr and
* informs the compiler that the value is rarely true.
*/
#define arc_compiler_rarely(a) __builtin_expect(!!(a), 0)
/**
* @fn void arc_mb(void)
* @brief Do memory barrier
*
*/
Inline void arc_mb(void)
{
Asm("dmb 3\n" : : : "memory");
}
/**
* @fn void arc_rmb(void)
* @brief Read memory barrier
*
*/
Inline void arc_rmb(void)
{
Asm("dmb 1\n" : : : "memory");
}
/**
* @fn void arc_wmb(void)
* @brief Write memory barrier
*
*/
Inline void arc_wmb(void)
{
Asm("dmb 2\n" : : : "memory");
}
/**
* @fn uint32_t arc_aux_read(uint32_t aux)
* @brief Read auxiliary register
*
* @param aux auxiliary register address
* @return value of auxiliary register
*/
Inline uint32_t arc_aux_read(uint32_t aux)
{
uint32_t ret;
Asm("lr %0, [%1]"
: "=r" (ret)
: "r" (aux));
return ret;
}
/**
* @fn void arc_aux_write(uint32_t aux, uint32_t val)
* @brief Write auxiliary register
*
* @param aux auxiliary register address
* @param val Value to write
*/
Inline void arc_aux_write(uint32_t aux, uint32_t val)
{
Asm(
"sr %0, [%1] \n"
:
: "ir" (val), "r" (aux));
}
/**
* @fn void arc_brk(void)
* @brief Call brk instruction
* stop the core through a brk instruction
*/
Inline void arc_brk(void)
{
Asm("brk");
}
/**
* @fn void arc_sync(void)
* @brief Call sync instruction
*
*/
Inline void arc_sync(void)
{
Asm("sync");
}
/**
* @fn void arc_kflag(uint32_t flag)
* @brief Call kflag instruction to change status32
*
* @param flag Flag to set in status32
*/
Inline void arc_kflag(uint32_t flag)
{
/*sr cannot write AUX_STATUS32 */
Asm("kflag %0" ::"ir" (flag));
}
/**
* @fn void arc_nop(void)
* @brief Call nop_s function
* flush the pipeline by nop_s instruction
*/
Inline void arc_nop(void)
{
Asm("nop_s");
}
/**
* @fn uint32_t arc_clri(void)
* @brief Call clri instruction
* call a clri instruction to disable interrupt
* @return interrupt related bits in status32
*/
Inline uint32_t arc_clri(void)
{
uint32_t v;
Asm("clri %0" : "=r" (v):: "memory");
return v;
}
/**
* @fn void arc_seti(uint32_t key)
* @brief Call seti instruction
* call a set instruction to change interrupt status
* @param key interrupt status
*/
Inline void arc_seti(uint32_t key)
{
Asm("seti %0" : : "ir" (key) : "memory");
}
/**
* @fn uint32_t arc_swap32(uint32_t val)
* @brief Swap bytes order of a 32-bits value
*
* @param val Target value
* @return Swapped value
*/
Inline uint32_t arc_swap32(uint32_t val)
{
uint32_t v;
Asm("swape %0, %1" : "=r" (v) : "r" (val));
return v;
}
/**
* @fn uint16_t arc_swap16(uint32_t val)
* @brief Swap bytes order of a 32-bits value and return high 16-bits
*
* @param val Target value
* @return High 16 bits of the swapped value
*/
Inline uint16_t arc_swap16(uint32_t val)
{
uint32_t temp;
uint32_t v;
Asm("swape %0, %1" : "=r" (temp) : "r" (val));
Asm("lsr16 %0, %1" : "=r" (v) : "r" (temp));
return (uint16_t)v;
}
/**
* @name cache related helper function
* @{
*/
/**
* @fn arc_read_uncached_32(void *ptr)
* @brief Read memory and bypass the cache
* @param ptr Memory address
* @return data in the memory
*/
Inline uint32_t arc_read_uncached_32(void *ptr)
{
uint32_t ret;
Asm("ld.di %0, [%1]" : "=r" (ret) : "r" (ptr));
return ret;
}
/**
* @fn arc_write_uncached_32(void *ptr, uint32_t data)
* @brief Write memory and bypass the cache
* @param ptr memory address
* @param data value to be written
*/
Inline void arc_write_uncached_32(void *ptr, uint32_t data)
{
Asm("st.di %0, [%1]" :: "r" (data), "r" (ptr));
}
/**
* @fn arc_read_cached_32(void *ptr)
* @brief Read memory with cache
* @param ptr Memory address
* @returns data in the memory
*/
Inline uint32_t arc_read_cached_32(void *ptr)
{
uint32_t ret;
Asm("ld %0, [%1]" : "=r" (ret) : "r" (ptr));
return ret;
}
/**
* @fn void arc_write_cached_32(void *ptr, uint32_t data)
* @brief Read memory with cache
* @param ptr Memory address
* @param data Data to be written
*/
Inline void arc_write_cached_32(void *ptr, uint32_t data)
{
Asm("st %0, [%1]" :: "r" (data), "r" (ptr));
}
/**
* @fn int32_t arc_goto_main(int32_t argc, char **argv)
* @brief Go to main function with proper arguments
* @param argc Argument count
* @param argv Argument content array
* @retval Return value of main function
*/
Inline int32_t arc_goto_main(int32_t argc, char **argv)
{
int32_t ret;
Asm(
"mov %%r0, %1\n"
"mov %%r1, %2\n"
"push_s %%blink\n"
"jl main\n"
"pop_s %%blink\n"
"mov %0, %%r0"
: "=r" (ret) : "r" (argc), "r" (argv));
return (int32_t)ret;
}
/**
* @fn uint32_t arc_find_msb(uint32_t val)
* @brief Find most significant bit set in a 32-bit word
*
* This routine finds the first bit set starting from the most significant bit
* in the argument passed in and returns the index of that bit. Bits are
* numbered starting at 1 from the least significant bit. A return value of
* zero indicates that the value passed is zero.
*
* @return Most significant bit set, 0 if @a val is 0
*/
Inline uint32_t arc_find_msb(uint32_t val)
{
uint32_t bit;
Asm(
/* BITSCAN_OPTION is required */
"fls.f %0, %1;\n"
"add.nz %0, %0, 1;\n"
: "=r" (bit)
: "r" (val));
return bit;
}
/**
* @fn uint32_t arc_find_lsb(uint32_t val)
* @brief Find least significant bit set in a 32-bit word
*
* This routine finds the first bit set starting from the least significant bit
* in the argument passed in and returns the index of that bit. Bits are
* numbered starting at 1 from the least significant bit. A return value of
* zero indicates that the value passed is zero.
*
* @return Least significant bit set, 0 if @a val is 0
*/
Inline uint32_t arc_find_lsb(uint32_t val)
{
uint32_t bit;
Asm(
/* BITSCAN_OPTION is required */
"ffs.f %0, %1;\n"
"add.nz %0, %0, 1;\n"
"mov.z %0, 0;\n"
: "=&r" (bit)
: "r" (val));
return bit;
}
/**
* @fn uint32_t arc_core_id(void)
* @brief Read core id
*
* @return Core id
*/
Inline uint32_t arc_core_id(void)
{
uint32_t ret;
Asm(
"lr %0, [%1]\n"
"xbfu %0, %0, 0xe8\n"
: "=r" (ret)
: "i" (AUX_IDENTITY));
return ret;
}
/**
* @fn void arc_stack_check_enable(void)
* @brief Enable hardware stack checking
*/
Inline void arc_stack_check_enable(void)
{
#if ARC_FEATURE_SEC_PRESENT
Asm(
"bset %0, %0, %1\n"
"sflag r0\n"
:
: "r" (arc_aux_read(AUX_SEC_STAT)), "i" (AUX_SEC_STAT_BIT_SSC));
#else
Asm(
"bset %0, %0, %1\n"
"kflag r0\n"
:
: "r" (arc_aux_read(AUX_STATUS32)), "i" (AUX_STATUS_BIT_SC));
#endif
}
/**
* @fn void arc_stack_check_disable(void)
* @brief Disable hardware stack checking
*/
Inline void arc_stack_check_disable(void)
{
#if ARC_FEATURE_SEC_PRESENT
Asm(
"bclr %0, %0, %1\n"
"sflag r0\n"
:
: "r" (arc_aux_read(AUX_SEC_STAT)), "i" (AUX_SEC_STAT_BIT_SSC));
#else
Asm(
"bclr %0, %0, %1\n"
"kflag r0\n"
:
: "r" (arc_aux_read(AUX_STATUS32)), "i" (AUX_STATUS_BIT_SC));
#endif
}
/**
* @fn void arc_kernel_stack_check_configure(uint32_t top, uint32_t base)
* @brief Configure stack checking in kernel mode
*
* @param top Top of stack
* @param base Base of stack
*/
Inline void arc_kernel_stack_check_configure(uint32_t top, uint32_t base)
{
#if ARC_FEATURE_SEC_PRESENT
arc_aux_write(AUX_S_KSTACK_TOP, top);
arc_aux_write(AUX_S_KSTACK_BASE, base);
#else
arc_aux_write(AUX_KSTACK_TOP, top);
arc_aux_write(AUX_KSTACK_BASE, base);
#endif
}
/**
* @fn uint32_t arc_is_user_mode(void)
* @brief Check whether processor is in user mode
* this function relies on AUX_STATUS_BIT_US set in privileged mode first
* @return 1 user mode, 0 privileged mode
*/
Inline uint32_t arc_is_user_mode(void)
{
uint32_t status;
Asm(
"lr %0, [%1]\n"
: "=r" (status)
: "i" (AUX_STATUS32)
: "memory");
return !(status & AUX_STATUS_MASK_US) ? 1 : 0;
}
/**
* @brief Go to user mode
* It's suggested to disable interrupt before call this function especially
* when using current stack, i.e., sp == 0. Because interrupt handling requires
* kernel mode stack which is different with user mode stack.
* @param target Target address to run in user mode, 0 means next
* line of code
* @param sp Stack where the target address runs, 0 means using
* current stack
*/
extern void arc_goto_usermode(void *target, uint32_t *sp);
/**
* @brief Go to kernel mode
* this function uses trap exception to do switch from user mode to kernel mode,
* please install exc_entry_arc_goto_kernelmode for trap exception before call this
* function
* @param target Target address to run in kernel mode, 0 means next line of code
* @param sp Stack where the target address runs, 0 means using current stack
*/
extern void arc_goto_kernelmode(void *target, uint32_t *sp);
/**
* @brief Trap exception entry used for arc_goto_kernelmode
*
* install this entry for trap exception before call arc_goto_kernelmode
*/
extern void exc_entry_arc_goto_kernelmode(void);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
/** @} */
#endif /* H_ARC_BUILTIN */
/** @} */

View File

@@ -1,331 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_CACHE
* @brief Header file of cache module
*/
#ifndef H_ARC_CACHE
#define H_ARC_CACHE
#include "arc/arc_builtin.h"
#include "arc/arc_exception.h"
/**
* @addtogroup ARC_HAL_MISC_CACHE
* @{
*/
/**
* @name Marco definitions for cache control
* @todo These definitions will be reviewed.
* @{
*/
#define IC_CTRL_IC_ENABLE (0x0) /*!< enable instruction cache */
#define IC_CTRL_IC_DISABLE (0x1) /*!< disable instruction cache */
#define IC_CTRL_DIRECT_ACCESS (0x0) /*!< direct access mode */
#define IC_CTRL_INDIRECT_ACCESS (0x20) /*!< indirect access mode */
#define IC_CTRL_OP_SUCCEEDED (0x8) /*!< instruction cache operation succeeded */
/** @} */
/**
* @name Marco definitions for data cache control
* @todo These definition will be reviewed.
* @{
*/
#define IC_CTRL_I
#define DC_CTRL_DC_ENABLE (0x0) /*!< enable data cache */
#define DC_CTRL_DC_DISABLE (0x1) /*!< disable data cache */
#define DC_CTRL_INVALID_ONLY (0x0) /*!< invalid data cache only */
#define DC_CTRL_INVALID_FLUSH (0x40) /*!< invalid and flush data cache */
#define DC_CTRL_ENABLE_FLUSH_LOCKED (0x80) /*!< the locked data cache can be flushed */
#define DC_CTRL_DISABLE_FLUSH_LOCKED (0x0) /*!< the locked data cache cannot be flushed */
#define DC_CTRL_FLUSH_STATUS (0x100) /*!< flush status */
#define DC_CTRL_DIRECT_ACCESS (0x0) /*!< direct access mode */
#define DC_CTRL_INDIRECT_ACCESS (0x20) /*!< indirect access mode */
#define DC_CTRL_OP_SUCCEEDED (0x4) /*!< data cache operation succeeded */
/** @} */
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name instruction cache related inline function
* @{
*/
/**
* @fn uint32_t icache_available(void)
* @brief Check whether instruction cache is available,
* @return 0 for not available, >0 for available
*/
Inline uint32_t icache_available(void)
{
return (arc_aux_read(AUX_BCR_I_CACHE) & 0xF);
}
/**
* @fn void icache_enable(uint32_t icache_en_mask)
* @brief Enable instruction cache
* @param icache_en_mask operation mask
*/
Inline void icache_enable(uint32_t icache_en_mask)
{
if (!icache_available()) {
return;
}
arc_aux_write(AUX_IC_CTRL, icache_en_mask);
}
/**
* @fn void icache_disable(void)
* @brief Disable instruction cache
*/
Inline void icache_disable(void)
{
arc_aux_write(AUX_IC_CTRL, IC_CTRL_IC_DISABLE);
}
/**
* @fn void icache_invalidate(void)
* @brief Invalidate the entire instruction cache
*/
Inline void icache_invalidate(void)
{
/* invalidate the entire icache */
arc_aux_write(AUX_IC_IVIC, 0);
arc_nop();
arc_nop();
arc_nop();
}
/**
* @fn void icache_invalidate_line(uint32_t address)
* @brief Invalidate specific cache line
* @param address Memory address
*/
Inline void icache_invalidate_line(uint32_t address)
{
arc_aux_write(AUX_IC_IVIL, address);
/* the 3 nops are required by ARCv2 ISA */
arc_nop();
arc_nop();
arc_nop();
}
/**
* @fn int32_t icache_lock_line(uint32_t address)
* @brief Lock specific cache line
* @param address Memory address
* @return 0, succeeded, -1, failed
*/
Inline int32_t icache_lock_line(uint32_t address)
{
arc_aux_write(AUX_IC_LIL, address);
if (arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) {
return 0;
} else {
return -1;
}
}
/**
* @fn void icache_access_mode(uint32_t mode)
* @brief Set icache access mode
* @param mode access mode, 1: indirect access 0:direct access
*/
Inline void icache_access_mode(uint32_t mode)
{
if (mode) {
arc_aux_write(AUX_IC_CTRL, arc_aux_read(AUX_IC_CTRL) | IC_CTRL_INDIRECT_ACCESS);
} else {
arc_aux_write(AUX_IC_CTRL, arc_aux_read(AUX_IC_CTRL) & (~IC_CTRL_INDIRECT_ACCESS));
}
}
/** @} */
/**
* @name data cache related inline functions
* @{
*/
/**
* @fn uint32_t dcache_available(void)
* @brief Check whether data cache is available,
* 0 for not available, >0 for available
*/
Inline uint32_t dcache_available(void)
{
return (arc_aux_read(AUX_BCR_D_CACHE) & 0xF);
}
/**
* @fn void dcache_invalidate(void)
* @brief Invalidate the entire data cache
*/
Inline void dcache_invalidate(void)
{
uint32_t status;
status = cpu_lock_save();
arc_aux_write(AUX_DC_IVDC, 1);
/* wait for flush completion */
while (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) {
;
}
cpu_unlock_restore(status);
}
/**
* @fn void dcache_invalidate_line(uint32_t address)
* @brief Invalidate the specific cache line
* @param address Memory address
*/
Inline void dcache_invalidate_line(uint32_t address)
{
arc_aux_write(AUX_DC_IVDL, address);
arc_nop();
arc_nop();
arc_nop();
}
/**
* @fn void dcache_enable(uint32_t dcache_en_mask)
* @brief Enable data cache
* @param dcache_en_mask Operation mask
*/
Inline void dcache_enable(uint32_t dcache_en_mask)
{
arc_aux_write(AUX_DC_CTRL, dcache_en_mask);
}
/**
* @fn void dcache_disable(void)
* @brief Disable data cache
*/
Inline void dcache_disable(void)
{
arc_aux_write(AUX_DC_CTRL, DC_CTRL_DC_DISABLE);
}
/**
* @fn void dcache_flush(void)
* @brief Flush data cache
*/
Inline void dcache_flush(void)
{
uint32_t status;
status = cpu_lock_save();
arc_aux_write(AUX_DC_FLSH, 1);
/* wait for flush completion */
while (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) {
;
}
cpu_unlock_restore(status);
}
/**
* @fn void dcache_flush_line(uint32_t address)
* @brief Flush the specific data cache line
* @param address Memory address
*/
Inline void dcache_flush_line(uint32_t address)
{
uint32_t status;
status = cpu_lock_save();
arc_aux_write(AUX_DC_FLDL, address);
while (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) {
;
}
cpu_unlock_restore(status);
}
/**
* @fn int32_t dcache_lock_line(uint32_t address)
* @brief Lock the specific data cache line
* @param address Memory address
* @return 0, succeeded, -1, failed
*/
Inline int32_t dcache_lock_line(uint32_t address)
{
arc_aux_write(AUX_DC_LDL, address);
if (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) {
return 0;
} else {
return -1;
}
}
/**
* @fn void dcache_access_mode(uint32_t mode)
* @brief Set dcache access mode
* @param mode Access mode, 1: indirect access 0:direct access
*/
Inline void dcache_access_mode(uint32_t mode)
{
if (mode) {
arc_aux_write(AUX_DC_CTRL, arc_aux_read(AUX_DC_CTRL) | DC_CTRL_INDIRECT_ACCESS);
} else {
arc_aux_write(AUX_DC_CTRL, arc_aux_read(AUX_DC_CTRL) & (~DC_CTRL_INDIRECT_ACCESS));
}
}
/** @} */
/**
* @name declarations of cache related functions
* @{
*/
extern int32_t icache_invalidate_mlines(uint32_t start_addr, uint32_t size);
extern int32_t icache_lock_mlines(uint32_t start_addr, uint32_t size);
extern int32_t icache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data);
extern int32_t icache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data);
extern int32_t icache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data);
extern int32_t dcache_invalidate_mlines(uint32_t start_addr, uint32_t size);
extern int32_t dcache_flush_mlines(uint32_t start_addr, uint32_t size);
extern int32_t dcache_lock_mlines(uint32_t start_addr, uint32_t size);
extern int32_t dcache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data);
extern int32_t dcache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data);
extern int32_t dcache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data);
extern void arc_cache_init(void);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
/** @} */
#endif /* H_ARC_CACHE */
/** @} end of group ARC_HAL_MISC_CACHE */

View File

@@ -1,250 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_ARC_CONNECT ARC_HAL
* @brief Header file of arc connect module
*/
#ifndef H_ARC_CONNECT
#define H_ARC_CONNECT
#include "arc/arc_builtin.h"
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ARC_CONNECT_CMD_CHECK_CORE_ID = 0x0,
ARC_CONNECT_CMD_INTRPT_GENERATE_IRQ = 0x1,
ARC_CONNECT_CMD_INTRPT_GENERATE_ACK = 0x2,
ARC_CONNECT_CMD_INTRPT_READ_STATUS = 0x3,
ARC_CONNECT_CMD_INTRPT_CHECK_SOURCE = 0x4,
ARC_CONNECT_CMD_SEMA_CLAIM_AND_READ = 0x11,
ARC_CONNECT_CMD_SEMA_RELEASE = 0x12,
ARC_CONNECT_CMD_SEMA_FORCE_RELEASE = 0x13,
ARC_CONNECT_CMD_MSG_SRAM_SET_ADDR = 0x21,
ARC_CONNECT_CMD_MSG_SRAM_READ_ADDR = 0x22,
ARC_CONNECT_CMD_MSG_SRAM_SET_ADDR_OFFSET = 0x23,
ARC_CONNECT_CMD_MSG_SRAM_READ_ADDR_OFFSET = 0x24,
ARC_CONNECT_CMD_MSG_SRAM_WRITE = 0x25,
ARC_CONNECT_CMD_MSG_SRAM_WRITE_INC = 0x26,
ARC_CONNECT_CMD_MSG_SRAM_WRITE_IMM = 0x27,
ARC_CONNECT_CMD_MSG_SRAM_READ = 0x28,
ARC_CONNECT_CMD_MSG_SRAM_READ_INC = 0x29,
ARC_CONNECT_CMD_MSG_SRAM_READ_IMM = 0x2a,
ARC_CONNECT_CMD_MSG_SRAM_SET_ECC_CTRL = 0x2b,
ARC_CONNECT_CMD_MSG_SRAM_READ_ECC_CTRL = 0x2c,
ARC_CONNECT_CMD_DEBUG_RESET = 0x31,
ARC_CONNECT_CMD_DEBUG_HALT = 0x32,
ARC_CONNECT_CMD_DEBUG_RUN = 0x33,
ARC_CONNECT_CMD_DEBUG_SET_MASK = 0x34,
ARC_CONNECT_CMD_DEBUG_READ_MASK = 0x35,
ARC_CONNECT_CMD_DEBUG_SET_SELECT = 0x36,
ARC_CONNECT_CMD_DEBUG_READ_SELECT = 0x37,
ARC_CONNECT_CMD_DEBUG_READ_EN = 0x38,
ARC_CONNECT_CMD_DEBUG_READ_CMD = 0x39,
ARC_CONNECT_CMD_DEBUG_READ_CORE = 0x3a,
ARC_CONNECT_CMD_GFRC_CLEAR = 0x41,
ARC_CONNECT_CMD_GFRC_READ_LO = 0x42,
ARC_CONNECT_CMD_GFRC_READ_HI = 0x43,
ARC_CONNECT_CMD_GFRC_ENABLE = 0x44,
ARC_CONNECT_CMD_GFRC_DISABLE = 0x45,
ARC_CONNECT_CMD_GFRC_READ_DISABLE = 0x46,
ARC_CONNECT_CMD_GFRC_SET_CORE = 0x47,
ARC_CONNECT_CMD_GFRC_READ_CORE = 0x48,
ARC_CONNECT_CMD_GFRC_READ_HALT = 0x49,
ARC_CONNECT_CMD_PDM_SET_PM = 0x81,
ARC_CONNECT_CMD_PDM_READ_PSTATUS = 0x82,
ARC_CONNECT_CMD_PMU_SET_PUCNT = 0x51,
ARC_CONNECT_CMD_PMU_READ_PUCNT = 0x52,
ARC_CONNECT_CMD_PMU_SET_RSTCNT = 0x53,
ARC_CONNECT_CMD_PMU_READ_RSTCNT = 0x54,
ARC_CONNECT_CMD_PMU_SET_PDCNT = 0x55,
ARC_CONNECT_CMD_PMU_READ_PDCNT = 0x56,
ARC_CONNECT_CMD_IDU_ENABLE = 0x71,
ARC_CONNECT_CMD_IDU_DISABLE = 0x72,
ARC_CONNECT_CMD_IDU_READ_ENABLE = 0x73,
ARC_CONNECT_CMD_IDU_SET_MODE = 0x74,
ARC_CONNECT_CMD_IDU_READ_MODE = 0x75,
ARC_CONNECT_CMD_IDU_SET_DEST = 0x76,
ARC_CONNECT_CMD_IDU_READ_DEST = 0x77,
ARC_CONNECT_CMD_IDU_GEN_CIRQ = 0x78,
ARC_CONNECT_CMD_IDU_ACK_CIRQ = 0x79,
ARC_CONNECT_CMD_IDU_CHECK_STATUS = 0x7a,
ARC_CONNECT_CMD_IDU_CHECK_SOURCE = 0x7b,
ARC_CONNECT_CMD_IDU_SET_MASK = 0x7c,
ARC_CONNECT_CMD_IDU_READ_MASK = 0x7d,
ARC_CONNECT_CMD_IDU_CHECK_FIRST = 0x7e
} ARC_CONNECT_CMD_T;
typedef enum {
ARC_CONNECT_CMD_TYPE_CMD_ONLY = 0x0,
ARC_CONNECT_CMD_TYPE_CMD_RETURN = 0x1,
ARC_CONNECT_CMD_TYPE_CMD_WDATA = 0x2,
ARC_CONNECT_CMD_TYPE_CMD_WDATA_RETURN = 0x3
} ARC_CONNECT_CMD_TYPE_T;
typedef struct {
ARC_CONNECT_CMD_T cmd;
ARC_CONNECT_CMD_TYPE_T type;
uint32_t param;
uint32_t wdata;
} ARC_CONNECT_OP_T;
#define ARC_CONNECT_INTRPT_TRIGGER_LEVEL 0
#define ARC_CONNECT_INTRPT_TRIGGER_EDGE 1
#define ARC_CONNECT_DISTRI_MODE_ROUND_ROBIN 0
#define ARC_CONNECT_DISTRI_MODE_FIRST_ACK 1
#define ARC_CONNECT_DISTRI_ALL_DEST 2
#define ARC_CONNECT_CORE_0 1
#define ARC_CONNECT_CORE_1 2
#define ARC_CONNECT_CORE_2 4
#define ARC_CONNECT_CORE_3 8
#define ARC_CONNECT_OP_SET(op, cmd_v, type_v, param_v, wdata_v) { \
(op)->cmd = (ARC_CONNECT_CMD_T)(cmd_v); \
(op)->type = (ARC_CONNECT_CMD_TYPE_T)(type_v); \
(op)->param = (uint32_t)(param_v); \
(op)->wdata = (uint32_t)(wdata_v); }
#define ARC_CONNECT_CMD_ONLY_OP_SET(op, cmd_v, param_v) { \
(op)->cmd = (ARC_CONNECT_CMD_T)(cmd_v); \
(op)->param = (uint32_t)(param_v); \
(op)->type = ARC_CONNECT_CMD_TYPE_CMD_ONLY; }
#define ARC_CONNECT_CMD_RETURN_OP_SET(op, cmd_v, param_v) { \
(op)->cmd = (ARC_CONNECT_CMD_T)(cmd_v); \
(op)->param = (uint32_t)(param_v); \
(op)->type = ARC_CONNECT_CMD_TYPE_CMD_RETURN; }
#define ARC_CONNECT_CMD_WDATA_OP_SET(op, cmd_v, param_v, wdata_v) \
ARC_CONNECT_OP_SET(op, cmd_v, ARC_CONNECT_CMD_TYPE_CMD_WDATA, param_v, wdata_v)
#define ARC_CONNECT_CMD_WDATA_RETURN_OP_SET(op, cmd_v, param_v, wdata_v) \
ARC_CONNECT_OP_SET(op, cmd_v, ARC_CONNECT_CMD_TYPE_CMD_WDATA_RETURN, param_v, wdata_v)
extern uint32_t arc_connect_check_core_id(void);
/* inter-core interrupt related functions */
extern void arc_connect_ici_generate(uint32_t core_id);
extern void arc_connect_ici_ack(uint32_t core_id);
extern uint32_t arc_connect_ici_read_status(uint32_t core_id);
extern uint32_t arc_connect_ici_check_src(void);
/* inter-core semaphore related functions */
extern uint32_t arc_connect_ics_take(uint32_t sem_id);
extern void arc_connect_ics_release(uint32_t sem_id);
extern void arc_connect_ics_force_release(uint32_t sem_id);
/* inter-core message related functions */
extern void arc_connect_icm_addr_set(uint32_t addr);
extern uint32_t arc_connect_icm_addr_read(void);
extern void arc_connect_icm_addr_offset_set(uint32_t offset);
extern uint32_t arc_connect_icm_addr_offset_read(void);
extern void arc_connect_icm_msg_write(uint32_t data);
extern void arc_connect_icm_msg_inc_write(uint32_t data);
extern void arc_connect_icm_msg_imm_write(uint32_t addr, uint32_t data);
extern uint32_t arc_connect_icm_msg_read(void);
extern uint32_t arc_connect_icm_msg_inc_read(void);
extern uint32_t arc_connect_icm_msg_imm_read(uint32_t addr);
extern void arc_connect_icm_ecc_ctrl_set(uint32_t val);
extern uint32_t arc_connect_icm_ecc_ctrl_read(void);
/* inter-core debug related functions */
extern void arc_connect_debug_reset(uint32_t cores);
extern void arc_connect_debug_halt(uint32_t cores);
extern void arc_connect_debug_run(uint32_t cores);
extern void arc_connect_debug_mask_set(uint32_t cores, uint32_t mask);
extern uint32_t arc_connect_debug_mask_read(uint32_t cores);
extern void arc_connect_debug_select_set(uint32_t cores);
extern uint32_t arc_connect_debug_select_read(void);
extern uint32_t arc_connect_debug_en_read(void);
extern uint32_t arc_connect_debug_cmd_read(void);
extern uint32_t arc_connect_debug_core_read(void);
/* global free-running counter(gfrc) related functions */
extern void arc_connect_gfrc_clear(void);
extern uint32_t arc_connect_gfrc_lo_read(void);
extern uint32_t arc_connect_gfrc_hi_read(void);
extern void arc_connect_gfrc_enable(void);
extern void arc_connect_gfrc_disable(void);
extern void arc_connect_gfrc_core_set(uint32_t cores);
extern uint32_t arc_connect_gfrc_halt_read(void);
extern uint32_t arc_connect_gfrc_core_read(void);
/* power domain management related functions */
extern void arc_connect_pdm_pm_set(uint32_t group, uint32_t cmd);
extern uint32_t arc_connect_pdm_pdstatus_read(uint32_t group);
/* power management unit related functions */
extern void arc_connect_pmu_pucnt_set(uint32_t cnt);
extern uint32_t arc_connect_pmu_pucnt_read(void);
extern void arc_connect_pmu_rstcnt_set(uint32_t cnt);
extern uint32_t arc_connect_pmu_rstcnt_read(void);
extern void arc_connect_pmu_pdccnt_set(uint32_t cnt);
extern uint32_t arc_connect_pmu_pdccnt_read(void);
/* interrupt distribute unit related functions */
extern void arc_connect_idu_enable(void);
extern void arc_connect_idu_disable(void);
extern uint32_t arc_connect_idu_read_enable(void);
extern void arc_connect_idu_set_mode(uint32_t irq_num, uint16_t trigger_mode, uint16_t distri_mode);
extern uint32_t arc_connect_idu_read_mode(uint32_t irq_num);
extern void arc_connect_idu_set_dest(uint32_t irq_num, uint32_t target_core);
extern uint32_t arc_connect_idu_read_dest(uint32_t irq_num);
extern void arc_connect_idu_gen_cirq(uint32_t irq_num);
extern void arc_connect_idu_ack_cirq(uint32_t irq_num);
extern uint32_t arc_connect_idu_check_status(uint32_t irq_num);
extern uint32_t arc_connect_idu_check_source(uint32_t irq_num);
extern void arc_connect_idu_set_mask(uint32_t irq_num, uint32_t mask);
extern uint32_t arc_connect_idu_read_mask(uint32_t irq_num);
extern uint32_t arc_connect_idu_check_first(uint32_t irq_num);
extern void arc_connect_idu_config_irq(uint32_t core, uint32_t irq_num, uint16_t trigger_mode, uint16_t distri_mode);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_CONNECT*/

View File

@@ -1,127 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_CORE_EM
* @brief Header file of EM series
*/
/**
* @addtogroup ARC_HAL_CORE_EM
* @{
*/
#ifndef H_ARC_EM
#define H_ARC_EM
#include "arc/arc.h"
/**
* @name Address Generation Unit (AGU) related auxiliary register
* @{
*/
#define AUX_AGU_AP0 (0x5c0)
#define AUX_AGU_AP1 (0x5c1)
#define AUX_AGU_AP2 (0x5c2)
#define AUX_AGU_AP3 (0x5c3)
#define AUX_AGU_AP4 (0x5c4)
#define AUX_AGU_AP5 (0x5c5)
#define AUX_AGU_AP6 (0x5c6)
#define AUX_AGU_AP7 (0x5c7)
#define AUX_AGU_AP8 (0x5c8)
#define AUX_AGU_AP9 (0x5c9)
#define AUX_AGU_AP10 (0x5ca)
#define AUX_AGU_AP11 (0x5cb)
#define AUX_AGU_AP12 (0x5cc)
#define AUX_AGU_AP13 (0x5cd)
#define AUX_AGU_AP14 (0x5ce)
#define AUX_AGU_AP15 (0x5cf)
#define AUX_AGU_OS0 (0x5d0)
#define AUX_AGU_OS1 (0x5d1)
#define AUX_AGU_OS2 (0x5d2)
#define AUX_AGU_OS3 (0x5d3)
#define AUX_AGU_OS4 (0x5d4)
#define AUX_AGU_OS5 (0x5d5)
#define AUX_AGU_OS6 (0x5d6)
#define AUX_AGU_OS7 (0x5d7)
#define AUX_AGU_OS8 (0x5d8)
#define AUX_AGU_OS9 (0x5d9)
#define AUX_AGU_OS10 (0x5da)
#define AUX_AGU_OS11 (0x5db)
#define AUX_AGU_OS12 (0x5dc)
#define AUX_AGU_OS13 (0x5dd)
#define AUX_AGU_OS14 (0x5de)
#define AUX_AGU_OS15 (0x5df)
#define AUX_AGU_MOD0 (0x5e0)
#define AUX_AGU_MOD1 (0x5e1)
#define AUX_AGU_MOD2 (0x5e2)
#define AUX_AGU_MOD3 (0x5e3)
#define AUX_AGU_MOD4 (0x5e4)
#define AUX_AGU_MOD5 (0x5e5)
#define AUX_AGU_MOD6 (0x5e6)
#define AUX_AGU_MOD7 (0x5e7)
#define AUX_AGU_MOD8 (0x5e8)
#define AUX_AGU_MOD9 (0x5e9)
#define AUX_AGU_MOD10 (0x5ea)
#define AUX_AGU_MOD11 (0x5eb)
#define AUX_AGU_MOD12 (0x5ec)
#define AUX_AGU_MOD13 (0x5ed)
#define AUX_AGU_MOD14 (0x5ee)
#define AUX_AGU_MOD15 (0x5ef)
#define AUX_AGU_MOD16 (0x5f0)
#define AUX_AGU_MOD17 (0x5f1)
#define AUX_AGU_MOD18 (0x5f2)
#define AUX_AGU_MOD19 (0x5f3)
#define AUX_AGU_MOD20 (0x5f4)
#define AUX_AGU_MOD21 (0x5f5)
#define AUX_AGU_MOD22 (0x5f6)
#define AUX_AGU_MOD23 (0x5f7)
/** @} */
#define AUX_XCCM_BASE (0x5f8)
#define AUX_YCCM_BASE (0x5f9)
/** @todo Add em series specific definitions here */
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_EM */
/** @} */

View File

@@ -1,558 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT
* @brief Public interface for configuring interrupts and exceptions
*/
#ifndef H_ARC_EXCEPTION
#define H_ARC_EXCEPTION
#include "arc/arc_builtin.h"
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup ARC_HAL_EXCEPTION_CPU
* @{
*/
#ifndef NUM_EXC_CPU
/*!< number of CPU exceptions */
#define NUM_EXC_CPU 16
#endif
#ifndef NUM_EXC_INT
/*!< number of interrupt exceptions, defined in arc_feature_config.h */
#define NUM_EXC_INT 9
#endif
/*!< total number of exceptions */
#define NUM_EXC_ALL (NUM_EXC_CPU + NUM_EXC_INT)
#ifdef ARC_FEATURE_SEC_PRESENT
typedef struct {
uint32_t erbta;
uint32_t r30; /* r30 is useless, skipped? */
uint32_t ilink; /* r29 is useless, skipped?*/
/* r28 is sp, saved other place */
uint32_t fp; /* r27 */
uint32_t gp; /* r26 */
#if ARC_FEATURE_DSP || ARC_FEATURE_FPU || ARC_FEATURE_MPU_OPTION_NUM > 6
/* accl and acch, common for mpy_option >6 and fpu_fma option */
uint32_t r59;
uint32_t r58;
#endif
uint32_t r12;
uint32_t lp_end, lp_start, lp_count;
#if ARC_FEATURE_CODE_DENSITY
uint32_t ei, ldi, jli;
#endif
uint32_t r0, r1, r2, r3;
#ifndef ARC_FEATURE_RF16
uint32_t r4, r5, r6, r7, r8, r9;
#endif
uint32_t r10, r11;
uint32_t blink; /* r31 */
uint32_t ret;
uint32_t sec_stat;
uint32_t status32;
} EMBARC_PACKED INT_EXC_FRAME_T;
#else
typedef struct {
uint32_t erbta;
uint32_t r30; /* r30 is useless, skipped? */
uint32_t ilink; /* r29 is useless, skipped?*/
/* r28 is sp, saved other place */
uint32_t fp; /* r27 */
uint32_t gp; /* r26 */
#if ARC_FEATURE_DSP || ARC_FEATURE_FPU || ARC_FEATURE_MPU_OPTION_NUM > 6
/* accl and acch, common for mpy_option >6 and fpu_fma option */
uint32_t r59;
uint32_t r58;
#endif
uint32_t r12;
uint32_t r0, r1, r2, r3;
#ifndef ARC_FEATURE_RF16
uint32_t r4, r5, r6, r7, r8, r9;
#endif
uint32_t r10, r11;
uint32_t blink; /* r31 */
uint32_t lp_end, lp_start, lp_count;
#if ARC_FEATURE_CODE_DENSITY
uint32_t ei, ldi, jli;
#endif
uint32_t ret;
uint32_t status32;
} EMBARC_PACKED INT_EXC_FRAME_T;
#endif
typedef struct {
/* todo xy memory support */
#if ARC_FEATURE_DSP_COMPLEX
uint32_t dsp_fft_ctrl;
uint32_t dsp_bfly0;
#endif
uint32_t acc0_ghi;
uint32_t acc0_hi;
uint32_t acc0_glo;
uint32_t acc0_lo;
uint32_t dsp_ctrl;
} EMBARC_PACKED DSP_EXT_FRAME_T;
typedef struct {
#if ARC_FEATURE_FPU_DA
uint32_t dpfp2h;
uint32_t dpfp2l;
uint32_t dpfp1h;
uint32_t dpfp1l;
#endif
uint32_t fpu_status;
uint32_t fpu_ctrl;
} EMBARC_PACKED FPU_EXT_FRAME_T;
typedef struct {
#if ARC_FEATURE_FPU_DSP_CONTEXT
#if ARC_FEATURE_DSP
DSP_EXT_FRAME_T dsp_regs;
#endif
#if ARC_FEATURE_FPU
FPU_EXT_FRAME_T fpu_ext_regs;
#endif
#endif /* ARC_FEATURE_FPU_DSP_CONTEXT */
#if defined(ARC_ENABLE_EXTRA_CALLEE)
#if ARC_FEATURE_SEC_PRESENT
uint32_t secure_kernel_sp;
uint32_t kernel_sp;
#else
uint32_t user_sp;
#endif
#endif
#ifndef ARC_FEATURE_RF16
uint32_t r25;
uint32_t r24;
uint32_t r23;
uint32_t r22;
uint32_t r21;
uint32_t r20;
uint32_t r19;
uint32_t r18;
uint32_t r17;
uint32_t r16;
#endif
uint32_t r15;
uint32_t r14;
uint32_t r13;
} EMBARC_PACKED CALLEE_FRAME_T;
typedef struct {
CALLEE_FRAME_T callee_regs;
INT_EXC_FRAME_T exc_frame;
} EMBARC_PACKED PROCESSOR_FRAME_T;
#define ARC_PROCESSOR_FRAME_T_SIZE (sizeof(PROCESSOR_FRAME_T) / sizeof(uint32_t))
#define ARC_INT_EXC_FRAME_T_SIZE (sizeof(INT_EXC_FRAME_T) / sizeof(uint32_t))
#define ARC_CALLEE_FRAME_T_SIZE (sizeof(CALLEE_FRAME_T) / sizeof(uint32_t))
/**
* @fn void arc_vector_base_write(uint32_t vec_base)
* @brief Write exception vector base
*
* @param vec_base Target vector base
*/
Inline void arc_vector_base_write(uint32_t vec_base)
{
arc_aux_write(AUX_INT_VECT_BASE, vec_base);
}
/**
* @fn uint32_t arc_vector_base_read(void)
* @brief Read current exception vector base
*
* @return Exception vector base (uint32_t)
*/
Inline uint32_t arc_vector_base_read(void)
{
return arc_aux_read(AUX_INT_VECT_BASE);
}
/** @}*/
/**
* @addtogroup ARC_HAL_EXCEPTION_INTERRUPT
* @{
*/
#ifndef INT_PRI_MIN
#define INT_PRI_MIN (-2) /*!< the minimum interrupt priority */
#endif
#define INT_PRI_MAX (-1) /*!< the maximum interrupt priority */
/**
* @fn void arc_int_disable(const uint32_t intno)
* @brief Disable interrupt
*
* @param intno Interrupt number
*/
Inline void arc_int_disable(const uint32_t intno)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
arc_aux_write(AUX_IRQ_ENABLE, 0);
}
/**
* @fn void arc_int_enable(const uint32_t intno)
* @brief Enable interrupt
*
* @param intno Interrupt number
*/
Inline void arc_int_enable(const uint32_t intno)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
arc_aux_write(AUX_IRQ_ENABLE, 1);
}
/**
* @fn uint32_t arc_int_enabled(const uint32_t intno)
* @brief Check whether the specific interrupt is enabled
*
* @param intno Interrupt number
* @return 0 disabled, 1 enabled
*/
Inline uint32_t arc_int_enabled(const uint32_t intno)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
return arc_aux_read(AUX_IRQ_ENABLE);
}
/**
* @fn uint32_t arc_int_ipm_get(void)
* @brief Get interrupt priority masking threshold
*
* @return Interrupt priority masking threshold, negative num
*/
Inline uint32_t arc_int_ipm_get(void)
{
return ((arc_aux_read(AUX_STATUS32) >> 1) & 0x0f);
}
/**
* @fn void arc_int_ipm_set(uint32_t intpri)
* @brief Set interrupt priority masking threshold
*
* @param intpri Interrupt priority masking threshold, negative num
*/
Inline void arc_int_ipm_set(uint32_t intpri)
{
volatile uint32_t status;
status = arc_aux_read(AUX_STATUS32) & ~0x1e;
status = status | ((intpri << 1) & 0x1e);
arc_kflag(status);
}
/**
* @fn uint32_t arc_int_pri_get(const uint32_t intno)
* @brief Get current interrupt priority masking threshold
*
* @param intno Interrupt number
*/
Inline uint32_t arc_int_pri_get(const uint32_t intno)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
return arc_aux_read(AUX_IRQ_PRIORITY) & 0xf;
}
/**
* @fn void arc_int_pri_set(const uint32_t intno, uint32_t intpri)
* @brief Set interrupt priority
*
* @param intno Interrupt number
* @param intpri Interrupt priority
*/
Inline void arc_int_pri_set(const uint32_t intno, uint32_t intpri)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
arc_aux_write(AUX_IRQ_PRIORITY, intpri | (arc_aux_read(AUX_IRQ_PRIORITY) & 0xfffffff0));
}
/**
* @fn void arc_int_secure_set(const uint32_t intno, uint32_t secure)
* @brief Set interrupt secure or not secure
* @param intno Interrupt number
* @param secure 0 for normal, > 0 for secure
*/
Inline void arc_int_secure_set(const uint32_t intno, uint32_t secure)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
if (secure) {
arc_aux_write(AUX_IRQ_PRIORITY, arc_aux_read(AUX_IRQ_PRIORITY) |
(1 << AUX_IRQ_PRIORITY_BIT_S));
} else {
arc_aux_write(AUX_IRQ_PRIORITY, arc_aux_read(AUX_IRQ_PRIORITY) & 0xf);
}
}
/**
* @fn uint32_t arc_int_probe(const uint32_t intno)
* @brief Probe interrupt pending state
*
* @param intno Interrupt number
* @returns 1 pending, 0 no pending, -1 error
*/
Inline uint32_t arc_int_probe(const uint32_t intno)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
return arc_aux_read(AUX_IRQ_PENDING);
}
/**
* @fn void arc_int_sw_trigger(const uint32_t intno)
* @brief Trigger software interrupt
*
* @param intno Interrupt number
*/
Inline void arc_int_sw_trigger(const uint32_t intno)
{
arc_aux_write(AUX_IRQ_HINT, intno);
}
/**
* @fn void arc_int_level_config(const uint32_t intno, const uint32_t level)
* @brief Configure interrupt request mode.
*
* @param intno Interrupt number
* @param level 0-level triggered, 1-pluse triggered
*/
Inline void arc_int_level_config(const uint32_t intno, const uint32_t level)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
arc_aux_write(AUX_IRQ_TRIGGER, level);
}
/**
* @fn uint32_t arc_int_level_get(const uint32_t intno)
* @brief Get interrupt request mode
*
* @param intno Interrupt number
* @return 0-level triggered, 1-pluse triggered
*/
Inline uint32_t arc_int_level_get(const uint32_t intno)
{
arc_aux_write(AUX_IRQ_SELECT, intno);
return arc_aux_read(AUX_IRQ_TRIGGER) & 0x1;
}
/**
* @fn void arc_lock(void)
* @brief Lock cpu to disable interrupts
*/
Inline void arc_lock(void)
{
arc_clri();
}
/**
* @fn void arc_unlock(void)
* @brief Unlock cpu to enable interrupts
*/
Inline void arc_unlock(void)
{
arc_seti(0);
}
/**
* @fn uint32_t arc_locked(void)
* @brief Check if cpu is locked
*
* @return 1 locked, 0 unlocked
*/
Inline uint32_t arc_locked(void)
{
if (arc_aux_read(AUX_STATUS32) & AUX_STATUS_MASK_IE) {
return 0;
} else {
return 1;
}
}
/**
* @fn uint32_t arc_lock_save(void)
* @brief Lock cpu and return status
*
* @return CPU status
*/
Inline uint32_t arc_lock_save(void)
{
return arc_clri();
}
/**
* @fn void arc_unlock_restore(const uint32_t status)
* @brief Unlock cpu with the specific status
*
* @param status CPU status saved by cpu_lock_save
*/
Inline void arc_unlock_restore(const uint32_t status)
{
arc_seti(status);
}
/**
* @fn uint32_t arc_int_active(void)
* @brief Check if interrupt is active
*
* @return 1 active, 0 inactive
*/
Inline uint32_t arc_int_active(void)
{
if (arc_aux_read(AUX_IRQ_ACT) == 0) {
return 0;
} else {
return 1;
}
}
/** @}*/
/**
* @addtogroup ARC_HAL_EXCEPTION_CPU
* @{
*/
/**
* @typedef EXC_ENTRY_T
* @brief Data type for exception entry
*/
typedef void (*EXC_ENTRY_T) (void);
/**
* @typedef EXC_HANDLER_T
* @brief Data type for exception handler
*/
typedef void (*EXC_HANDLER_T) (void *exc_frame);
/** @}*/
/**
* @ingroup ARC_HAL_EXCEPTION_INTERRUPT
* @typedef INT_HANDLER_T
* @brief Data type for interrupt handler
*/
typedef void (*INT_HANDLER_T) (void *ptr);
extern EXC_ENTRY_T exc_entry_table[NUM_EXC_ALL];
extern EXC_HANDLER_T exc_int_handler_table[NUM_EXC_ALL];
/** @ingroup ARC_HAL_EXCEPTION_CPU
* @{
*/
/**
* @fn exc_entry_reset
* @brief Reset entry
*/
extern void exc_entry_reset(void);
/**
* @fn exc_entry_cpu
* @brief Default CPU exception entry
*/
extern void exc_entry_cpu(void);
/**
* @fn exc_entry_firq
* @brief Fast interrupt exception entry
*/
extern void exc_entry_firq(void);
/**
* @fn exc_entry_int
* @brief Interrupt exception entry
*/
extern void exc_entry_int(void);
/** @}*/
/* exception related apis */
extern void exc_int_init(void);
extern int32_t exc_entry_install(const uint32_t excno, EXC_ENTRY_T entry);
extern EXC_ENTRY_T exc_entry_get(const uint32_t excno);
extern int32_t exc_handler_install(const uint32_t excno, EXC_HANDLER_T handler);
extern EXC_HANDLER_T exc_handler_get(const uint32_t excno);
/* interrupt related apis */
extern int32_t int_disable(const uint32_t intno);
extern int32_t int_enable(const uint32_t intno);
extern int32_t int_enabled(const uint32_t intno);
extern int32_t int_ipm_get(void);
extern int32_t int_ipm_set(int32_t intpri);
extern int32_t int_pri_get(const uint32_t intno);
extern int32_t int_pri_set(const uint32_t intno, int32_t intpri);
extern int32_t int_probe(const uint32_t intno);
extern int32_t int_sw_trigger(const uint32_t intno);
extern int32_t int_level_config(const uint32_t intno, const uint32_t level);
extern int32_t int_level_get(const uint32_t intno);
extern void cpu_lock(void);
extern void cpu_unlock(void);
extern uint32_t cpu_lock_save(void);
extern void cpu_unlock_restore(const uint32_t status);
extern int32_t int_handler_install(const uint32_t intno, INT_HANDLER_T handler);
extern INT_HANDLER_T int_handler_get(const uint32_t intno);
extern int32_t int_secure_set(const uint32_t intno, uint32_t secure);
extern void arc_firq_stack_set(uint8_t *firq_sp);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_EXCEPTION*/

View File

@@ -1,470 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC
* @brief Header file for arc feature configuration
*/
/**
* @addtogroup ARC_HAL_MISC
* @{
*/
#ifndef H_ARC_FEATURE_CONFIG
#define H_ARC_FEATURE_CONFIG
#ifdef EMBARC_TCF_GENERATED
#include "core_config.h"
#endif
/** ARC baseline instruction set version number */
#if !defined(ARC_FEATURE_ISA_VER)
#if defined(core_config_cir_identity_arcver)
#define ARC_FEATURE_ISA_VER core_config_cir_identity_arcver
#else
#define ARC_FEATURE_ISA_VER 0x42
#endif
#endif
#define ARC_FEATURE_ARC_EM 0x4
#define ARC_FEATURE_ARC_HS 0x5
#if !defined(ARC_FEATURE_ARC_FAMILY)
#if defined(core_config_cir_identity_family)
#define ARC_FEATURE_ARC_FAMILY core_config_cir_identity_family
#else
#define ARC_FEATURE_ARC_FAMILY ARC_FEATURE_ARC_EM
#endif
#endif
#if !defined(ARC_FEATURE_ARC_CORE_VER)
#if defined(core_config_cir_identity_corever)
#define ARC_FEATURE_ARC_CORE_VER core_config_cir_identity_corever
#else
#define ARC_FEATURE_ARC_CORE_VER 2
#endif
#endif
/** ARC CPU Clock Frequency in Hz unit */
#if !defined(ARC_FEATURE_CPU_CLOCK_FREQ)
#if defined(core_config_clock_speed)
#define ARC_FEATURE_CPU_CLOCK_FREQ (core_config_clock_speed * 1000000)
#endif
#endif
/** ARC PC size */
#if !defined(ARC_FEATURE_PC_SIZE)
#if defined(core_config_pc_size)
#define ARC_FEATURE_PC_SIZE core_config_pc_size
#else
#define ARC_FEATURE_PC_SIZE 32
#endif
#endif
/** ARC LPC size */
#if !defined(ARC_FEATURE_LPC_SIZE)
#if defined(core_config_lpc_size)
#define ARC_FEATURE_LPC_SIZE core_config_lpc_size
#else
#define ARC_FEATURE_LPC_SIZE 32
#endif
#endif
/** ARC Addr size */
#if !defined(ARC_FEATURE_ADDR_SIZE)
#if defined(core_config_addr_size)
#define ARC_FEATURE_ADDR_SIZE core_config_addr_size
#else
#define ARC_FEATURE_ADDR_SIZE 32
#endif
#endif
/** ARC Endian/Byte Order */
#define ARC_FEATURE_LITTLE_ENDIAN 1234
#define ARC_FEATURE_BIG_ENDIAN 4321
#if !defined(ARC_FEATURE_BYTE_ORDER)
#if defined(core_config_bcr_isa_config_b)
#if core_config_bcr_isa_config_b == 0
#define ARC_FEATURE_BYTE_ORDER ARC_FEATURE_LITTLE_ENDIAN
#else
#define ARC_FEATURE_BYTE_ORDER ARC_FEATURE_BIG_ENDIAN
#endif
#else
#define ARC_FEATURE_BYTE_ORDER ARC_FEATURE_LITTLE_ENDIAN
#endif
#endif
/** Reduced register option, if enabled, ARC_FEATURE_RF16 will be defined */
#if !defined(ARC_FEATURE_RF16)
#if defined(core_config_bcr_rf_build_e) && core_config_bcr_rf_build_e == 1
#define ARC_FEATURE_RF16
#endif
#endif
/** Unaligned access option, if enabled, ARC_FEATURE_UNALIGNED will be defined */
#if !defined(ARC_FEATURE_UNALIGNED)
#if defined(core_config_unaligned) && core_config_unaligned == 1
#define ARC_FEATURE_UNALIGNED
#endif
#endif
/** Code density option, if enabled, ARC_FEATURE_CODE_DENSITY will be defined */
#if !defined(ARC_FEATURE_CODE_DENSITY)
#if defined(core_config_code_density) && core_config_code_density == 1
#define ARC_FEATURE_CODE_DENSITY 1
#else
#define ARC_FEATURE_CODE_DENSITY 0
#endif
#endif
/** The number of register file banks */
#if !defined(ARC_FEATURE_RGF_NUM_BANKS)
#if defined(core_config_rgf_num_banks)
#define ARC_FEATURE_RGF_NUM_BANKS core_config_rgf_num_banks
#else
#define ARC_FEATURE_RGF_NUM_BANKS 1
#endif
#endif
/** The number of registers replicated per register bank */
#if !defined(ARC_FEATURE_RGF_BANKED_REGS)
#if defined(core_config_rgf_banked_regs)
#define ARC_FEATURE_RGF_BANKED_REGS core_config_rgf_banked_regs
#endif
#endif
/** Interrupt unit presence */
#if !defined(ARC_FEATURE_INTERRUPTS_PRESENT)
#if defined(core_config_interrupts_present)
#define ARC_FEATURE_INTERRUPTS_PRESENT core_config_interrupts_present
#endif
#endif
/** FIRQ_OPTION configuration option, 1 for enabled, 0 for disabled */
#if !defined(ARC_FEATURE_FIRQ)
#if defined(core_config_bcr_irq_build_f)
#define ARC_FEATURE_FIRQ core_config_bcr_irq_build_f
#else
#define ARC_FEATURE_FIRQ 0
#endif
#endif
/** The number of interrupts */
#if !defined(NUM_EXC_INT)
#if defined(core_config_interrupts_number)
#define NUM_EXC_INT core_config_interrupts_number
#endif
#endif
/** The number of external interrupts */
#if !defined(NUM_EXC_EXT_INT)
#if defined(core_config_interrupts_externals)
#define NUM_EXC_EXT_INT core_config_interrupts_externals
#endif
#endif
/** The interrupt priority levels */
#if !defined(INT_PRI_MIN)
#if defined(core_config_interrupts_priorities)
#define INT_PRI_MIN (-core_config_interrupts_priorities)
#endif
#endif
/** Timer0 present or not */
#if !defined(ARC_FEATURE_TIMER0_PRESENT)
#if defined(core_config_timer0)
#define ARC_FEATURE_TIMER0_PRESENT core_config_timer0
#define ARC_FEATURE_TIMER0_LEVEL (core_config_timer0_level - core_config_interrupts_priorities)
#define ARC_FEATURE_TIMER0_VECTOR core_config_timer0_vector
#endif
#endif
/** Timer1 present or not */
#if !defined(ARC_FEATURE_TIMER1_PRESENT)
#if defined(core_config_timer1)
#define ARC_FEATURE_TIMER1_PRESENT core_config_timer1
#define ARC_FEATURE_TIMER1_LEVEL (core_config_timer1_level - core_config_interrupts_priorities)
#define ARC_FEATURE_TIMER1_VECTOR core_config_timer1_vector
#endif
#endif
/** Secure Timer0 present or not */
#if !defined(ARC_FEATURE_SEC_TIMER0_PRESENT)
#if defined(core_config_sec_timer0)
#define ARC_FEATURE_SEC_TIMER0_PRESENT core_config_sec_timer0
#define ARC_FEATURE_SEC_TIMER0_LEVEL (core_config_sec_timer0_level - core_config_interrupts_priorities)
#define ARC_FEATURE_SEC_TIMER0_VECTOR 20
#endif
#endif
/** Secure Timer1 present or not */
#if !defined(ARC_FEATURE_SEC_TIMER1_PRESENT)
#if defined(core_config_sec_timer1)
#define ARC_FEATURE_SEC_TIMER1_PRESENT core_config_sec_timer1
#define ARC_FEATURE_SEC_TIMER1_LEVEL (core_config_sec_timer1_level - core_config_interrupts_priorities)
#define ARC_FEATURE_SEC_TIMER1_VECTOR 21
#endif
#endif
/** 64bit RTC present or not */
#if !defined(ARC_FEATURE_RTC_PRESENT)
#if defined(core_config_rtc)
#define ARC_FEATURE_RTC_PRESENT core_config_rtc
#endif
#endif
/** ICCM Presence, base address and size */
#if !defined(ARC_FEATURE_ICCM_PRESENT)
#if defined(core_config_iccm_present) && core_config_iccm_present == 1
#define ARC_FEATURE_ICCM_PRESENT 1
#define ARC_FEATURE_ICCM_BASE core_config_iccm_base
#define ARC_FEATURE_ICCM_SIZE core_config_iccm_size
#endif
#endif
/** ICCM0 Presence, base address and size */
#if !defined(ARC_FEATURE_ICCM0_PRESENT)
#if defined(core_config_iccm0_present) && core_config_iccm0_present == 1
#define ARC_FEATURE_ICCM0_PRESENT 1
#define ARC_FEATURE_ICCM0_BASE core_config_iccm0_base
#define ARC_FEATURE_ICCM0_SIZE core_config_iccm0_size
#endif
#endif
/** ICCM1 Presence, base address and size */
#if !defined(ARC_FEATURE_ICCM1_PRESENT)
#if defined(core_config_iccm1_present) && core_config_iccm1_present == 1
#define ARC_FEATURE_ICCM1_PRESENT 1
#define ARC_FEATURE_ICCM1_BASE core_config_iccm1_base
#define ARC_FEATURE_ICCM1_SIZE core_config_iccm1_size
#endif
#endif
/** DCCM Presence, base address and size */
#if !defined(ARC_FEATURE_DCCM_PRESENT)
#if defined(core_config_dccm_present) && core_config_dccm_present == 1
#define ARC_FEATURE_DCCM_PRESENT 1
#define ARC_FEATURE_DCCM_BASE core_config_dccm_base
#define ARC_FEATURE_DCCM_SIZE core_config_dccm_size
#ifdef core_config_dccm_interleave
#define ARC_FEATURE_DCCM_INTERLEAVE core_config_dccm_interleave
#endif
#endif
#endif
/** ARC XY memory options */
#if !defined(ARC_FEATURE_XY_MEM)
#if defined(core_config_xy) && core_config_xy == 1
#define ARC_FEATURE_XY_MEM core_config_xy
#if defined(core_config_xy_x_base)
#define ARC_FEATURE_XCCM_PRESENT 1
#define ARC_FEATURE_XCCM_BASE core_config_xy_x_base
#define ARC_FEATURE_YCCM_SIZE core_config_xy_size
#endif
#if defined(core_config_xy_y_base)
#define ARC_FEATURE_YCCM_PRESENT 1
#define ARC_FEATURE_YCCM_BASE core_config_xy_y_base
#define ARC_FEATURE_YCCM_SIZE core_config_xy_size
#endif
#endif
#endif
/** Peripheral memory region(DMP) base address, if dmp configured, this macro will be defined as base address */
#if !defined(ARC_FEATURE_DMP_PERIPHERAL)
#if defined(core_config_cir_dmp_peripheral)
#define ARC_FEATURE_DMP_PERIPHERAL core_config_cir_dmp_peripheral
#endif
#endif
/** MPU options */
#if !defined(ARC_FEATURE_MPU_PRESENT)
#if defined(core_config_mpu_present) && core_config_mpu_present == 1
#define ARC_FEATURE_MPU_PRESENT 1
#define ARC_FEATURE_MPU_VERSION core_config_bcr_mpu_build_version
#define ARC_FEATURE_MPU_REGIONS core_config_mpu_regions
#ifdef core_config_bcr_mpu_build_i
#define ARC_FEATURE_MPU_BUILD_I core_config_bcr_mpu_build_i
#endif
#ifdef core_config_bcr_mpu_build_s
#define ARC_FEATURE_MPU_BUILD_S core_config_bcr_mpu_build_s
#endif
#endif
#endif
/** Secure BCR SEC_BUILD BCR */
#if !defined(ARC_FEATURE_SEC_PRESENT)
#if defined(core_config_bcr_sec_build)
#define ARC_FEATURE_SEC_PRESENT 1
#define ARC_FEATURE_SEC_VERSION core_config_bcr_sec_build_version
#define ARC_FEATURE_SEC_BUILD_DSM core_config_bcr_sec_build_dsm
#define ARC_FEATURE_SEC_BUILD_NSM core_config_bcr_sec_build_nsm
#define ARC_FEATURE_SEC_BUILD_I1SM core_config_bcr_sec_build_i1sm
#define ARC_FEATURE_SEC_BUILD_I0SM core_config_bcr_sec_build_i0sm
#define ARC_FEATURE_SEC_BUILD_S core_config_bcr_sec_build_s
#define ARC_FEATURE_SEC_BUILD_EI core_config_bcr_sec_build_ei
#define ARC_FEATURE_SEC_BUILD_ED core_config_bcr_sec_build_ed
#endif
#endif
#if !defined(ARC_FEATURE_SEC_MODES)
#if defined(core_config_sec_modes)
#define ARC_FEATURE_SEC_MODES core_config_sec_modes
#endif
#endif
/** Data Cache options */
#if !defined(ARC_FEATURE_DCACHE_PRESENT)
#if defined(core_config_dcache_present) && core_config_dcache_present == 1
#define ARC_FEATURE_DCACHE_PRESENT 1
#define ARC_FEATURE_DCACHE_BUILD core_config_bcr_d_cache_build
#define ARC_FEATURE_DCACHE_BUILD_VERSION core_config_bcr_d_cache_build_version
#define ARC_FEATURE_DCACHE_BUILD_ASSOC core_config_bcr_d_cache_build_assoc
#define ARC_FEATURE_DCACHE_BUILD_CAPACITY core_config_bcr_d_cache_build_capacity
#define ARC_FEATURE_DCACHE_BUILD_BSIZE core_config_bcr_d_cache_build_bsize
#define ARC_FEATURE_DCACHE_BUILD_FL core_config_bcr_d_cache_build_fl
#define ARC_FEATURE_DCACHE_BUILD_U core_config_bcr_d_cache_build_u
#define ARC_FEATURE_DCACHE_SIZE core_config_dcache_size
#define ARC_FEATURE_DCACHE_LINE_SIZE core_config_dcache_line_size
#define ARC_FEATURE_DCACHE_WAYS core_config_dcache_ways
#define ARC_FEATURE_DCACHE_FEATURE core_config_dcache_feature
#endif
#endif
/** Instruction Cache options */
#if !defined(ARC_FEATURE_ICACHE_PRESENT)
#if defined(core_config_icache_present) && core_config_icache_present == 1
#define ARC_FEATURE_ICACHE_PRESENT 1
#define ARC_FEATURE_ICACHE_BUILD core_config_bcr_i_cache_build
#define ARC_FEATURE_ICACHE_BUILD_VERSION core_config_bcr_i_cache_build_version
#define ARC_FEATURE_ICACHE_BUILD_ASSOC core_config_bcr_i_cache_build_assoc
#define ARC_FEATURE_ICACHE_BUILD_CAPACITY core_config_bcr_i_cache_build_capacity
#define ARC_FEATURE_ICACHE_BUILD_BSIZE core_config_bcr_i_cache_build_bsize
#define ARC_FEATURE_ICACHE_BUILD_FL core_config_bcr_i_cache_build_fl
#define ARC_FEATURE_ICACHE_BUILD_D core_config_bcr_i_cache_build_d
#define ARC_FEATURE_ICACHE_SIZE core_config_icache_size
#define ARC_FEATURE_ICACHE_LINE_SIZE core_config_icache_line_size
#define ARC_FEATURE_ICACHE_WAYS core_config_icache_ways
#define ARC_FEATURE_ICACHE_FEATURE core_config_icache_feature
#endif
#endif
/** ARC uDMA options */
#if !defined(ARC_FEATURE_DMAC)
#if defined(core_config_dmac)
#define ARC_FEATURE_DMAC core_config_dmac
#define CORE_DMAC_CHANNELS core_config_dmac_channels
#define CORE_DMAC_REGISTERS core_config_dmac_registers
#if core_config_bcr_dmac_build_int_cfg == 2 || core_config_bcr_dmac_build_int_cfg == 4
#define DMA_MULTI_IRQ 1
#else
#define DMA_MULTI_IRQ 0
#endif
#define ARC_FEATURE_DMAC_PRESENT core_config_dmac
#define ARC_FEATURE_DMAC_VERSION core_config_bcr_dmac_build_version
#define ARC_FEATURE_DMAC_CHANNELS core_config_dmac_channels
#define ARC_FEATURE_DMAC_REGISTERS core_config_dmac_registers
#define ARC_FEATURE_DMAC_INT_CFG core_config_bcr_dmac_build_int_cfg
#define ARC_FEATURE_DMAC_FIFO_DEPTH core_config_dmac_fifo_depth
#ifndef CORE_DMAC_INTERNAL_VERSION
#define CORE_DMAC_INTERNAL_VERSION ARC_FEATURE_DMAC_VERSION
#endif
#ifdef ARC_FEATURE_SEC_TIMER0_PRESENT
#define DMA_IRQ_NUM_START 22
#define ARC_FEATURE_DMAC_VECTOR_START 22
#else
#define DMA_IRQ_NUM_START 20
#define ARC_FEATURE_DMAC_VECTOR_START 20
#endif
#endif
#endif
/** ARC mpy option */
#if !defined(ARC_FEATURE_MPU_OPTION_NUM)
#define ARC_FEATURE_MPU_OPTION_NUM core_config_mpy_option_num
#endif
#if !defined(ARC_FEATURE_FPU_DSP_CONTEXT)
#define ARC_FEATURE_FPU_DSP_CONTEXT 1 /* whether to put FPU and DSP regs into the context */
#endif
/** ARC FPU options */
#if !defined(ARC_FEATURE_FPU)
#if core_config_bcr_fpu_build_sp || core_config_bcr_fpu_build_dp
#define ARC_FEATURE_FPU 1
#if core_config_bcr_fpu_build_da
#define ARC_FEATURE_FPU_DA 1
#endif
#endif
#endif
/** ARC DSP options */
#if !defined(ARC_FEATURE_DSP)
#if core_config_dsp1 || core_config_dsp2
#define ARC_FEATURE_DSP 1
#if core_config_dsp_complex
#define ARC_FEATURE_DSP_COMPLEX 1
#endif
#endif
#endif
/** ARC Stack check options */
#if !defined(ARC_FEATURE_STACK_CHECK)
#if core_config_stack_check
#define ARC_FEATURE_STACK_CHECK 1
#endif
#endif
/* ARC multi processors/cores related features */
#if !defined(ARC_FEATURE_MP_NUM_CPUS)
#define ARC_FEATURE_MP_NUM_CPUS 1
#endif
#if !defined(ARC_FEATURE_CONNECT_PRESENT)
#if defined(core_config_connect_idu) && core_config_connect_idu > 1
#define ARC_FEATURE_CONNECT_PRESENT 1
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* H_ARC_FEATURE_CONFIG */
/** @} */

View File

@@ -1,121 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_CORE_HS
* @brief header file of HS series
*/
/**
* @addtogroup ARC_HAL_CORE_HS
* @{
*/
#ifndef H_ARC_HS
#define H_ARC_HS
#include "arc/arc.h"
#define AUX_TLBPD0 (0x460)
#define AUX_TLBPD1 (0x461)
#define AUX_TLBPD1_HL (0x463)
#define AUX_TLBINDEX (0x464)
#define AUX_TLBCOMMAND (0x465)
#define AUX_PID (0x468)
#define AUX_SASID0 (0x46a)
#define AUX_SASID1 (0x46b)
#define AUX_SCRATCH_DATA0 (0x46c)
#define AUX_BPU_FLUSH (0x480)
#define AUX_BPU_CTRL (0x481)
#define AUX_IO_COH_ENABLE (0x500)
#define AUX_IO_COH_PARTIAL (0x501)
#define AUX_IO_COH_AP0_BASE (0x508)
#define AUX_IO_COH_AP0_SIZE (0x509)
#define AUX_IO_CACHE_ENABLE (0x520)
#define AUX_IO_CACHE_AP0_BASE (0x528)
#define AUX_IO_CACHE_AP0_SIZE (0x529)
#define AUX_SLC_AUX_CACHE_CONFIG (0x901)
#define AUX_SLC_AUX_CACHE_CTRL (0x903)
#define AUX_SLC_AUX_CACHE_FLUSH (0x904)
#define AUX_SLC_AUX_CACHE_INV (0x905)
#define AUX_SLC_AUX_CACHE_LOCK0 (0x906)
#define AUX_SLC_AUX_CACHE_LOCK1 (0x907)
#define AUX_SLC_AUX_CACHE_LOCK2 (0x908)
#define AUX_SLC_AUX_CACHE_LOCK3 (0x909)
#define AUX_SLC_AUX_CACHE_LOCK4 (0x90a)
#define AUX_SLC_AUX_CACHE_LOCK5 (0x90b)
#define AUX_SLC_AUX_CACHE_LOCK6 (0x90c)
#define AUX_SLC_AUX_CACHE_LOCK7 (0x90d)
#define AUX_SLC_AUX_LINE_LOCK (0x90e)
#define AUX_SLC_AUX_LINE_LOCK1 (0x90f)
#define AUX_SLC_AUX_LINE_INV (0x910)
#define AUX_SLC_AUX_LINE_INV1 (0x911)
#define AUX_SLC_AUX_LINE_FLUSH (0x912)
#define AUX_SLC_AUX_LINE_FLUSH1 (0x913)
#define AUX_SLC_AUX_RGN_START (0x914)
#define AUX_SLC_AUX_RGN_START1 (0x915)
#define AUX_SLC_AUX_RGN_END (0x916)
#define AUX_SLC_AUX_RGN_END1 (0x917)
#define AUX_SLC_AUX_LINE_ADDR (0x918)
#define AUX_SLC_AUX_LINE_ADDR1 (0x919)
#define AUX_SLC_AUX_DIRECT_IDX (0x91a)
#define AUX_SLC_AUX_TAG_DATA (0x91b)
#define AUX_SLC_AUX_TAG_DATA1 (0x91c)
#define AUX_SLC_AUX_STATUS_DATA (0x91d)
#define AUX_SLC_AUX_DATA0 (0x91f)
#define AUX_SLC_AUX_DATA1 (0x920)
#define AUX_SLC_AUX_DATA2 (0x921)
#define AUX_SLC_AUX_DATA3 (0x922)
#define AUX_SLC_AUX_FAULT_ADDR (0x923)
#define AUX_SLC_AUX_FAULT_ADDR1 (0x924)
#define AUX_SLC_AUX_FAULT_STAT (0x925)
#define AUX_SLC_AUX_PM_CMD (0x926)
#define AUX_SLC_AUX_PM_EVENT (0x927)
#define AUX_SLC_AUX_PM_OVF (0x928)
#define AUX_SLC_AUX_PM_CNT0 (0x929)
#define AUX_SLC_AUX_PM_CNT1 (0x92a)
/** @todo add hs series specific definitions here */
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_HS */
/** @}*/

View File

@@ -1,154 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2019, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_ARC_MP
#define H_ARC_MP
/* ARC multi processors/cores related functions */
#include "arc/arc_builtin.h"
#ifndef INTNO_ICI
#define INTNO_ICI 19 /* inter-core interrupt intno */
#endif
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
/* smp barrier */
#define arc_smp_mb() arc_mb()
typedef struct {
volatile uint32_t slock;
} ARC_SPINLOCK_T;
#define ARC_SPIN_LOCK_LOCKED 1
#define ARC_SPIN_LOCK_UNLOCKED 0
/**
* @fn void arc_spinlock_get(ARC_SPINLOCK_T *lock)
* @brief Get a spin lock
*
* @param lock Spin lock to get
*/
Inline void arc_spinlock_get(ARC_SPINLOCK_T *lock)
{
#if ARC_FEATURE_ARC_FAMILY == ARC_FEATURE_ARC_HS
uint32_t val;
arc_smp_mb();
Asm(
"1: llock %[val], [%[slock]] \n"
" breq %[val], %[LOCKED], 1b \n" /* spin while LOCKED */
" scond %[LOCKED], [%[slock]] \n" /* acquire */
" bnz 1b \n"
" \n"
:[val] "=&r" (val)
:[slock] "r" (&(lock->slock)),
[LOCKED] "r" (ARC_SPIN_LOCK_LOCKED)
: "memory", "cc");
arc_smp_mb();
#else
lock->slock = arc_clri();
#endif
}
/**
* @fn int32_t arc_spinlock_try(ARC_SPINLOCK_T *lock)
* @brief Try to get a spinlock
*
* @param lock Spin lock to get
* @return 0 failed, 1 success
*/
Inline int32_t arc_spinlock_try(ARC_SPINLOCK_T *lock)
{
#if ARC_FEATURE_ARC_FAMILY == ARC_FEATURE_ARC_HS
uint32_t val, got_it = 0;
arc_smp_mb();
Asm(
"1: llock %[val], [%[slock]] \n"
" breq %[val], %[LOCKED], 4f \n" /* already LOCKED, just bail */
" scond %[LOCKED], [%[slock]] \n" /* acquire */
" bnz 1b \n"
" mov %[got_it], 1 \n"
"4: \n"
" \n"
:[val] "=&r" (val), [got_it] "+&r" (got_it)
:[slock] "r" (&(lock->slock)),
[LOCKED] "r" (ARC_SPIN_LOCK_LOCKED)
: "memory", "cc");
arc_smp_mb();
return got_it;
#else
lock->slock = arc_clri();
return 1;
#endif
}
/**
* @fn void arc_spinlock_release(ARC_SPINLOCK_T *lock)
* @brief release a spin lock
*
* @param lock Spin lock to release
*/
Inline void arc_spinlock_release(ARC_SPINLOCK_T *lock)
{
#if ARC_FEATURE_ARC_FAMILY == ARC_FEATURE_ARC_HS
arc_smp_mb();
lock->slock = ARC_SPIN_LOCK_UNLOCKED;
arc_smp_mb();
#else
arc_seti(lock->slock);
#endif
}
/* variables required by start up of multi-core */
extern volatile uint32_t arc_cpu_wake_flag;
extern volatile uint8_t *arc_cpu_sp;
extern void arc_start_slave_cpu(uint32_t cpu_num, uint8_t *stack, uint32_t sz,
void (*fn)(uint32_t, void *), void *arg);
extern void arc_slave_start(uint32_t cpu_num);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_MP */

View File

@@ -1,172 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MPU
* @brief Header file of mpu module
*/
#ifndef H_ARC_MPU
#define H_ARC_MPU
#include "arc/arc_builtin.h"
/**
* @addtogroup ARC_HAL_MISC_MPU
* @{
*/
#ifndef ARC_FEATURE_MPU_VERSION
#define ARC_FEATURE_MPU_VERSION 2
#endif
#ifndef ARC_FEATURE_MPU_REGIONS
#define ARC_FEATURE_MPU_REGIONS arc_mpu_regions()
#endif
#define AUX_MPU_VALID_MASK (0x1)
#define AUX_MPU_EN_ENABLE (0x40000000)
#define AUX_MPU_EN_DISABLE (0xBFFFFFFF)
#define AUX_MPU_RDP_REGION_SIZE(bits) \
(((bits - 1) & 0x3) | (((bits - 1) & 0x1C) << 7))
#if ARC_FEATURE_MPU_VERSION == 2
#define AUX_MPU_ATTR_MASK (0xFFB)
#elif ARC_FEATURE_MPU_VERSION == 4
#define AUX_MPU_ATTR_MASK (0xFF81F9)
#else
#define AUX_MPU_ATTR_MASK (0xFFFFFFFF)
#endif
#define AUX_MPU_ATTR_UE 0x008 /* allow user execution */
#define AUX_MPU_ATTR_UW 0x010 /* allow user write */
#define AUX_MPU_ATTR_UR 0x020 /* allow user read */
#define AUX_MPU_ATTR_KE 0x040 /* only allow kernel execution */
#define AUX_MPU_ATTR_KW 0x080 /* only allow kernel write */
#define AUX_MPU_ATTR_KR 0x100 /* only allow kernel read */
#define AUX_MPU_ATTR_S 0x8000 /* secure */
#define AUX_MPU_ATTR_N 0x0000 /* normal */
#define AUX_MPU_ATTR_SID_OFFSET 16
#define AUX_MPU_ATTR_SID_MASK (0xFF << AUX_MPU_ATTR_SID_OFFSET)
#define AUX_MPU_ATTR_SID(x) (x << AUX_MPU_ATTR_SID_OFFSET)
#define AUX_MPU_INDEX_DEFAULT 0x80000000
#define AUX_MPU_INDEX_MULT 0x40000000
#if ARC_FEATURE_MPU_VERSION == 2
#define ARC_FEATURE_MPU_ALIGNMENT_BITS 11
#elif ARC_FEATURE_MPU_VERSION == 4
#define ARC_FEATURE_MPU_ALIGNMENT_BITS 5
#endif
/* derived region alignment settings */
#define ARC_FEATURE_MPU_ALIGNMENT (1UL << ARC_FEATURE_MPU_ALIGNMENT_BITS)
#define ARC_FEATURE_MPU_ALIGNMENT_MASK (ARC_FEATURE_MPU_ALIGNMENT - 1)
/* Some helper defines for common regions */
#define ARC_MPU_REGION_RAM_ATTR \
(AUX_MPU_ATTR_UW | AUX_MPU_ATTR_UR | \
AUX_MPU_ATTR_KW | AUX_MPU_ATTR_KR)
#define ARC_MPU_REGION_FLASH_ATTR \
(AUX_MPU_ATTR_UE | AUX_MPU_ATTR_UR | \
AUX_MPU_ATTR_KE | AUX_MPU_ATTR_KR)
#define ARC_MPU_REGION_IO_ATTR \
(AUX_MPU_ATTR_UW | AUX_MPU_ATTR_UR | \
AUX_MPU_ATTR_KW | AUX_MPU_ATTR_KR)
#define ARC_MPU_REGION_ALL_ATTR \
(AUX_MPU_ATTR_UW | AUX_MPU_ATTR_UR | \
AUX_MPU_ATTR_KW | AUX_MPU_ATTR_KR | \
AUX_MPU_ATTR_KE | AUX_MPU_ATTR_UE)
#define REGION_32B (0x200)
#define REGION_64B (0x201)
#define REGION_128B (0x202)
#define REGION_256B (0x203)
#define REGION_512B (0x400)
#define REGION_1K (0x401)
#define REGION_2K (0x402)
#define REGION_4K (0x403)
#define REGION_8K (0x600)
#define REGION_16K (0x601)
#define REGION_32K (0x602)
#define REGION_64K (0x603)
#define REGION_128K (0x800)
#define REGION_256K (0x801)
#define REGION_512K (0x802)
#define REGION_1M (0x803)
#define REGION_2M (0xA00)
#define REGION_4M (0xA01)
#define REGION_8M (0xA02)
#define REGION_16M (0xA03)
#define REGION_32M (0xC00)
#define REGION_64M (0xC01)
#define REGION_128M (0xC02)
#define REGION_256M (0xC03)
#define REGION_512M (0xE00)
#define REGION_1G (0xE01)
#define REGION_2G (0xE02)
#define REGION_4G (0xE03)
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @fn uint8_t arc_mpu_regions(void)
*/
Inline uint8_t arc_mpu_regions(void)
{
uint32_t num = arc_aux_read(AUX_BCR_MPU);
num = (num & 0xFF00) >> 8;
return (uint8_t)num;
}
extern void arc_mpu_enable(void);
extern void arc_mpu_disable(void);
extern void arc_mpu_region_config(uint32_t index, uint32_t base, uint32_t size, uint32_t region_attr);
extern void arc_mpu_default(uint32_t region_attr);
extern int32_t arc_mpu_in_region(uint32_t index, uint32_t start, uint32_t size);
extern int32_t arc_mpu_probe(uint32_t addr);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_MPU */
/** @} end of group ARC_HAL_MISC_MPU */

View File

@@ -1,125 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_TIMER
* @brief header file of ARC internal timer
*/
/**
* @addtogroup ARC_HAL_MISC_TIMER
* @{
*/
#ifndef H_ARC_TIMER
#define H_ARC_TIMER
#include "arc/arc_builtin.h"
/**
* @name arc internal timers names
* @{
*/
#define TIMER_0 0 /*!< macro name for arc internal timer 0 */
#define TIMER_1 1 /*!< macro name for arc internal timer 1 */
#define TIMER_RTC 2 /*!< macro name for arc internal RTC */
#define SECURE_TIMER_0 0 /*!< macro name for arc internal secure timer 0 */
#define SECURE_TIMER_1 1 /*!< macro name for arc internal secure timer 1 */
/** @} */
#ifdef ARC_FEATURE_TIMER0_VECTOR
#define INTNO_TIMER0 ARC_FEATURE_TIMER0_VECTOR /*!< ARC Timer0 */
#else
#define INTNO_TIMER0 16
#endif
#ifdef ARC_FEATURE_TIMER1_VECTOR
#define INTNO_TIMER1 ARC_FEATURE_TIMER1_VECTOR /*!< ARC Timer1 */
#else
#define INTNO_TIMER1 17
#endif
#ifdef ARC_FEATURE_SEC_TIMER0_VECTOR
#define INTNO_SECURE_TIMER0 ARC_FEATURE_SEC_TIMER0_VECTOR /*!< Core Secure Timer 0 */
#else
#define INTNO_SECURE_TIMER0 20
#endif
#ifdef ARC_FEATURE_SEC_TIMER1_VECTOR
#define INTNO_SECURE_TIMER1 ARC_FEATURE_SEC_TIMER1_VECTOR /*!< Core Secure Timer 1 */
#else
#define INTNO_SECURE_TIMER1 21
#endif
/**
* @name bit definition of RTC CTRL reg
* @{
*/
#define TIMER_RTC_ENABLE (0x01) /*!< enable RTC */
#define TIMER_RTC_CLEAR (0x02) /* clears the AUX_RTC_LOW and AUX_RTC_HIGH */
#define TIMER_RTC_STATUS_A0 (0x40000000) /*!< track bit of atomicity of reads of RTC */
#define TIMER_RTC_STATUS_A1 (0x80000000) /*!< track bit of atomicity of reads of RTC */
/** @} */
/**
* @name bit definition of timer CTRL reg
* @{
*/
#define TIMER_CTRL_IE (1 << 0) /*!< Interrupt when count reaches limit */
#define TIMER_CTRL_NH (1 << 1) /*!< Count only when CPU NOT halted */
#define TIMER_CTRL_W (1 << 2) /*!< watchdog enable */
#define TIMER_CTRL_IP (1 << 3) /*!< interrupt pending */
/** @} */
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
extern int32_t timer_present(const uint32_t no);
extern int32_t timer_start(const uint32_t no, const uint32_t mode, const uint32_t val);
extern int32_t timer_stop(const uint32_t no);
extern int32_t timer_current(const uint32_t no, void *val);
extern int32_t timer_int_clear(const uint32_t no);
extern void arc_timer_init(void);
extern void arc_delay_us(uint32_t usecs);
extern uint64_t timer_calibrate_delay(uint32_t cpu_clock);
extern int32_t secure_timer_present(const uint32_t no);
extern int32_t secure_timer_start(const uint32_t no, const uint32_t mode, const uint32_t val);
extern int32_t secure_timer_stop(const uint32_t no);
extern int32_t secure_timer_current(const uint32_t no, void *val);
extern int32_t secure_timer_int_clear(const uint32_t no);
extern void secure_timer_init(void);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_TIMER */
/** @}*/

View File

@@ -1,330 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_UDMA
* @brief header file for ARC uDMA Controller
*/
/**
* @addtogroup ARC_HAL_MISC_UDMA
* @{
*/
#ifndef H_ARC_UDMA
#define H_ARC_UDMA
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "arc/arc_builtin.h"
#include "arc/arc_cache.h"
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef CORE_DMAC_INTERNAL_VERSION
/** Version of the DMA controller */
#define CORE_DMAC_INTERNAL_VERSION 2
#endif
#ifndef DMA_MULTI_IRQ
/** Multiple interrupts for DMA */
#define DMA_MULTI_IRQ 0
#endif
#ifndef DMA_IRQ_PRIO
/** DMA IRQ priority */
#define DMA_IRQ_PRIO (INT_PRI_MIN)
#endif
#ifndef DMA_IRQ_NUM_START
/** DMA IRQ start vector */
#define DMA_IRQ_NUM_START 20
#endif
#ifndef DMA_ALL_CHANNEL_NUM
/*!< Number of all DMA channels */
#ifdef CORE_DMAC_CHANNELS
#define DMA_ALL_CHANNEL_NUM CORE_DMAC_CHANNELS
#else
#define DMA_ALL_CHANNEL_NUM 2
#endif
#endif
#ifndef DMA_REGISTER_CHANNEL_NUM
/*!< Number of all aux-register based DMA channels */
#ifdef CORE_DMAC_REGISTERS
#define DMA_REGISTER_CHANNEL_NUM CORE_DMAC_REGISTERS
#else
#define DMA_REGISTER_CHANNEL_NUM 0
#endif
#endif
/*!< Mask of all DMA channels at the most */
#define DMA_ALL_CHANNEL_MASK 0xFFFF
#define DMACTRLx_OP_OFS (0) /*!< bit field offset: bit 0,1 */
#define DMACTRLx_R_OFS (2) /*!< bit field offset: bit 2 */
#define DMACTRLx_DTT_OFS (3) /*!< bit field offset: bit 3,4 */
#define DMACTRLx_DWINC_OFS (5) /*!< bit field offset: bit 5,6,7 */
#define DMACTRLx_SIZE_OFS (8) /*!< bit field offset: bit 8..20 */
#define DMACTRLx_ARB_OFS (21) /*!< bit field offset: bit 21..28 */
#define DMACTRLx_INT_OFS (29) /*!< bit field offset: bit 29 */
#define DMACTRLx_AM_OFS (30) /*!< bit field offset: bit 30,31 */
#define DMACTRLx_OP(x) ((x) << DMACTRLx_OP_OFS) /*!< bit field value: bit 0,1 */
#define DMACTRLx_R(x) ((x) << DMACTRLx_R_OFS) /*!< bit field value: bit 2 */
#define DMACTRLx_DTT(x) ((x) << DMACTRLx_DTT_OFS) /*!< bit field value: bit 3,4 */
#define DMACTRLx_DWINC(x) ((x) << DMACTRLx_DWINC_OFS) /*!< bit field value: bit 5,6,7 */
#define DMACTRLx_SIZE(x) ((x) << DMACTRLx_SIZE_OFS) /*!< bit field value: bit 8..20 */
#define DMACTRLx_ARB(x) ((x) << DMACTRLx_ARB_OFS) /*!< bit field value: bit 21..28 */
#define DMACTRLx_INT(x) ((x) << DMACTRLx_INT_OFS) /*!< bit field value: bit 29 */
#define DMACTRLx_AM(x) ((x) << DMACTRLx_AM_OFS) /*!< bit field value: bit 30,31 */
#define DMACTRLx_OP_MASK DMACTRLx_OP(0x3) /*!< bit field mask: bit 0,1 */
#define DMACTRLx_R_MASK DMACTRLx_R(0x1) /*!< bit field mask: bit 2 */
#define DMACTRLx_DTT_MASK DMACTRLx_DTT(0x3) /*!< bit field mask: bit 3,4 */
#define DMACTRLx_DWINC_MASK DMACTRLx_DWINC(0x7) /*!< bit field mask: bit 5,6,7 */
#define DMACTRLx_SIZE_MASK DMACTRLx_SIZE(0x1FFF) /*!< bit field mask: bit 8..20 */
#define DMACTRLx_ARB_MASK DMACTRLx_ARB(0xFF) /*!< bit field mask: bit 21..28 */
#define DMACTRLx_INT_MASK DMACTRLx_INT(0x1) /*!< bit field mask: bit 29 */
#define DMACTRLx_AM_MASK DMACTRLx_AM(0x3) /*!< bit field mask: bit 30,31 */
#define DMACHANNEL(x) ((0x1 << (x)) & 0xFFFF) /*!< Channel number to Bit */
/** Handler function for uDAM callback, param should be current dma channel transfer structure DMA_CHANNEL_T */
typedef void (*DMA_CALLBACK_T) (void *param);
typedef struct {
uint32_t op : 2; /*!< operation field */
uint32_t rt : 1; /*!< request type field */
uint32_t dtt : 2; /*!< source and destination target types field */
uint32_t dwinc : 3; /*!< data width and address increment field */
uint32_t blksz : 13; /*!< data transfer in bytes field */
uint32_t arb : 8; /*!< arbitration size */
uint32_t intm : 1; /*!< interrupt mode bit */
uint32_t am : 2; /*!< address mode field */
} DMA_CTRL_FIELD_T;
/** DMA channel control register union */
typedef union {
DMA_CTRL_FIELD_T bits; /*!< control register in bits format */
uint32_t value; /*!< control register in word format */
} DMA_CTRL_T;
/** DMA working status enumeration */
#define DMA_IDLE 0 /*!< Current DMA status is IDLE */
#define DMA_BUSY 1 /*!< Current DMA status is busy, in transfer */
#define DMA_ERROR 2 /*!< Current DMA status is error, in transfer error */
#define DMA_STOP 3 /*!< Current DMA is stop by user */
#define DMA_CHN_ANY -1 /*!< Any channel, request one */
#define DMA_CHN_INVALID -2 /*!< Invalid channel */
/** DMA channel request or trigger source enumeration */
#define DMA_REQ_SOFT 0 /*!< Software trigger */
#define DMA_REQ_PERIPHERAL 1 /*!< Peripheral trigger */
/** DMA descriptor (DMA channel registers) */
typedef struct {
uint32_t DMACTRLx; /*!< DMA channel control register */
uint32_t DMASARx; /*!< DMA channel end source address register */
uint32_t DMADARx; /*!< DMA channel end destination address register */
uint32_t DMALLPx; /*!< DMA channel link-list pointer (for chaining/linking separate DMA transfers only) */
} DMA_DESC_T;
/** DMA Channel transfer structure */
typedef struct {
int32_t channel; /*!< Channel ID binded to this transfer */
int16_t priority; /*!< Transfer priority */
int16_t int_en; /*!< Interrupt enable status */
uint32_t source; /*!< DMA request or trigger source for this transfer */
DMA_DESC_T *desc; /*!< DMA transfer descriptor for this transfer */
volatile uint32_t status; /*!< DMA transfer status of this transfer */
DMA_CALLBACK_T callback; /*!< DMA transfer callback */
} DMA_CHANNEL_T;
/** DMA channel control bit field enumeration - DMA Operation (OP) */
#define DMA_INVALID_TRANSFER 0 /*!< Invalid channel */
#define DMA_SINGLE_TRANSFER 1 /*!< Single Block */
#define DMA_AUTO_LINKED_TRANSFER 2 /*!< Link-List (Auto-Request) */
#define DMA_MANUAL_LINKED_TRANSFER 3 /*!< Link-List (Manual-Request) */
/** DMA channel control bit field enumeration - Request Type (RT) */
#define DMA_AUTO_REQUEST 0 /*!< Auto-request following channel arbitration */
#define DMA_MANUAL_REQUEST 1 /*!< Manual-request following channel arbitration */
/** DMA channel control bit field enumeration - Data Transfer Type (DTT) */
#define DMA_MEM2MEM 0 /*!< Memory to Memory */
#define DMA_MEM2AUX 1 /*!< Memory to Auxiliary */
#define DMA_AUX2MEM 2 /*!< Auxiliary to Memory */
#define DMA_AUX2AUX 3 /*!< Auxiliary to Auxiliary */
/** DMA channel control bit field enumeration - Data Width/Increment (DW/INC) */
#define DMA_DW1INC1 0 /*!< dw=byte, inc=byte */
#define DMA_DW1INC2 1 /*!< dw=byte, inc=half-word */
#define DMA_DW1INC4 2 /*!< dw=byte, inc=word */
#define DMA_DW2INC2 3 /*!< dw=half-word, inc=half-word */
#define DMA_DW2INC4 4 /*!< dw=half-word, inc=word */
#define DMA_DW4INC4 5 /*!< dw=word, inc=word */
#define DMA_DWINC_CLR 6 /*!< clear mode (dw=word, inc=word) */
#define DMA_DW8INC8 7 /*!< dw=double-word, inc=double-word(Only supported in HS) */
/** DMA channel control bit field enumeration - Internal/External Interrupt enable (INT) */
#define DMA_INT_DISABLE 0 /*!< Interrupt disabled, no interrupt raised is on completion of a data transfer */
#define DMA_INT_ENABLE 1 /*!< Interrupt enabled, a level interrupt raised on completion of a data transfer */
/** DMA channel control bit field enumeration - Address update Mode (AM) */
#define DMA_AM_SRCNOT_DSTNOT 0 /*!< No Source or Destination Address increment */
#define DMA_AM_SRCINC_DSTNOT 1 /*!< Source Address incremented, Destination Address not incremented */
#define DMA_AM_SRCNOT_DSTINC 2 /*!< Source Address not incremented, Destination Address incremented */
#define DMA_AM_SRCINC_DSTINC 3 /*!< Source Address and Destination Address incremented */
/** DMA channel priority enumeration */
#define DMA_CHN_NORM_PRIO 0 /*!< Normal priority */
#define DMA_CHN_HIGH_PRIO 1 /*!< High priority */
/** Number of Memory based DMA Channel */
#define DMA_MEMORY_CHANNEL_NUM ((DMA_ALL_CHANNEL_NUM) -(DMA_REGISTER_CHANNEL_NUM))
#if CORE_DMAC_INTERNAL_VERSION == 1
#if DMA_MEMORY_CHANNEL_NUM > 0
/** Memory based DMA channels existed */
#define DMA_MEMORY_HEADER
#endif
#endif
/** Check whether channel have register interface */
#define DMA_CHECK_REGISTER(channel) (channel >= (DMA_MEMORY_CHANNEL_NUM))
/** DMA state to maintain uDMA resources */
typedef struct {
#ifdef DMA_MEMORY_HEADER
/*!< Memory based DMA descriptors */
EMBARC_ALIGNED(256) volatile DMA_DESC_T mem_dma_descs[DMA_MEMORY_CHANNEL_NUM];
#endif
#if CORE_DMAC_INTERNAL_VERSION > 1
EMBARC_ALIGNED(32) volatile uint32_t mem_dma_ptrs[DMA_ALL_CHANNEL_NUM];
#endif
/*!< All uDMA channel resources */
volatile DMA_CHANNEL_T *dma_chns[DMA_ALL_CHANNEL_NUM];
} DMA_STATE_T;
/** Set DMA_CTRL_T structure ctrl bit field - OP
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_OP(ctrl, val) (ctrl)->bits.op = val;
/** Set DMA_CTRL_T structure ctrl bit field - RT
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_RT(ctrl, val) (ctrl)->bits.rt = val;
/** Set DMA_CTRL_T structure ctrl bit field - DTT
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_DTT(ctrl, val) (ctrl)->bits.dtt = val;
/** Set DMA_CTRL_T structure ctrl bit field - DW/INC
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_DWINC(ctrl, val) (ctrl)->bits.dwinc = val;
/** Calculate right size
*
* @param x transfer size
* @retval (x-1) value after calculation
*/
#define DMA_CTRL_BLKSZ(x) (x - 1)
/** Set DMA_CTRL_T structure ctrl bit field - BLOCKSIZE
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_BLKSZ(ctrl, val) (ctrl)->bits.blksz = val;
/** Set DMA_CTRL_T structure ctrl bit field - ARB
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_ARB(ctrl, val) (ctrl)->bits.arb = val;
/** Set DMA_CTRL_T structure ctrl bit field - I
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_INT(ctrl, val) (ctrl)->bits.intm = val;
/** Set DMA_CTRL_T structure ctrl bit field - AM
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_AM(ctrl, val) (ctrl)->bits.am = val;
/** Set DMA_CTRL_T structure ctrl value
*
* @param ctrl This should be DMA_CTRL_T structure, and not NULL
* @param val Target value
*/
#define DMA_CTRL_SET_VALUE(ctrl, val) (ctrl)->value = val;
extern int32_t dmac_init(DMA_STATE_T *state);
extern void dmac_close(void);
extern int32_t dmac_config_desc(DMA_DESC_T *desc, void *src, void *dst, uint32_t size, DMA_CTRL_T *ctrl);
extern int32_t dmac_desc_add_linked(DMA_DESC_T *head, DMA_DESC_T *next);
extern int32_t dmac_init_channel(DMA_CHANNEL_T *dma_chn);
extern int32_t dmac_config_channel(DMA_CHANNEL_T *dma_chn, DMA_DESC_T *desc);
extern int32_t dmac_reserve_channel(int32_t channel, DMA_CHANNEL_T *dma_chn, uint32_t source);
extern int32_t dmac_start_channel(DMA_CHANNEL_T *dma_chn, DMA_CALLBACK_T callback, uint32_t priority);
extern int32_t dmac_stop_channel(DMA_CHANNEL_T *dma_chn);
extern int32_t dmac_release_channel(DMA_CHANNEL_T *dma_chn);
extern int32_t dmac_wait_channel(DMA_CHANNEL_T *dma_chn);
extern int32_t dmac_check_channel(DMA_CHANNEL_T *dma_chn);
extern int32_t dmac_clear_channel(DMA_CHANNEL_T *dma_chn);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_UDMA */
/** @}*/

View File

@@ -1,308 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_ARC_XY_AGU
#define H_ARC_XY_AGU
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
#define U0 % r32
#define U1 % r33
#define U2 % r34
#ifdef ARC_FEATURE_XCCM_PRESENT
#define ARC_X_CCM __attribute__ ((section(".x_ccm")))
#else
#define ARC_X_CCM
#endif
#ifdef ARC_FEATURE_YCCM_PRESENT
#define ARC_Y_CCM __attribute__ ((section(".y_ccm")))
#else
#define ARC_Y_CCM
#endif
#define US_EXPAND_MOD_NAME(reg_id) AUX_AGU_MOD ## reg_id
#define US_EXPAND_OS_NAME(reg_id) AUX_AGU_OS ## reg_id
#define US_EXPAND_AP_NAME(reg_id) AUX_AGU_AP ## reg_id
#define ARC_AGU_MOD_SET(agu_mod, ptr_id, data_type, addressing) \
arc_aux_write(US_EXPAND_MOD_NAME(agu_mod), (uint32_t)(ptr_id | data_type | addressing))
#define ARC_AGU_OS_SET(os_id, offset) \
arc_aux_write(US_EXPAND_OS_NAME(os_id), (uint32_t)offset)
#define ARC_AGU_AP_SET(ap_id, addr) \
arc_aux_write(US_EXPAND_AP_NAME(ap_id), (uint32_t)addr)
#define ARC_AGU_MOD_GET(mod_id) arc_aux_read(US_EXPAND_MOD_NAME(mod_id))
#define ARC_AGU_OS_GET(os_id) arc_aux_read(US_EXPAND_MOD_NAME(os_id))
#define ARC_AGU_AP_GET(ap_id) arc_aux_read(US_EXPAND_AP_NAME(ap_id))
#define ARC_AGU_MOD_VW(x) ((x) << 4)
#define ARC_AGU_MOD_FX(x) ((x) << 6)
#define ARC_AGU_MOD_DIR(x) ((x) << 11)
#define ARC_AGU_MOD_REV (1 << 12)
#define ARC_AGU_MOD_REP (1 << 13)
#define ARC_AGU_MOD_SC(x) ((x) << 14)
#define ARC_AGU_MOD_OFFSET_REG(x) ((x) << 25)
#define ARC_AGU_MOD_OFFSET_IMM(x) ((x) << 18)
#define ARC_AGU_MOD_WRAP_REG(x) ((x) << 14)
#define ARC_AGU_MOD_WRAP_IMM(x) ((x) << 14)
#define ARC_AGU_MOD_OPC(x) ((x) << 29)
#define ARC_AGU_DT_I32 (ARC_AGU_MOD_FX(11) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_I32_CAST_I16 (ARC_AGU_MOD_FX(8) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_I32_CAST_I8 (ARC_AGU_MOD_FX(4) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_I16 (ARC_AGU_MOD_FX(3) | ARC_AGU_MOD_VW(1))
#define ARC_AGU_DT_I16_CAST_I8 (ARC_AGU_MOD_FX(0) | ARC_AGU_MOD_VW(1))
#define ARC_AGU_DT_I8 (ARC_AGU_MOD_FX(7) | ARC_AGU_MOD_VW(0))
#define ARC_AGU_DT_V2I16 (ARC_AGU_MOD_FX(3) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_V2I16_REPLIC_I16 (ARC_AGU_MOD_FX(3) | ARC_AGU_MOD_VW(2) | ARC_AGU_MOD_REP)
#define ARC_AGU_DT_V2I16_CAST_V2I8 (ARC_AGU_MOD_FX(0) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_V2I8 (ARC_AGU_MOD_FX(7) | ARC_AGU_MOD_VW(1))
#define ARC_AGU_DT_V2I8_REPLIC_I8 (ARC_AGU_MOD_FX(7) | ARC_AGU_MOD_VW(1) | ARC_AGU_MOD_REP)
#define ARC_AGU_DT_V4I8 (ARC_AGU_MOD_FX(7) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_V4I8_REPLIC_I8 (ARC_AGU_MOD_FX(7) | ARC_AGU_MOD_VW(2) | ARC_AGU_MOD_REP)
/* AGU addressing modes with scling factor macroses */
#define ARC_AGU_AD_INC_I32(offset) (ARC_AGU_MOD_OPC(1) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(2))
#define ARC_AGU_AD_DEC_I32(offset) (ARC_AGU_MOD_OPC(1) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(2) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_INC_I32_REG(reg_id) (ARC_AGU_MOD_OPC(0) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(2))
#define ARC_AGU_AD_DEC_I32_REG(reg_id) (ARC_AGU_MOD_OPC(0) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(2) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_BITREV_INC_I32(offset) (ARC_AGU_MOD_OPC(3) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(2))
#define ARC_AGU_AD_BITREV_DEC_I32(offset) (ARC_AGU_MOD_OPC(3) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(2) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_BITREV_INC_I32_REG(reg_id) (ARC_AGU_MOD_OPC(2) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(2))
#define ARC_AGU_AD_BITREV_DEC_I32_REG(reg_id) (ARC_AGU_MOD_OPC(2) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(2) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_INC_I16(offset) (ARC_AGU_MOD_OPC(1) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(1))
#define ARC_AGU_AD_DEC_I16(offset) (ARC_AGU_MOD_OPC(1) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(1) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_INC_I16_REG(reg_id) (ARC_AGU_MOD_OPC(0) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(1))
#define ARC_AGU_AD_DEC_I16_REG(reg_id) (ARC_AGU_MOD_OPC(0) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(1) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_BITREV_INC_I16(offset) (ARC_AGU_MOD_OPC(3) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(1))
#define ARC_AGU_AD_BITREV_DEC_I16(offset) (ARC_AGU_MOD_OPC(3) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(1) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_BITREV_INC_I16_REG(reg_id) (ARC_AGU_MOD_OPC(2) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(1))
#define ARC_AGU_AD_BITREV_DEC_I16_REG(reg_id) (ARC_AGU_MOD_OPC(2) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(1) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_INC_I8(offset) (ARC_AGU_MOD_OPC(1) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(0))
#define ARC_AGU_AD_DEC_I8(offset) (ARC_AGU_MOD_OPC(1) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(0) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_INC_I8_REG(reg_id) (ARC_AGU_MOD_OPC(0) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(0))
#define ARC_AGU_AD_DEC_I8_REG(reg_id) (ARC_AGU_MOD_OPC(0) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(0) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_BITREV_INC_I8(offset) (ARC_AGU_MOD_OPC(3) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(0))
#define ARC_AGU_AD_BITREV_DEC_I8(offset) (ARC_AGU_MOD_OPC(3) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_SC(0) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_BITREV_INC_I8_REG(reg_id) (ARC_AGU_MOD_OPC(2) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(0))
#define ARC_AGU_AD_BITREV_DEC_I8_REG(reg_id) (ARC_AGU_MOD_OPC(2) | ARC_AGU_MOD_OFFSET_REG(reg_id) | ARC_AGU_MOD_SC(0) | ARC_AGU_MOD_DIR(1))
/******************************************************************************
*
* AGU data types with type casting macroses for unsigned int data types
* unsigned int data type assumes lsb aligned data conversion without sign extension
*
******************************************************************************/
#define ARC_AGU_DT_UI32 ARC_AGU_DT_I32
#define ARC_AGU_DT_UI32_CAST_UI16 (ARC_AGU_MOD_FX(9) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_UI32_CAST_UI8 (ARC_AGU_MOD_FX(5) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_UI16 ARC_AGU_DT_I16
#define ARC_AGU_DT_UI16_CAST_UI8 (ARC_AGU_MOD_FX(1) | ARC_AGU_MOD_VW(1))
#define ARC_AGU_DT_UI8 ARC_AGU_DT_I8
#define ARC_AGU_DT_V2UI16 ARC_AGU_DT_V2I16
#define ARC_AGU_DT_V2UI16_REPLIC_UI16 ARC_AGU_DT_V2I16_REPLIC_I16
#define ARC_AGU_DT_V2UI16_CAST_V2UI8 (ARC_AGU_MOD_FX(1) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_V2UI8 ARC_AGU_DT_V2I8
#define ARC_AGU_DT_V2UI8_REPLIC_UI8 ARC_AGU_DT_V2I8_REPLIC_I8
#define ARC_AGU_DT_V4UI8 ARC_AGU_DT_V4I8
#define ARC_AGU_DT_V4UI8_REPLIC_UI8 ARC_AGU_DT_V4I8_REPLIC_I8
/* AGU addressing modes with scling factor macroses */
#define ARC_AGU_AD_INC_UI32(offset) ARC_AGU_AD_INC_I32(offset)
#define ARC_AGU_AD_DEC_UI32(offset) ARC_AGU_AD_DEC_I32(offset)
#define ARC_AGU_AD_INC_UI32_REG(reg_id) ARC_AGU_AD_INC_I32_REG(reg_id)
#define ARC_AGU_AD_DEC_UI32_REG(reg_id) ARC_AGU_AD_DEC_I32_REG(reg_id)
#define ARC_AGU_AD_BITREV_INC_UI32(offset) ARC_AGU_AD_BITREV_INC_I32(offset)
#define ARC_AGU_AD_BITREV_DEC_UI32(offset) ARC_AGU_AD_BITREV_DEC_I32(offset)
#define ARC_AGU_AD_BITREV_INC_UI32_REG(reg_id) ARC_AGU_AD_BITREV_INC_I32_REG(reg_id)
#define ARC_AGU_AD_BITREV_DEC_UI32_REG(reg_id) ARC_AGU_AD_BITREV_DEC_I32_REG(reg_id)
#define ARC_AGU_AD_INC_UI16(offset) ARC_AGU_AD_INC_I16(offset)
#define ARC_AGU_AD_DEC_UI16(offset) ARC_AGU_AD_DEC_I16(offset)
#define ARC_AGU_AD_INC_UI16_REG(reg_id) ARC_AGU_AD_INC_I16_REG(reg_id)
#define ARC_AGU_AD_DEC_UI16_REG(reg_id) ARC_AGU_AD_DEC_I16_REG(reg_id)
#define ARC_AGU_AD_BITREV_INC_UI16(offset) ARC_AGU_AD_BITREV_INC_I16(offset)
#define ARC_AGU_AD_BITREV_DEC_UI16(offset) ARC_AGU_AD_BITREV_DEC_I16(offset)
#define ARC_AGU_AD_BITREV_INC_UI16_REG(reg_id) ARC_AGU_AD_BITREV_INC_I16_REG(reg_id)
#define ARC_AGU_AD_BITREV_DEC_UI16_REG(reg_id) ARC_AGU_AD_BITREV_DEC_I16_REG(reg_id)
#define ARC_AGU_AD_INC_UI8(offset) ARC_AGU_AD_INC_I8(offset)
#define ARC_AGU_AD_DEC_UI8(offset) ARC_AGU_AD_DEC_I8(offset)
#define ARC_AGU_AD_INC_UI8_REG(reg_id) ARC_AGU_AD_INC_I8_REG(reg_id)
#define ARC_AGU_AD_DEC_UI8_REG(reg_id) ARC_AGU_AD_DEC_I8_REG(reg_id)
#define ARC_AGU_AD_BITREV_INC_UI8(offset) ARC_AGU_AD_BITREV_INC_I8(offset)
#define ARC_AGU_AD_BITREV_DEC_UI8(offset) ARC_AGU_AD_BITREV_DEC_I8(offset)
#define ARC_AGU_AD_BITREV_INC_UI8_REG(reg_id) ARC_AGU_AD_BITREV_INC_I8_REG(reg_id)
#define ARC_AGU_AD_BITREV_DEC_UI8_REG(reg_id) ARC_AGU_AD_BITREV_DEC_I8_REG(reg_id)
/******************************************************************************
*
* AGU data types with type casting macroses for q.xx data types
* q.xx data type assumes msb aligned data conversion
*
******************************************************************************/
#define ARC_AGU_DT_Q31 ARC_AGU_DT_I32
#define ARC_AGU_DT_Q31_CAST_Q15 (ARC_AGU_MOD_FX(10) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_Q31_CAST_Q7 (ARC_AGU_MOD_FX(6) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_Q15 ARC_AGU_DT_I16
#define ARC_AGU_DT_Q15_CAST_Q7 (ARC_AGU_MOD_FX(2) | ARC_AGU_MOD_VW(1))
#define ARC_AGU_DT_Q7 ARC_AGU_DT_I8
#define ARC_AGU_DT_Q7_CAST_Q15 (ARC_AGU_MOD_FX(2) | ARC_AGU_MOD_VW(1)) // packing
#define ARC_AGU_DT_V2Q15 ARC_AGU_DT_V2I16
#define ARC_AGU_DT_V2Q15_REPLIC_Q15 ARC_AGU_DT_V2I16_REPLIC_I16
#define ARC_AGU_DT_V2Q15_CAST_V2Q7 (ARC_AGU_MOD_FX(2) | ARC_AGU_MOD_VW(2))
#define ARC_AGU_DT_V2Q7 ARC_AGU_DT_V2I8
#define ARC_AGU_DT_V2Q7_REPLIC_Q7 ARC_AGU_DT_V2I8_REPLIC_I8
#define ARC_AGU_DT_V2Q7_CAST_V2Q15 (ARC_AGU_MOD_FX(2) | ARC_AGU_MOD_VW(2)) // packing
#define ARC_AGU_DT_V4Q7 ARC_AGU_DT_V4I8
#define ARC_AGU_DT_V4Q7_REPLIC_Q7 ARC_AGU_DT_V4I8_REPLIC_I8
/* AGU addressing modes with scling factor macroses for q.xx data types */
#define ARC_AGU_AD_INC_Q31(offset) ARC_AGU_AD_INC_I32(offset)
#define ARC_AGU_AD_DEC_Q31(offset) ARC_AGU_AD_DEC_I32(offset)
#define ARC_AGU_AD_INC_Q31_REG(reg_id) ARC_AGU_AD_INC_I32_REG(reg_id)
#define ARC_AGU_AD_DEC_Q31_REG(reg_id) ARC_AGU_AD_DEC_I32_REG(reg_id)
#define ARC_AGU_AD_BITREV_INC_Q31(offset) ARC_AGU_AD_BITREV_INC_I32(offset)
#define ARC_AGU_AD_BITREV_DEC_Q31(offset) ARC_AGU_AD_BITREV_DEC_I32(offset)
#define ARC_AGU_AD_BITREV_INC_Q31_REG(reg_id) ARC_AGU_AD_BITREV_INC_I32_REG(reg_id)
#define ARC_AGU_AD_BITREV_DEC_Q31_REG(reg_id) ARC_AGU_AD_BITREV_DEC_I32_REG(reg_id)
#define ARC_AGU_AD_INC_Q15(offset) ARC_AGU_AD_INC_I16(offset)
#define ARC_AGU_AD_DEC_Q15(offset) ARC_AGU_AD_DEC_I16(offset)
#define ARC_AGU_AD_INC_Q15_REG(reg_id) ARC_AGU_AD_INC_I16_REG(reg_id)
#define ARC_AGU_AD_DEC_Q15_REG(reg_id) ARC_AGU_AD_DEC_I16_REG(reg_id)
#define ARC_AGU_AD_BITREV_INC_Q15(offset) ARC_AGU_AD_BITREV_INC_I16(offset)
#define ARC_AGU_AD_BITREV_DEC_Q15(offset) ARC_AGU_AD_BITREV_DEC_I16(offset)
#define ARC_AGU_AD_BITREV_INC_Q15_REG(reg_id) ARC_AGU_AD_BITREV_INC_I16_REG(reg_id)
#define ARC_AGU_AD_BITREV_DEC_Q15_REG(reg_id) ARC_AGU_AD_BITREV_DEC_I16_REG(reg_id)
#define ARC_AGU_AD_INC_Q7(offset) ARC_AGU_AD_INC_I8(offset)
#define ARC_AGU_AD_DEC_Q7(offset) ARC_AGU_AD_DEC_I8(offset)
#define ARC_AGU_AD_INC_Q7_REG(reg_id) ARC_AGU_AD_INC_I8_REG(reg_id)
#define ARC_AGU_AD_DEC_Q7_REG(reg_id) ARC_AGU_AD_DEC_I8_REG(reg_id)
#define ARC_AGU_AD_BITREV_INC_Q7(offset) ARC_AGU_AD_BITREV_INC_I8(offset)
#define ARC_AGU_AD_BITREV_DEC_Q7(offset) ARC_AGU_AD_BITREV_DEC_I8(offset)
#define ARC_AGU_AD_BITREV_INC_Q7_REG(reg_id) ARC_AGU_AD_BITREV_INC_I8_REG(reg_id)
#define ARC_AGU_AD_BITREV_DEC_Q7_REG(reg_id) ARC_AGU_AD_BITREV_DEC_I8_REG(reg_id)
/* AGU modificator for reverse vector elements (can be useful for Endian conversions) */
#define ARC_AGU_DT_VECTOR_REVERSE ARC_AGU_MOD_REV
/* AGU wrapping modifiers */
#define ARC_AGU_AD_WRAP_INC_RR(inc_os_id, modulo_os_id) (ARC_AGU_MOD_OPC(4) | ARC_AGU_MOD_OFFSET_REG(inc_os_id) | ARC_AGU_MOD_WRAP_REG(modulo_os_id))
#define ARC_AGU_AD_WRAP_DEC_RR(dec_os_id, modulo_os_id) (ARC_AGU_MOD_OPC(4) | ARC_AGU_MOD_OFFSET_REG(dec_os_id) | ARC_AGU_MOD_WRAP_REG(modulo_os_id) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_WRAP_INC_II(offset, modulo) (ARC_AGU_MOD_OPC(5) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_WRAP_IMM(modulo))
#define ARC_AGU_AD_WRAP_DEC_II(offset, modulo) (ARC_AGU_MOD_OPC(5) | ARC_AGU_MOD_OFFSET_IMM(offset) | ARC_AGU_MOD_WRAP_IMM(modulo) | ARC_AGU_MOD_DIR(1))
#define ARC_AGU_AD_WRAP_INC_RI(dec_os_id, modulo) (ARC_AGU_MOD_OPC(6) | ARC_AGU_MOD_OFFSET_REG(dec_os_id) | ARC_AGU_MOD_WRAP_IMM(modulo))
#define ARC_AGU_AD_WRAP_DEC_RI(dec_os_id, modulo) (ARC_AGU_MOD_OPC(6) | ARC_AGU_MOD_OFFSET_REG(dec_os_id) | ARC_AGU_MOD_WRAP_IMM(modulo) | ARC_AGU_MOD_DIR(1))
/* Immediate Wrapping constants */
#define AGU_WRAP_IMM_2 0
#define AGU_WRAP_IMM_4 1
#define AGU_WRAP_IMM_8 2
#define AGU_WRAP_IMM_16 3
#define AGU_WRAP_IMM_32 4
#define AGU_WRAP_IMM_64 5
#define AGU_WRAP_IMM_128 6
#define AGU_WRAP_IMM_256 7
#define AGU_WRAP_IMM_512 8
#define AGU_WRAP_IMM_1024 9
#define AGU_WRAP_IMM_2048 10
#define AGU_WRAP_IMM_4096 11
#define AGU_WRAP_IMM_8192 12
#define AGU_WRAP_IMM_16384 13
#define AGU_WRAP_IMM_32768 14
#define AGU_WRAP_IMM_65536 15
/* push pop macros to follow calling conventions */
#define ARC_AGU_STORE_REGS(ap_num, mod_num, os_num) \
int32_t agu_temp_idx; \
uint32_t agu_temp_ap[ap_num]; \
uint32_t agu_temp_mod[mod_num]; \
uint32_t agu_temp_os[os_num]; \
int32_t agu_temp_ap_num = ap_num; \
int32_t agu_temp_mod_num = mod_num; \
int32_t agu_temp_os_num = os_num; \
for (agu_temp_idx = 0; agu_temp_idx < ap_num; agu_temp_idx++) agu_temp_ap[agu_temp_idx] = _lr(AGU_AUX_AP0 + agu_temp_idx); \
for (agu_temp_idx = 0; agu_temp_idx < mod_num; agu_temp_idx++) agu_temp_mod[agu_temp_idx] = _lr(AGU_AUX_MOD0 + agu_temp_idx); \
for (agu_temp_idx = 0; agu_temp_idx < os_num; agu_temp_idx++) agu_temp_os[agu_temp_idx] = _lr(AGU_AUX_OS0 + agu_temp_idx); {}
#define ARC_AGU_RESTORE_REGS() \
for (agu_temp_idx = 0; agu_temp_idx < agu_temp_ap_num; agu_temp_idx++) _sr (agu_temp_ap[agu_temp_idx], AGU_AUX_AP0 + agu_temp_idx); \
for (agu_temp_idx = 0; agu_temp_idx < agu_temp_mod_num; agu_temp_idx++) _sr (agu_temp_mod[agu_temp_idx], AGU_AUX_MOD0 + agu_temp_idx); \
for (agu_temp_idx = 0; agu_temp_idx < agu_temp_os_num; agu_temp_idx++) _sr (agu_temp_os[agu_temp_idx], AGU_AUX_OS0 + agu_temp_idx); {}
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_XY_AGU */

View File

@@ -1,136 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_GPIO
#define H_DW_GPIO
#include "device/ip_hal/dev_gpio.h"
#include "arc/arc_exception.h"
#define DW_GPIO_PORT_A (0)
#define DW_GPIO_PORT_B (1)
#define DW_GPIO_PORT_C (2)
#define DW_GPIO_PORT_D (3)
#define DW_GPIO_INT_ACT_LOW GPIO_INT_ACTIVE_LOW
#define DW_GPIO_INT_ACT_HIGH GPIO_INT_ACTIVE_HIGH
#define DW_GPIO_INT_LEVEL_TRIG GPIO_INT_LEVEL_TRIG
#define DW_GPIO_INT_EDGE_TRIG GPIO_INT_EDGE_TRIG
#define DW_GPIO_INT_NO_DEBOUNCE GPIO_INT_NO_DEBOUNCE
#define DW_GPIO_INT_DEBOUNCE GPIO_INT_DEBOUNCE
#define DW_GPIO_ALL_ZERO (0x0)
#define DW_GPIO_ALL_ONE (0xffffffff)
#define DW_GPIO_MASK_ALL (0xffffffff)
#define DW_GPIO_INPUT_ALL (0x0)
#define DW_GPIO_OUTPUT_ALL (0xffffffff)
#define DW_GPIO_INVALID_INTNO (DEV_INTNO_INVALID)
/**
* @name DesignWare GPIO Register Structure
* @brief DesignWare GPIO register structure for gpio port
* @{
*/
typedef struct {
uint32_t DR;
uint32_t DDR;
uint32_t CTRL;
} PORT_CTRL;
/* DW GPIO PORTS Registers */
typedef volatile struct {
PORT_CTRL SWPORTS[4];
uint32_t INTEN; /*!< (0x30) */
uint32_t INTMASK; /*!< (0x34) */
uint32_t INTTYPE_LEVEL; /*!< (0x38) */
uint32_t INT_POLARITY; /*!< (0x3c) */
uint32_t INTSTATUS; /*!< (0x40) */
uint32_t RAW_INTSTATUS; /*!< (0x44) */
uint32_t DEBOUNCE; /*!< (0x48) */
uint32_t PORTA_EOI; /*!< (0x4c) */
uint32_t EXT_PORTS[4]; /*!< (0x50) -A
(0x54) -B
(0x58) -C
(0x5c) -D */
uint32_t LS_SYNC; /*!< (0x60) */
uint32_t ID_CODE; /*!< (0x64) */
uint32_t RESERVED_3; /*!< (0x68) */
uint32_t VER_ID_CODE; /*!< (0x6c) */
uint32_t CONFIG_REG2; /*!< (0x70) */
uint32_t CONFIG_REG1; /*!< (0x74) */
} DW_GPIO_REG, *DW_GPIO_REG_PTR;
/** @} */
/** interrupt handler for each port bit */
typedef struct {
uint32_t int_bit_max_cnt; /*!< max bit count for each port */
DEV_GPIO_HANDLER *int_bit_handler_ptr; /*!< interrupt handler pointer */
} DW_GPIO_BIT_ISR, *DW_GPIO_BIT_ISR_PTR;
/**
* @brief DesignWare GPIO control structure
* @details Structure type for gpio implementation
*/
typedef struct {
uint32_t no; /*!< gpio port number */
DW_GPIO_REG_PTR regs; /*!< gpio port register */
uint32_t intno; /*!< gpio interrupt vector number */
uint32_t valid_bit_mask; /*!< valid bit mask of gpio port */
INT_HANDLER_T int_handler; /*!< gpio interrupt handler */
DW_GPIO_BIT_ISR_PTR gpio_bit_isr; /*!< gpio bit handler struct */
} DW_GPIO_PORT, *DW_GPIO_PORT_PTR;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name DesignWare GPIO Function Declaration
* @brief Contains declarations of designware gpio functions
* @details These are only used in gpio object implementation source file
* @{
*/
extern int32_t dw_gpio_open(DEV_GPIO *gpio_obj, uint32_t dir);
extern int32_t dw_gpio_close(DEV_GPIO *gpio_obj);
extern int32_t dw_gpio_read(DEV_GPIO *gpio_obj, uint32_t *val, uint32_t mask);
extern int32_t dw_gpio_write(DEV_GPIO *gpio_obj, uint32_t val, uint32_t mask);
extern int32_t dw_gpio_control(DEV_GPIO *gpio_obj, uint32_t ctrl_cmd, void *param);
extern int32_t dw_gpio_isr_handler(DEV_GPIO *gpio_obj, void *ptr);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* H_DW_GPIO */

View File

@@ -1,345 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_I2S
#define H_DW_I2S
#include "device/ip_hal/dev_i2s.h"
#include "stdio.h"
/* embARC HAL */
#include "embARC.h"
#include "embARC_debug.h"
/**
* If this header file is included, will indicate that this designware I2S device is used.
*
* sclk - serial clock
* ws - word select
* sd - serial data
* Transmitter - device that places data on the sd line and is clocked by sclk and ws
* Receiver - device that receives data from the sd line and is clocked by sclk and ws
* Master - when configured as a master, DW_apb_i2s initializes the ws signal and supplies the
* clock gating and clock enabling signals
* Slave - when configured as a slave, DW_apb_i2s responds to externally generated sclk and
* ws signals
*/
#define DEVICE_USE_DESIGNWARE_I2S
/**
* @defgroup DEVICE_DW_I2S_INFO DesignWare I2S Related Information
* @ingroup DEVICE_DW_I2S
* @brief Types and macro definitions for designware i2s
* @{
*/
#define DW_I2S_MASTER_SUPPORTED (0x1) /*!< Support Designware I2S Master Mode */
#define DW_I2S_SLAVE_SUPPORTED (0x2) /*!< Support Designware I2S Slave Mode */
#define DW_I2S_CHANNEL0_SUPPORTED (0x1) /*!< Support Designware I2S TX/RX Channel 0 */
#define DW_I2S_CHANNEL1_SUPPORTED (0x2) /*!< Support Designware I2S TX/RX Channel 1 */
#define DW_I2S_CHANNEL2_SUPPORTED (0x4) /*!< Support Designware I2S TX/RX Channel 2 */
#define DW_I2S_CHANNEL3_SUPPORTED (0x8) /*!< Support Designware I2S TX/RX Channel 3 */
#define DW_I2S_DATA_LENGTH_16 (1) /*!< Set the length of data 16 bits else 32 bits>*/
/*!< I2S TX/RX channel */
typedef enum {
DW_I2S_CHANNEL0 = 0, /*!< I2S TX/RX channel 0 */
DW_I2S_CHANNEL1 = 1, /*!< I2S TX/RX channel 1 */
DW_I2S_CHANNEL2 = 2, /*!< I2S TX/RX channel 2 */
DW_I2S_CHANNEL3 = 3 /*!< I2S TX/RX channel 3 */
} DW_I2S_CHANNEL;
/*!< I2S word select line (ws_out) stays in the left or right sample mode */
typedef enum {
DW_I2S_WSS_16_CLK = 0, /*!< 16 clock cycles */
DW_I2S_WSS_24_CLK = 1, /*!< 24 clock cycles */
DW_I2S_WSS_32_CLK = 2 /*!< 32 clock cycles */
} DW_I2S_WSS;
/*!< I2S gating of sclk */
typedef enum {
DW_I2S_SCLKG_NO = 0, /*!< No clock gating */
DW_I2S_SCLKG_12_CLK = 1, /*!< Gate after 12 clock cycles */
DW_I2S_SCLKG_16_CLK = 2, /*!< Gate after 16 clock cycles */
DW_I2S_SCLKG_20_CLK = 3, /*!< Gate after 20 clock cycles */
DW_I2S_SCLKG_24_CLK = 4 /*!< Gate after 24 clock cycles */
} DW_I2S_SCLKG;
#define DW_I2S_GINT_DISABLED (0) /*!< DesignWare interrupt disabled for control I2S irq/fiq */
#define DW_I2S_GINT_ENABLE (1 << 0) /*!< DesignWare interrupt enabled for control I2S irq/fiq */
#define DW_I2S_TXINT_ENABLE (1 << 1) /*!< DesignWare interrupt enabled for control transmit process */
#define DW_I2S_RXINT_ENABLE (1 << 2) /*!< DesignWare interrupt enabled for control transmit process */
/** @} */
/**
* @defgroup DEVICE_DW_I2S_REGSTRUCT DesignWare I2S Register Structure
* @ingroup DEVICE_DW_I2S
* @brief Structure definitions for register
* @details Description of DesignWare I2S register information
* @{
*/
/**
* @brief DesignWare I2S receiver register structure
* @details Detailed struct description of DesignWare I2S receiver
*/
typedef volatile struct {
uint32_t IER; /*!< (0x000) : Enable Register */
uint32_t IRER; /*!< (0x004) : I2S Receiver Block Enable Register */
uint32_t ITER; /*!< (0X008) : I2S Transmitter Block Enable Register*/
uint32_t CER; /*!< (0x00C) : Clock Enable Register */
uint32_t CCR; /*!< (0x010) : Clock Configuration Register */
uint32_t RXFFR; /*!< (0x014) : Receiver Block FIFO Register */
uint32_t TXFFR; /*!< (0x018) : Transmitter Block FIFO Register */
uint32_t RESERVED0; /*!< (0x01C) : Reserved */
uint32_t LRBR0; /*!< (0x020) : Left Receive Buffer 0 */
uint32_t RRBR0; /*!< (0x024) : Right Receive Buffer 0 */
uint32_t RER0; /*!< (0x028) : Receive Enable Register 0 */
uint32_t TER0; /*!< (0x02C) : Transmit Enable Register 0 */
uint32_t RCR0; /*!< (0x030) : Receive Configuration Register 0 */
uint32_t TCR0; /*!< (0x034) : Transmit Configuration Register 0 */
uint32_t ISR0; /*!< (0x038) : Interrupt Status Register 0 */
uint32_t IMR0; /*!< (0x03C) : Interrupt Mask Register 0 */
uint32_t ROR0; /*!< (0x040) : Receive Overrun Register 0 */
uint32_t TOR0; /*!< (0x044) : Transmit Overrun Register 0 */
uint32_t RFCR0; /*!< (0x048) : Receive FIFO Configuration Register 0 */
uint32_t TFCR0; /*!< (0x04C) : Transmit FIFO Configuration Register 0 */
uint32_t RFF0; /*!< (0x050) : Receive FIFO Flush 0 */
uint32_t TFF0; /*!< (0x054) : Transmit FIFO Flush 0 */
uint32_t RESERVED1[2]; /*!< (0x058) : Reserved */
uint32_t LRBR1; /*!< (0x060) : Left Receive Buffer 1 */
uint32_t RRBR1; /*!< (0x064) : Right Receive Buffer 1 */
uint32_t RER1; /*!< (0x068) : Receive Enable Register 1 */
uint32_t TER1; /*!< (0x06C) : Transmit Enable Register 1 */
uint32_t RCR1; /*!< (0x070) : Receive Configuration Register 1 */
uint32_t TCR1; /*!< (0x074) : Transmit Configuration Register 1 */
uint32_t ISR1; /*!< (0x078) : Interrupt Status Register 1 */
uint32_t IMR1; /*!< (0x07C) : Interrupt Mask Register 1 */
uint32_t ROR1; /*!< (0x080) : Receive Overrun Register 1 */
uint32_t TOR1; /*!< (0x084) : Transmit Overrun Register 1 */
uint32_t RFCR1; /*!< (0x088) : Receive FIFO Configuration Register 1 */
uint32_t TFCR1; /*!< (0x08C) : Transmit FIFO Configuration Register 1 */
uint32_t RFF1; /*!< (0x090) : Receive FIFO Flush 1 */
uint32_t TFF1; /*!< (0x094) : Transmit FIFO Flush 1 */
uint32_t RESERVED2[2]; /*!< (0x098) : Reserved */
uint32_t LRBR2; /*!< (0x0A0) : Left Receive Buffer 2 */
uint32_t RRBR2; /*!< (0x0A4) : Right Receive Buffer 2 */
uint32_t RER2; /*!< (0x0A8) : Receive Enable Register 2 */
uint32_t TER2; /*!< (0x0AC) : Transmit Enable Register 2 */
uint32_t RCR2; /*!< (0x0B0) : Receive Configuration Register 2 */
uint32_t TCR2; /*!< (0x0B4) : Transmit Configuration Register 2 */
uint32_t ISR2; /*!< (0x0B8) : Interrupt Status Register 2 */
uint32_t IMR2; /*!< (0x0BC) : Interrupt Mask Register 2 */
uint32_t ROR2; /*!< (0x0C0) : Receive Overrun Register 2 */
uint32_t TOR2; /*!< (0x0C4) : Transmit Overrun Register 2 */
uint32_t RFCR2; /*!< (0x0C8) : Receive FIFO Configuration Register 2 */
uint32_t TFCR2; /*!< (0x0CC) : Transmit FIFO Configuration Register 2 */
uint32_t RFF2; /*!< (0x0D0) : Receive FIFO Flush 2 */
uint32_t TFF2; /*!< (0x0D4) : Transmit FIFO Flush 2 */
uint32_t RESERVED3[2]; /*!< (0x0D8) : Reserved */
uint32_t LRBR3; /*!< (0x0E0) : Left Receive Buffer 3 */
uint32_t RRBR3; /*!< (0x0E4) : Right Receive Buffer 3 */
uint32_t RER3; /*!< (0x0E8) : Receive Enable Register 3 */
uint32_t TER3; /*!< (0x0EC) : Transmit Enable Register 3 */
uint32_t RCR3; /*!< (0x0F0) : Receive Configuration Register 3 */
uint32_t TCR3; /*!< (0x0F4) : Transmit Configuration Register 3 */
uint32_t ISR3; /*!< (0x0F8) : Interrupt Status Register 3 */
uint32_t IMR3; /*!< (0x0FC) : Interrupt Mask Register 3 */
uint32_t ROR3; /*!< (0x100) : Receive Overrun Register 3 */
uint32_t TOR3; /*!< (0x104) : Transmit Overrun Register 3 */
uint32_t RFCR3; /*!< (0x108) : Receive FIFO Configuration Register 3 */
uint32_t TFCR3; /*!< (0x10C) : Transmit FIFO Configuration Register 3 */
uint32_t RFF3; /*!< (0x110) : Receive FIFO Flush 3 */
uint32_t TFF3; /*!< (0x114) : Transmit FIFO Flush 3 */
uint32_t RESERVED4[42]; /*!< (0x118) : Reserved */
uint32_t RXDMA; /*!< (0x1C0) : Receiver Block DMA Register */
uint32_t RRXDMA; /*!< (0x1C4) : Reset Receiver Block DMA Register */
uint32_t TXDMA; /*!< (0x1C8) : Transmitter Block DMA Register */
uint32_t RTXDMA; /*!< (0x1CC) : Reset Transmitter Block DMA Register */
uint32_t RESERVED5[8]; /*!< (0x1D0) : Reserved */
uint32_t I2S_COMP_PARAM_2; /*!< (0x1F0) : Component Parameter 2 Register */
uint32_t I2S_COMP_PARAM_1; /*!< (0x1F4) : Component Parameter 1 Register */
uint32_t I2S_COMP_VERSION; /*!< (0x1F8) : Component Version ID */
uint32_t I2S_COMP_TYPE; /*!< (0x1FC) : DesignWare Component Type */
} DW_I2S_RX_REG, *DW_I2S_RX_REG_PTR;
/**
* @brief Designware I2S transmitter register structure
* @details Detailed struct description of DesignWare I2S transmitter
*/
typedef volatile struct {
uint32_t IER; /*!< (0x000) : Enable Register */
uint32_t IRER; /*!< (0x004) : I2S Receiver Block Enable Register */
uint32_t ITER; /*!< (0X008) : I2S Transmitter Block Enable Register*/
uint32_t CER; /*!< (0x00C) : Clock Enable Register */
uint32_t CCR; /*!< (0x010) : Clock Configuration Register */
uint32_t RXFFR; /*!< (0x014) : Receiver Block FIFO Register */
uint32_t TXFFR; /*!< (0x018) : Transmitter Block FIFO Register */
uint32_t RESERVED0; /*!< (0x01C) : Reserved */
uint32_t LTHR0; /*!< (0x020) : Left Transmit Holding Register 0 */
uint32_t RTHR0; /*!< (0x024) : Right Transmit Holding Register 0 */
uint32_t RER0; /*!< (0x028) : Receive Enable Register 0 */
uint32_t TER0; /*!< (0x02C) : Transmit Enable Register 0 */
uint32_t RCR0; /*!< (0x030) : Receive Configuration Register 0 */
uint32_t TCR0; /*!< (0x034) : Transmit Configuration Register 0 */
uint32_t ISR0; /*!< (0x038) : Interrupt Status Register 0 */
uint32_t IMR0; /*!< (0x03C) : Interrupt Mask Register 0 */
uint32_t ROR0; /*!< (0x040) : Receive Overrun Register 0 */
uint32_t TOR0; /*!< (0x044) : Transmit Overrun Register 0 */
uint32_t RFCR0; /*!< (0x048) : Receive FIFO Configuration Register 0 */
uint32_t TFCR0; /*!< (0x04C) : Transmit FIFO Configuration Register 0 */
uint32_t RFF0; /*!< (0x050) : Receive FIFO Flush 0 */
uint32_t TFF0; /*!< (0x054) : Transmit FIFO Flush 0 */
uint32_t RESERVED1[2]; /*!< (0x058) : Reserved */
uint32_t LTHR1; /*!< (0x060) : Left Transmit Holding Register 1 */
uint32_t RTHR1; /*!< (0x064) : Right Transmit Holding Register 1 */
uint32_t RER1; /*!< (0x068) : Receive Enable Register 1 */
uint32_t TER1; /*!< (0x06C) : Transmit Enable Register 1 */
uint32_t RCR1; /*!< (0x070) : Receive Configuration Register 1 */
uint32_t TCR1; /*!< (0x074) : Transmit Configuration Register 1 */
uint32_t ISR1; /*!< (0x078) : Interrupt Status Register 1 */
uint32_t IMR1; /*!< (0x07C) : Interrupt Mask Register 1 */
uint32_t ROR1; /*!< (0x080) : Receive Overrun Register 1 */
uint32_t TOR1; /*!< (0x084) : Transmit Overrun Register 1 */
uint32_t RFCR1; /*!< (0x088) : Receive FIFO Configuration Register 1 */
uint32_t TFCR1; /*!< (0x08C) : Transmit FIFO Configuration Register 1 */
uint32_t RFF1; /*!< (0x090) : Receive FIFO Flush 1 */
uint32_t TFF1; /*!< (0x094) : Transmit FIFO Flush 1 */
uint32_t RESERVED2[2]; /*!< (0x098) : Reserved */
uint32_t LTHR2; /*!< (0x0A0) : Left Transmit Holding Register 2 */
uint32_t RTHR2; /*!< (0x0A4) : Right Transmit Holding Register 2 */
uint32_t RER2; /*!< (0x0A8) : Receive Enable Register 2 */
uint32_t TER2; /*!< (0x0AC) : Transmit Enable Register 2 */
uint32_t RCR2; /*!< (0x0B0) : Receive Configuration Register 2 */
uint32_t TCR2; /*!< (0x0B4) : Transmit Configuration Register 2 */
uint32_t ISR2; /*!< (0x0B8) : Interrupt Status Register 2 */
uint32_t IMR2; /*!< (0x0BC) : Interrupt Mask Register 2 */
uint32_t ROR2; /*!< (0x0C0) : Receive Overrun Register 2 */
uint32_t TOR2; /*!< (0x0C4) : Transmit Overrun Register 2 */
uint32_t RFCR2; /*!< (0x0C8) : Receive FIFO Configuration Register 2 */
uint32_t TFCR2; /*!< (0x0CC) : Transmit FIFO Configuration Register 2 */
uint32_t RFF2; /*!< (0x0D0) : Receive FIFO Flush 2 */
uint32_t TFF2; /*!< (0x0D4) : Transmit FIFO Flush 2 */
uint32_t RESERVED3[2]; /*!< (0x0D8) : Reserved */
uint32_t LTHR3; /*!< (0x0E0) : Left Transmit Holding Register 3 */
uint32_t RTHR3; /*!< (0x0E4) : Right Transmit Holding Register 3 */
uint32_t RER3; /*!< (0x0E8) : Receive Enable Register 3 */
uint32_t TER3; /*!< (0x0EC) : Transmit Enable Register 3 */
uint32_t RCR3; /*!< (0x0F0) : Receive Configuration Register 3 */
uint32_t TCR3; /*!< (0x0F4) : Transmit Configuration Register 3 */
uint32_t ISR3; /*!< (0x0F8) : Interrupt Status Register 3 */
uint32_t IMR3; /*!< (0x0FC) : Interrupt Mask Register 3 */
uint32_t ROR3; /*!< (0x100) : Receive Overrun Register 3 */
uint32_t TOR3; /*!< (0x104) : Transmit Overrun Register 3 */
uint32_t RFCR3; /*!< (0x108) : Receive FIFO Configuration Register 3 */
uint32_t TFCR3; /*!< (0x10C) : Transmit FIFO Configuration Register 3 */
uint32_t RFF3; /*!< (0x110) : Receive FIFO Flush 3 */
uint32_t TFF3; /*!< (0x114) : Transmit FIFO Flush 3 */
uint32_t RESERVED4[42]; /*!< (0x118) : Reserved */
uint32_t RXDMA; /*!< (0x1C0) : Receiver Block DMA Register */
uint32_t RRXDMA; /*!< (0x1C4) : Reset Receiver Block DMA Register */
uint32_t TXDMA; /*!< (0x1C8) : Transmitter Block DMA Register */
uint32_t RTXDMA; /*!< (0x1CC) : Reset Transmitter Block DMA Register */
uint32_t RESERVED5[8]; /*!< (0x1D0) : Reserved */
uint32_t I2S_COMP_PARAM_2; /*!< (0x1F0) : Component Parameter 2 Register */
uint32_t I2S_COMP_PARAM_1; /*!< (0x1F4) : Component Parameter 1 Register */
uint32_t I2S_COMP_VERSION; /*!< (0x1F8) : Component Version ID */
uint32_t I2S_COMP_TYPE; /*!< (0x1FC) : DesignWare Component Type */
} DW_I2S_TX_REG, *DW_I2S_TX_REG_PTR;
/** @} */
typedef struct {
#ifdef DW_I2S_DATA_LENGTH_16
uint16_t *buf;
#else
uint32_t *buf;
#endif
uint32_t ofs;
uint32_t len;
} DW_I2S_BUFFER, *DW_I2S_BUFFER_PTR;
typedef struct {
uint32_t support_modes; /*!< Supported I2S modes, [DW_I2S_MASTER_SUPPORTED, DW_I2S_SLAVE_SUPPORTED] */
uint32_t fifo_len; /*!< FIFO length (uint: word) */
uint32_t channels; /*!< Suppported channels, [DW_I2S_CHANNEL0_SUPPORTED, DW_I2S_CHANNEL3_SUPPORTED] */
/* Master mode only, clock generation, not available in slave mode */
uint32_t ws_length; /*!< Number of sclk cycles for which ws_out stays, related to WSS */
uint32_t sclk_gate; /*!< I2S gating of sclk */
/* Channel setting */
uint32_t data_res[4]; /*!< Desired audio data resolution, which can be @ref I2S_AUD_DATA_RES, related WLEN */
uint32_t sample_rate[4]; /*!< Audio sampling rate, which can be @ref I2S_AUD_SAMPLE_RATE, related to audio reference clk */
uint32_t intno[4]; /*!< I2S interrupt vector number, bit0-15 tx_emp_intr/rx_da_intr, bit16-31 tx_or_intr/rx_or_intr */
INT_HANDLER_T dw_i2s_int_handler; /*!< I2S interrupt handler */
} DW_I2S_CONFIG, *DW_I2S_CONFIG_PTR;
/**
* @brief Structure definitions for DesignWare I2S control
* @details Structure type for DesignWare I2S implementation
*/
typedef struct {
DW_I2S_RX_REG *dw_i2s_regs; /*!< I2S device registers */
/* Variables which always change during I2S operation */
uint32_t int_status[4]; /*!< I2S interrupt status */
DW_I2S_BUFFER dw_i2s_buf; /*!< I2S read buffer for receive data, left+right data */
} DW_I2S_RX_CTRL, *DW_I2S_RX_CTRL_PTR;
typedef struct {
DW_I2S_TX_REG *dw_i2s_regs; /*!< I2S device registers */
/* Variables which always change during I2S operation */
uint32_t int_status[4]; /*!< I2S interrupt status */
DW_I2S_BUFFER dw_i2s_buf; /*!< I2S write buffer for transmit data, left+right data */
} DW_I2S_TX_CTRL, *DW_I2S_TX_CTRL_PTR;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup DEVICE_DW_I2S_FUNCDLR DesignWare I2S Function Declaration
* @ingroup DEVICE_DW_I2S
* @brief Contains declarations of DesignWare I2S functions
* @details These are only used in I2S object implementation source file
* @{
*/
extern int32_t dw_i2s_open(DEV_I2S *i2s_obj, uint32_t mode, uint32_t param);
extern int32_t dw_i2s_close(DEV_I2S *i2s_obj);
extern int32_t dw_i2s_control(DEV_I2S *i2s_obj, uint32_t ctrl_cmd, void *param);
extern int32_t dw_i2s_write(DEV_I2S *i2s_obj, const void *data, uint32_t len, uint32_t channel);
extern int32_t dw_i2s_read(DEV_I2S *i2s_obj, void *data, uint32_t len, uint32_t channel);
extern void dw_i2s_isr_tx(DEV_I2S *i2s_obj, void *ptr);
extern void dw_i2s_isr_rx(DEV_I2S *i2s_obj, void *ptr);
extern uint32_t dw_i2s_write2(DEV_I2S *i2s_obj, const void *data, uint32_t len, uint32_t channel);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* H_DW_I2S */

View File

@@ -1,124 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_I2S_HAL
#define H_DW_I2S_HAL
#include "device/designware/dw_i2s_hal_cfg.h"
/** IER (I2S Enable Register) */
#define DW_I2S_IER_IEN 1
/** IRER (I2S Receiver Block Enable Register) */
#define DW_I2S_IRER_RXEN 1
/** ITER (I2S Transmitter Block Enable Register) */
#define DW_I2S_ITER_TXEN 1
/** CER (I2S Clock Enable Register) */
#define DW_I2S_CER_CLKEN 1
/** CCR (Clock Configuration Register) */
#define DW_I2S_CCR_WSS(x) ((x & 0x03) << 3)
#define DW_I2S_CCR_SCLKG(x) (x & 0x07)
/** RXFFR (Receiver Block FIFO Reset Register) */
#define DW_I2S_RXFFR_RXFFR 1
/** TXFFR (Transmitter Block FIFO Reset Register) */
#define DW_I2S_TXFFR_TXFFR 1
/** LRBRx (Left Receive Buffer Register) */
#define DW_I2S_LRBR0_LRBR0(x) (x & ((1 << I2S_RX_WORDSIZE_0) - 1))
/** LTHRx (Left Transmit Holding Register) */
#define DW_I2S_LTHR0_LTHR0(x) (x & ((1 << I2S_TX_WORDSIZE_0) - 1))
/** RRBRx (Right Receive Buffer Register) */
#define DW_I2S_RRBR0_RRBR0(x) (x & ((1 << I2S_RX_WORDSIZE_0) - 1))
/** RTHRx (Right Transmit Holding Register) */
#define DW_I2S_RTHR0_RTHR0(x) (x & ((1 << I2S_TX_WORDSIZE_0) - 1))
/** RERx (Receive Enable Register) */
#define DW_I2S_RERX_RXCHENX 1
/** TERx (Transmit Enable Register) */
#define DW_I2S_TERX_TXCHENX 1
/** RCRx (Receive Configuration Register) */
#define DW_I2S_RCRX_WLEN(x) (x & 0x07)
/** TCRx (Transmit Configuration Register) */
#define DW_I2S_TCRX_WLEN(x) (x & 0x07)
/** ISRx (Interrupt Status Register) */
#define DW_I2S_ISRX_TXFO (1 << 5)
#define DW_I2S_ISRX_TXFE (1 << 4)
#define DW_I2S_ISRX_RXFO (1 << 1)
#define DW_I2S_ISRX_RXDA 1
/** IMRx (Interrupt Mask Register) */
#define DW_I2S_IMRX_TXFOM (1 << 5)
#define DW_I2S_IMRX_TXFEM (1 << 4)
#define DW_I2S_IMRX_RXFOM (1 << 1)
#define DW_I2S_IMRX_RXDAM 1
/** RORx (Receive Overrun Register) */
#define DW_I2S_RORX_RXCHO 1
/** TORx (Transmit Overrun Register) */
#define DW_I2S_TORX_TXCHO 1
/** RFCRx (Receive FIFO Configuration Register) */
#define DW_I2S_RFCRX_RXCHDT(x) (x & 0x0f)
/** TFCRx (Transmit FIFO Configuration Register) */
#define DW_I2S_TFCRX_TXCHET(x) (x & 0x0f)
/** RFFx (Receive FIFO Flush Register) */
#define DW_I2S_RFFX_RXCHFR 1
/** TFFx (Transmit FIFO Flush Register) */
#define DW_I2S_TFFX_TXCHFR 1
/** RXDMA (Receiver Block DMA Register) */
#define DW_I2S_RXDMA_RXDMA (x & ((1 << APB_DATA_BUS_WIDTH) - 1))
/** RRXDMA (Reset Receiver Block DMA Register) */
#define DW_I2S_RRXDMA_RRXDMA 1
/** TXDMA (Transmitter Block DMA Register) */
#define DW_I2S_TXDMA_TXDMA (x & ((1 << APB_DATA_BUS_WIDTH) - 1))
/** RTXDMA (Reset Transmitter Block DMA Register) */
#define DW_I2S_RTXDMA_RTXDMA 1
#endif /* H_DW_I2S_HAL */

View File

@@ -1,158 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_I2S_HAL_CFG
#define H_DW_I2S_HAL_CFG
/** Top-level parameters */
/** APB data bus width, 8, 16 or 32 bits */
#ifndef APB_DATA_BUS_WIDTH
#define APB_DATA_BUS_WIDTH 32
#endif
/** Receiver block enabled, false (0) or ture (1) */
#ifndef I2S_RECEIVER_BLOCK
#define I2S_RECEIVER_BLOCK 1
#endif
/** Number of receive channels, 1, 2, 3 or 4 channels */
#ifndef I2S_RX_CHANNELS
#define I2S_RX_CHANNELS 1
#endif
/** Transmitter block enabled, false (0) or ture (1) */
#ifndef I2S_TRANSMITTER_BLOCK
#define I2S_TRANSMITTER_BLOCK 1
#endif
/** Number of transmit channels, 1, 2, 3 or 4 channels */
#ifndef I2S_TX_CHANNELS
#define I2S_TX_CHANNELS 1
#endif
/** Set an I2S master, false (0) or ture (1) */
#ifndef I2S_MODE_EN
#define I2S_MODE_EN 1
#endif
/** FIFO depth for RX and TX channels, 2, 4, 8 and 16 words */
#ifndef I2S_FIFO_DEPTH_GLOBAL
#define I2S_FIFO_DEPTH_GLOBAL 16
#endif
/** Word select length, 0 - 16 sclk cycles, 1 - 24 sclk cycles, 2 - 32 sclk cycles */
#ifndef I2S_WS_LENGTH
#define I2S_WS_LENGTH 32
#endif
/** Serial clock gating, 0 - no gating, 1 - 12 clock cycles, 2 - 16 clock cycles,
* 3 - 20 clock cycles, 4 - 24 clock cycles
*/
#ifndef I2S_SCLK_GATE
#define I2S_SCLK_GATE 4
#endif
/** Multiple interrupt output ports present, false (0) or ture (1) */
#ifndef I2S_INTERRUPT_SIGNALS
#define I2S_INTERRUPT_SIGNALS 0
#endif
/** Polarity of interrupt signals is acitve high, false (0) or ture (1) */
#ifndef I2S_INTR_POL
#define I2S_INTR_POL 1
#endif
/** Clock domain crossing synchronization depth
* 1 - two-stage synchronization; first stage negative edge, second stage positive edge
* 2 - two-stage synchronization; both stages positive edge
* 3 - three-stage synchronization; all stage positive edge
*/
#ifndef I2S_SYNC_DEPTH
#define I2S_SYNC_DEPTH 2
#endif
/** Receiver channel parameters */
/** Receiver block DMA enabled, false (0) or ture (1) */
#ifndef I2S_RX_DMA
#define I2S_RX_DMA 0
#endif
/** Max audio resolution - receive channel x, 12, 16, 20, 24 or 32 bits
* only support 0 in this version
*/
#ifndef I2S_RX_WORDSIZE_0
#define I2S_RX_WORDSIZE_0 16
#endif
/** FIFO depth - receive channel x, 2, 4, 8 and 16 words
* only support 0 in this version
*/
#ifndef I2S_RX_FIFO_0
#define I2S_RX_FIFO_0 I2S_FIFO_DEPTH_GLOBAL
#endif
/** RX FIFO data available trigger, 0 to I2S_RX_FIFO_x - 1; maximum = 15
* only support 0 in this version
*/
#ifndef I2S_RX_FIFO_THRE_0
#define I2S_RX_FIFO_THRE_0 7
#endif
/** Transmitter channel parameters */
/** Receiver block DMA enabled, false (0) or ture (1) */
#ifndef I2S_TX_DMA
#define I2S_TX_DMA 0
#endif
/** Max audio resolution - transmit channel x, 12, 16, 20, 24 or 32 bits
* only support 0 in this version
*/
#ifndef I2S_TX_WORDSIZE_0
#define I2S_TX_WORDSIZE_0 16
#endif
/** FIFO depth - transmit channel x, 2, 4, 8 and 16 words
* only support 0 in this version
*/
#ifndef I2S_TX_FIFO_0
#define I2S_TX_FIFO_0 I2S_FIFO_DEPTH_GLOBAL
#endif
/** TX FIFO data available trigger, 0 to I2S_TX_FIFO_x - 1; maximum = 15
* only support 0 in this version
*/
#ifndef I2S_TX_FIFO_THRE_0
#define I2S_TX_FIFO_THRE_0 7
#endif
#endif /* H_DW_I2S_HAL_CFG */

View File

@@ -1,208 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_IIC
#define H_DW_IIC
#include "device/ip_hal/dev_iic.h"
#include "arc/arc_exception.h"
/**
* If this header file is included,
* will indicate that this designware iic device
* is used
*/
#define DEVICE_USE_DESIGNWARE_IIC
#define DW_IIC_MASTER_SUPPORTED (0x1) /*!< Support Designware IIC Master Mode */
#define DW_IIC_SLAVE_SUPPORTED (0x2) /*!< Support Designware IIC Slave Mode */
/*!< Support Designware IIC Both Master and Slave Mode */
#define DW_IIC_BOTH_SUPPORTED (DW_IIC_MASTER_SUPPORTED | DW_IIC_SLAVE_SUPPORTED)
#define DW_IIC_INVALID_INTNO (DEV_INTNO_INVALID)
enum {
DW_IIC_CAP_LOADING_100PF = 0,
DW_IIC_CAP_LOADING_400PF
};
/**
* @defgroup DEVICE_DW_IIC_REGSTRUCT DesignWare IIC Register Structure
* @ingroup DEVICE_DW_I2S
* @brief Structure definitions for DesignWare IIC register
* @details Detailed struct description of DesignWare IIC
* block register information, implementation of DEV_IIC_INFO::iic_regs
* @{
*/
typedef volatile struct {
uint32_t IC_CON; /*!< (0x00) : IIC control */
uint32_t IC_TAR; /*!< (0x04) : IIC target address */
uint32_t IC_SAR; /*!< (0x08) : IIC slave address */
uint32_t IC_HS_MADDR; /*!< (0x0c) : IIC HS Master Mode Code address */
uint32_t IC_DATA_CMD; /*!< (0x10) : IIC Rx/Tx Data Buffer and Command */
uint32_t IC_SS_SCL_HCNT; /*!< (0x14) : Standard Speed IIC clock SCL High Count */
uint32_t IC_SS_SCL_LCNT; /*!< (0x18) : Standard Speed IIC clock SCL Low Count */
uint32_t IC_FS_SCL_HCNT; /*!< (0x1c) : Fast Speed IIC clock SCL Low Count */
uint32_t IC_FS_SCL_LCNT; /*!< (0x20) : Fast Speed IIC clock SCL Low Count */
uint32_t IC_HS_SCL_HCNT; /*!< (0x24) : High Speed IIC clock SCL Low Count */
uint32_t IC_HS_SCL_LCNT; /*!< (0x28) : High Speed IIC clock SCL Low Count */
uint32_t IC_INTR_STAT; /*!< (0x2c) : IIC Interrupt Status */
uint32_t IC_INTR_MASK; /*!< (0x30) : IIC Interrupt Mask */
uint32_t IC_RAW_INTR_STAT; /*!< (0x34) : IIC Raw Interrupt Status */
uint32_t IC_RX_TL; /*!< (0x38) : IIC Receive FIFO Threshold */
uint32_t IC_TX_TL; /*!< (0x3c) : IIC Transmit FIFO Threshold */
uint32_t IC_CLR_INTR; /*!< (0x40) : Clear combined and Individual Interrupts */
uint32_t IC_CLR_RX_UNDER; /*!< (0x44) : Clear RX_UNDER Interrupt */
uint32_t IC_CLR_RX_OVER; /*!< (0x48) : Clear RX_OVER Interrupt */
uint32_t IC_CLR_TX_OVER; /*!< (0x4c) : Clear TX_OVER Interrupt */
uint32_t IC_CLR_RD_REQ; /*!< (0x50) : Clear RQ_REQ Interrupt */
uint32_t IC_CLR_TX_ABRT; /*!< (0x54) : Clear TX_ABRT Interrupt */
uint32_t IC_CLR_RX_DONE; /*!< (0x58) : Clear RX_DONE Interrupt */
uint32_t IC_CLR_ACTIVITY; /*!< (0x5c) : Clear ACTIVITY Interrupt */
uint32_t IC_CLR_STOP_DET; /*!< (0x60) : Clear STOP_DET Interrupt */
uint32_t IC_CLR_START_DET; /*!< (0x64) : Clear START_DET Interrupt */
uint32_t IC_CLR_GEN_CALL; /*!< (0x68) : Clear GEN_CALL Interrupt */
uint32_t IC_ENABLE; /*!< (0x6c) : IIC Enable */
uint32_t IC_STATUS; /*!< (0x70) : IIC Status */
uint32_t IC_TXFLR; /*!< (0x74) : Transmit FIFO Level Register */
uint32_t IC_RXFLR; /*!< (0x78) : Receive FIFO Level Register */
uint32_t IC_SDA_HOLD; /*!< (0x7c) : SDA Hold Time Length Reg */
uint32_t IC_TX_ABRT_SOURCE; /*!< (0x80) : IIC Transmit Abort Status Reg */
uint32_t IC_SLV_DATA_NACK_ONLY; /*!< (0x84) : Generate SLV_DATA_NACK Register */
uint32_t IC_DMA_CR; /*!< (0x88) : DMA Control Register */
uint32_t IC_DMA_TDLR; /*!< (0x8c) : DMA Transmit Data Level */
uint32_t IC_DMA_RDLR; /*!< (0x90) : DMA Receive Data Level */
uint32_t IC_SDA_SETUP; /*!< (0x94) : SDA Setup Register */
uint32_t IC_ACK_GENERAL_CALL; /*!< (0x98) : ACK General Call Register */
uint32_t IC_ENABLE_STATUS; /*!< (0x9c) : Enable Status Register */
uint32_t IC_FS_SPKLEN; /*!< (0xa0) : ISS and FS spike suppression limit */
uint32_t IC_HS_SPKLEN; /*!< (0xa4) : HS spike suppression limit */
uint32_t RESERVED[19]; /*!< (0xa8) : Reserved */
uint32_t IC_COMP_PARAM_1; /*!< (0xf4) : Component Parameter Register */
uint32_t IC_COMP_VERSION; /*!< (0xf8) : Component Version ID Reg */
uint32_t IC_COMP_TYPE; /*!< (0xfc) : Component Type Reg */
} DW_IIC_REG, *DW_IIC_REG_PTR;
/** @} */
/** Spike Suppression Limit Configurations */
typedef struct {
uint32_t fs_spklen; /*!< value for IC_FS_SPKLEN, Tsp for fast mode is 50ns */
uint32_t hs_spklen; /*!< value for IC_HS_SPKLEN, Tsp for high-speed mode is 10ns */
} DW_IIC_SPKLEN, *DW_IIC_SPKLEN_PTR;
/** IIC Clock SCL High and Low Count Configurations for Different Speed */
typedef struct {
uint32_t ss_scl_hcnt; /*!< value for IC_SS_SCL_HCNT */
uint32_t ss_scl_lcnt; /*!< value for IC_SS_SCL_LCNT */
uint32_t fs_scl_hcnt; /*!< value for IC_FS_SCL_HCNT */
uint32_t fs_scl_lcnt; /*!< value for IC_FS_SCL_LCNT */
uint32_t hs_scl_hcnt; /*!< value for IC_HS_SCL_HCNT */
uint32_t hs_scl_lcnt; /*!< value for IC_HS_SCL_LCNT */
} DW_IIC_SCL_CNT, *DW_IIC_SCL_CNT_PTR;
#define DW_IIC_GINT_DISABLED (0) /*!< designware interrupt disabled for control iic irq/fiq */
#define DW_IIC_GINT_ENABLE (1 << 0) /*!< designware interrupt enabled for control iic irq/fiq */
#define DW_IIC_TXINT_ENABLE (1 << 1) /*!< designware interrupt enabled for control transmit process */
#define DW_IIC_RXINT_ENABLE (1 << 2) /*!< designware interrupt enabled for control transmit process */
typedef struct {
DEV_BUFFER *buf;
uint32_t ofs;
uint32_t len;
} DW_IIC_BUFFER, *DW_IIC_BUFFER_PTR;
/**
* @brief Structure definitions for DesignWare IIC control
* @details implement of DEV_IIC_INFO::iic_ctrl
*/
typedef struct {
DW_IIC_REG *dw_iic_regs; /*!< iic device registers */
/* Variables which should be set during object implementation */
uint32_t ic_clkhz; /*!< IC clock in HZ */
uint32_t ic_caploading; /*!< I2C Bus cap loading pf */
uint32_t support_modes; /*!< supported iic modes */
uint32_t tx_fifo_len; /*!< transmit fifo length */
uint32_t rx_fifo_len; /*!< receive fifo length */
uint32_t iic_master_code; /*!< value for IC_HS_MADDR */
uint32_t retry_cnt; /*!< retry count for TX or RX */
uint32_t intno; /*!< iic interrupt vector number */
INT_HANDLER_T dw_iic_int_handler; /*!< iic interrupt handler */
DW_IIC_SPKLEN iic_spklen; /*!< iic spike suppression length settings */
DW_IIC_SCL_CNT iic_scl_cnt; /*!< iic scl count settings */
/* Variables which always change during iic operation */
uint32_t int_status; /*!< iic interrupt status */
uint32_t iic_tx_over; /*!< iic tx overflow count */
uint32_t iic_rx_over; /*!< iic rx overflow count */
DW_IIC_BUFFER dw_iic_rxbuf; /*!< iic read buffer for receive data */
} DW_IIC_CTRL, *DW_IIC_CTRL_PTR;
/*!< One possible value for @ref DW_IIC_CTRL::retry_cnt */
#define DW_IIC_MAX_RETRY_COUNT (100000)
#define DW_IIC_FS_SPKLEN_NS (50)
#define DW_IIC_HS_SPKLEN_NS (10)
#define MIN_DW_IIC_SS_SCL_LCNT(spklen) ((spklen) + 7)
#define MIN_DW_IIC_FS_SCL_LCNT(spklen) ((spklen) + 7)
#define MIN_DW_IIC_SS_SCL_HCNT(spklen) ((spklen) + 5)
#define MIN_DW_IIC_FS_SCL_HCNT(spklen) ((spklen) + 5)
#define MIN_DW_IIC_HS_SCL_LCNT(spklen) ((spklen) + 7)
#define MIN_DW_IIC_HS_SCL_HCNT(spklen) ((spklen) + 5)
#define MIN_DW_IIC_SS_HIGH_TIME_NS (4000)
#define MIN_DW_IIC_SS_LOW_TIME_NS (4700)
#define MIN_DW_IIC_FS_HIGH_TIME_NS (600)
#define MIN_DW_IIC_FS_LOW_TIME_NS (1300)
#define MIN_DW_IIC_HS_100PF_HIGH_TIME_NS (60)
#define MIN_DW_IIC_HS_100PF_LOW_TIME_NS (160)
#define MIN_DW_IIC_HS_400PF_HIGH_TIME_NS (120)
#define MIN_DW_IIC_HS_400PF_LOW_TIME_NS (320)
#ifdef __cplusplus
extern "C" {
#endif
extern int32_t dw_iic_open(DEV_IIC *iic_obj, uint32_t mode, uint32_t param);
extern int32_t dw_iic_close(DEV_IIC *iic_obj);
extern int32_t dw_iic_control(DEV_IIC *iic_obj, uint32_t ctrl_cmd, void *param);
extern int32_t dw_iic_write(DEV_IIC *iic_obj, const void *data, uint32_t len);
extern int32_t dw_iic_read(DEV_IIC *iic_obj, void *data, uint32_t len);
extern void dw_iic_isr(DEV_IIC *iic_obj, void *ptr);
#ifdef __cplusplus
}
#endif
#endif /* H_DW_IIC */

View File

@@ -1,174 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_IIC_HAL
#define H_DW_IIC_HAL
#include "device/designware/dw_iic_hal_cfg.h"
/** Enable Designware IIC */
#define DW_IIC_ENABLE (1)
/** Disable Designware IIC */
#define DW_IIC_DISABLE (0)
/** Stop Condition issue after this byte */
#define IC_DATA_CMD_STOP (1 << 9)
/** Restart Condition issue after this byte */
#define IC_DATA_CMD_RESTART (1 << 10)
/** No Restart or stop condition after this byte */
#define IC_DATA_CMD_NONE (0)
/** Perform a write request */
#define IC_DATA_CMD_WRITE_REQ (0)
/** Perform a read request */
#define IC_DATA_CMD_READ_REQ (1 << 8)
/** Fields of IC_CON register */
/* DW_APB I2C IP Config Dependencies. */
#if DW_IIC_ALLOW_RESTART
#define IC_CON_RESTART_EN (1 << 5)
#else
#define IC_CON_RESTART_EN (0x00)
#endif
/* Master Addressing Mode Config */
#if DW_IIC_MST_10_BIT_ADDR_SUPPORT
#define MST_10_BIT_ADDR_MODE (1 << 4)
#define IC_10BITADDR_MASTER (1 << 12)
#else
#define MST_10_BIT_ADDR_MODE (0x00)
#define IC_10BITADDR_MASTER (0x00)
#endif
/* Slave Addressing Mode Config */
#if DW_IIC_SLV_10_BIT_ADDR_SUPPORT
#define SLV_10_BIT_ADDR_MODE (1 << 3)
#else
#define SLV_10_BIT_ADDR_MODE (0x00)
#endif
#if DW_IIC_SPECIAL_START_BYTE
#define IC_TAR_SPECIAL (1 << 11)
#define IC_TAR_GC_OR_START (1 << 10)
#else
#define IC_TAR_SPECIAL (0x00)
#define IC_TAR_GC_OR_START (0x00)
#endif
/** 7bit IIC address mask for target address register */
#define IC_TAR_7BIT_ADDR_MASK (0x7F)
/** 7bit IIC address mask for slave address register */
#define IC_SAR_7BIT_ADDR_MASK (0x7F)
/** 10bit IIC address mask for target address register */
#define IC_TAR_10BIT_ADDR_MASK (0x3FF)
/** 10bit IIC address mask for slave address register */
#define IC_SAR_10BIT_ADDR_MASK (0x3FF)
/** Speed modes of IC_CON */
#define IC_CON_SPEED_MASK (0x6)
#define IC_CON_SPEED_STANDARD (0x2)
#define IC_CON_SPEED_FAST (0x4)
#define IC_CON_SPEED_HIGH (0x6)
/** Working mode of IC_CON */
#define IC_CON_MST_SLV_MODE_MASK (0x41)
#define IC_CON_ENA_MASTER_MODE (0x41)
#define IC_CON_ENA_SLAVE_MODE (0)
/* IIC interrupt control */
#define IC_INT_DISABLE_ALL (0x0)
#define IC_INT_ENABLE_ALL (0x7FF)
/* Interrupt Register Fields */
#define IC_INTR_STAT_GEN_CALL (1 << 11)
#define IC_INTR_STAT_START_DET (1 << 10)
#define IC_INTR_STAT_STOP_DET (1 << 9)
#define IC_INTR_STAT_ACTIVITY (1 << 8)
#define IC_INTR_STAT_RX_DONE (1 << 7)
#define IC_INTR_STAT_TX_ABRT (1 << 6)
#define IC_INTR_STAT_RD_REQ (1 << 5)
#define IC_INTR_STAT_TX_EMPTY (1 << 4)
#define IC_INTR_STAT_TX_OVER (1 << 3)
#define IC_INTR_STAT_RX_FULL (1 << 2)
#define IC_INTR_STAT_RX_OVER (1 << 1)
#define IC_INTR_STAT_RX_UNDER (1 << 0)
/* Interrupt enable mask as master */
#define IC_INT_MST_TX_ENABLE (IC_INTR_STAT_TX_EMPTY | IC_INTR_STAT_TX_OVER | IC_INTR_STAT_TX_ABRT)
#define IC_INT_MST_RX_ENABLE (IC_INTR_STAT_TX_EMPTY | IC_INTR_STAT_RX_FULL | IC_INTR_STAT_RX_OVER | IC_INTR_STAT_RX_UNDER | IC_INTR_STAT_TX_ABRT)
/* Interrupt enable mask as master */
#define IC_INT_SLV_COMMON_ENABLE (IC_INTR_STAT_START_DET | IC_INTR_STAT_STOP_DET)
#define IC_INT_SLV_TX_ENABLE (IC_INTR_STAT_RD_REQ | IC_INTR_STAT_TX_ABRT)
#define IC_INT_SLV_RX_ENABLE (IC_INTR_STAT_RX_FULL | IC_INTR_STAT_RX_OVER | IC_INTR_STAT_RX_UNDER)
/* IC_ENABLE_STATUS Bits */
#define IC_ENABLE_STATUS_IC_EN (1 << 0)
#define IC_ENABLE_STATUS_SLV_DIS (1 << 1)
#define IC_ENABLE_STATUS_SLV_RX_LOST (1 << 2)
/* IIC TX & RX threshold settings */
#define IIC_TX_THRESHOLD (0)
#define IIC_RX_THRESHOLD (0)
/* DW_APB IIC (DW_IC_STATUS) Status Register Fields. */
#define IC_STATUS_ACTIVITY (0x01)
#define IC_STATUS_TFNF (0x02) /* (1 << 1) */
#define IC_STATUS_TFE (0x04) /* (1 << 2) */
#define IC_STATUS_RFNE (0x08) /* (1 << 3) */
#define IC_STATUS_RFF (0x10) /* (1 << 4) */
#define IC_STATUS_MASTER_ACT (0x20) /* (1 << 5) */
#define IC_STATUS_SLAVE_ACT (0x40) /* (1 << 6) */
/* IC_TX_ABRT_SOURCE Register Bit Fields */
#define IC_TX_ABRT_7B_ADDR_NOACK (1 << 0)
#define IC_TX_ABRT_10ADDR1_NOACK (1 << 1)
#define IC_TX_ABRT_10ADDR2_NOACK (1 << 2)
#define IC_TX_ABRT_TXDATA_NOACK (1 << 3)
#define IC_TX_ABRT_GCALL_NOACK (1 << 4)
#define IC_TX_ABRT_GCALL_READ (1 << 5)
#define IC_TX_ABRT_HS_ACKDET (1 << 6)
#define IC_TX_ABRT_SBYTE_ACKDET (1 << 7)
#define IC_TX_ABRT_HS_NORSTRT (1 << 8)
#define IC_TX_ABRT_SBYTE_NORSTRT (1 << 9)
#define IC_TX_ABRT_10B_RD_NORSTRT (1 << 10)
#define IC_TX_ABRT_MASTER_DIS (1 << 11)
#define IC_TX_ABRT_ARB_LOST (1 << 12)
#define IC_TX_ABRT_SLVFLUSH_TXFIFO (1 << 13)
#define IC_TX_ABRT_SLV_ARBLOST (1 << 14)
#define IC_TX_ABRT_SLVRD_INTX (1 << 15)
/* Combined bits for iic abort source as master */
#define IIC_MST_ABRT_ADDR_NOACK (IC_TX_ABRT_7B_ADDR_NOACK | IC_TX_ABRT_10ADDR1_NOACK | IC_TX_ABRT_10ADDR1_NOACK)
#define IIC_MST_ABRT_LOST_BUS (IC_TX_ABRT_ARB_LOST)
#define IIC_MST_ABRT_DATA_NOACK (IC_TX_ABRT_TXDATA_NOACK)
/* Combined bits for iic abort source as slave */
#define IIC_SLV_ABRT_LOST_BUS (IC_TX_ABRT_ARB_LOST | IC_TX_ABRT_SLV_ARBLOST)
#endif /* H_DW_IIC_HAL */

View File

@@ -1,62 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_IIC_HAL_CFG
#define H_DW_IIC_HAL_CFG
#ifndef DW_IIC_ALLOW_RESTART
#define DW_IIC_ALLOW_RESTART (1) /*!< allow restart configuration */
#endif
#ifdef DW_IIC_SPECIAL_START_BYTE
#define DW_IIC_SPECIAL_START_BYTE (0) /*!< SPECIAL bit enable in IC_TAR */
#endif
#ifndef DW_IIC_MST_10_BIT_ADDR_SUPPORT
#define DW_IIC_MST_10_BIT_ADDR_SUPPORT (1) /*!< enable 10-bit address mode */
#endif
#ifdef DW_IIC_SLV_10_BIT_ADDR_SUPPORT
#define DW_IIC_SLV_10_BIT_ADDR_SUPPORT (1) /*!< slave 10-bit addressing mode */
#endif
#ifndef DW_IIC_DYNAMIC_TAR_UPDATE_SUPPORT
#define DW_IIC_DYNAMIC_TAR_UPDATE_SUPPORT (0) /*!< Dynamic target address update support */
#endif
#ifndef DW_IIC_DISABLE_MAX_T_POLL_CNT
#define DW_IIC_DISABLE_MAX_T_POLL_CNT (1250) /*!< Timeout count, approximate to be 25us in 50MHz CPU @ Standard mode */
#endif
#ifndef DW_IIC_CALC_FIFO_LEN_ENABLE
#define DW_IIC_CALC_FIFO_LEN_ENABLE (1) /*!< Default enable calculate fifo length */
#endif
#endif /* H_DW_IIC_HAL_CFG */

View File

@@ -1,169 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_NIST_TRNG
#define H_DW_NIST_TRNG
#include "device/ip_hal/dev_trng.h"
#include "arc/arc_exception.h"
#ifdef TRNG_VERSION_NIST
#define DW_TRNG_GINT_DISABLE (0)
#define DW_TRNG_GINT_ENABLE (1 << 31)
#define DW_TRNG_INT_ZEROIZED_ENABLE (1 << 0)
#define DW_TRNG_INT_KAT_ENABLE (1 << 1)
#define DW_TRNG_INT_NOISE_RDY_ENABLE (1 << 2)
#define DW_TRNG_INT_ALARMS_ENABLE (1 << 3)
#define DW_TRNG_INT_DONE_ENABLE (1 << 4)
#define DW_TRNG_INT_ALL (0x8000001F)
#define DW_TRNG_ISTATE_ALL (0x1F)
#define DW_TRNG_INVALID_INTNO (DEV_INTNO_INVALID)
// DesignWare NIST TRNG register structure
typedef volatile struct dw_nist_trng_reg {
uint32_t CTRL; // (0x0)
uint32_t MODE; // (0x4)
union {
uint32_t SMODE; // (0x8)
struct {
uint32_t nonce : 1;
uint32_t secure_en : 1;
uint32_t max_rejecets : 8;
uint32_t rsvd : 22;
} smode;
};
union {
uint32_t STAT; // (0xC)
struct {
uint32_t last_cmd : 4;
uint32_t sec_alg : 1;
uint32_t nonce_mode : 1;
uint32_t secure : 1;
uint32_t drbg_state : 2;
uint32_t rsvd : 22;
uint32_t busy : 1;
} stat;
};
union {
uint32_t IE; // (0x10)
struct {
uint32_t zeroized : 1;
uint32_t kat_completed : 1;
uint32_t noise_rdy : 1;
uint32_t alarms : 1;
uint32_t done : 1;
uint32_t rsvd : 26;
uint32_t glbl : 1;
} ie;
};
union {
uint32_t ISTAT; // (0x14)
struct {
uint32_t zeroized : 1;
uint32_t kat_completed : 1;
uint32_t noise_rdy : 1;
uint32_t alarms : 1;
uint32_t done : 1;
uint32_t rsvd : 27;
} istat;
};
union {
uint32_t ALARMS; // (0x18)
struct {
uint32_t failed_test_id : 4;
uint32_t illegal_cmd_seq : 1;
uint32_t rsvd : 27;
} alarms;
};
uint32_t COREKIT_REL; // (0x1C)
uint32_t FEATURES; // (0x20)
uint32_t RAND0; // (0x24)
uint32_t RAND1; // (0x28)
uint32_t RAND2; // (0x2C)
uint32_t RAND3; // (0x30)
uint32_t NPA_DATA0; // (0x34)
uint32_t NPA_DATA1; // (0x38)
uint32_t NPA_DATA2; // (0x3C)
uint32_t NPA_DATA3; // (0x40)
uint32_t NPA_DATA4; // (0x44)
uint32_t NPA_DATA5; // (0x48)
uint32_t NPA_DATA6; // (0x4C)
uint32_t NPA_DATA7; // (0x50)
uint32_t NPA_DATA8; // (0x54)
uint32_t NPA_DATA9; // (0x58)
uint32_t NPA_DATA10; // (0x5C)
uint32_t NPA_DATA11; // (0x60)
uint32_t NPA_DATA12; // (0x64)
uint32_t NPA_DATA13; // (0x68)
uint32_t NPA_DATA14; // (0x6C)
uint32_t NPA_DATA15; // (0x70)
uint32_t SEED0; // (0x74)
uint32_t SEED1; // (0x78)
uint32_t SEED2; // (0x7C)
uint32_t SEED3; // (0x80)
uint32_t SEED4; // (0x84)
uint32_t SEED5; // (0x88)
uint32_t SEED6; // (0x8C)
uint32_t SEED7; // (0x90)
uint32_t SEED8; // (0x94)
uint32_t SEED9; // (0x98)
uint32_t SEED10; // (0x9C)
uint32_t SEED11; // (0xA0)
uint32_t IA_RDATA; // (0xA4)
uint32_t IA_WDATA; // (0xA8)
uint32_t IA_ADDR; // (0xAC)
uint32_t IA_CMD; // (0xB0)
} DW_TRNG_REG, *DW_TRNG_REG_PTR;
typedef struct dw_trng_ctrl {
DW_TRNG_REG_PTR dw_trng_regs; /*!< dw trng register */
uint32_t intno; /*!< interrupt vector number */
INT_HANDLER_T dw_trng_int_handler; /*!< interrupt handler */
uint32_t int_status; /*!< interrupt status */
} DW_TRNG_CTRL, *DW_TRNG_CTRL_PTR;
#ifdef __cplusplus
extern "C" {
#endif
extern int32_t dw_trng_open(DEV_TRNG_PTR trng_obj);
extern int32_t dw_trng_close(DEV_TRNG_PTR trng_obj);
extern int32_t dw_trng_control(DEV_TRNG_PTR trng_obj, uint32_t ctrl_cmd, void *param);
extern int32_t dw_trng_read(DEV_TRNG_PTR trng_obj, uint32_t *data_buf);
extern void dw_trng_isr(DEV_TRNG_PTR trng_obj, void *ptr);
#ifdef __cplusplus
}
#endif
#endif /* TRNG_VERSION_NIST */
#endif /* H_DW_NIST_TRNG */

View File

@@ -1,106 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_PWM_TIMER
#define H_DW_PWM_TIMER
#include "device/ip_hal/dev_pwm_timer.h"
#include "arc/arc_exception.h"
#define DW_PWM_TIMER_CH_MAX_COUNT 8
#define DW_PWM_TIMER_INVALID_INTNO (DEV_INTNO_INVALID)
/**
* @name Structure definitions for DesignWare PWM_TIMER Register
* @brief Contains definitions of DesignWare PWM_TIMER register structure
* @{
*/
typedef volatile struct {
uint32_t LOAD_COUNT; /*!< Value to be loaded into Timer */
uint32_t CURRENT_VALUE; /*!< Current Value of Timer */
uint32_t CONTROL_REG; /*!< Control Register for Timer */
uint32_t EOI; /*!< Clears the interrupt from Timer */
uint32_t INT_STATUS; /*!< Contains the interrupt status for Timer */
} CH_CTRL;
typedef volatile struct {
CH_CTRL CTRL[DW_PWM_TIMER_CH_MAX_COUNT]; /*!< (0x00 ~ 0x9C) */
uint32_t PWM_TIMERS_INT_STATUS; /*!< (0xA0) Contains the interrupt status of all timers in the component.*/
uint32_t PWM_TIMERS_EOI; /*!< (0xA4) Read return all zeroes (0) and clears all active interrupts.*/
uint32_t PWM_TIMERS_RAWINT_STATUS; /*!< (0xA8) Contains the unmasked interrupt status of all timers in the component.*/
uint32_t PWM_TIMERS_COMP_VER; /*!< (0xAC) Current revision number of the DW_apb_timers component.*/
uint32_t LOAD_COUNT2[DW_PWM_TIMER_CH_MAX_COUNT]; /*!< (0xB0 ~ 0xCC) Value to be loaded into Timer when toggle output changes from 0 to 1*/
} DW_PWM_TIMER_REG, *DW_PWM_TIMER_REG_PTR;
/** @} */
/** interrupt handler for each pwm_timer channel */
typedef struct {
uint32_t int_ch_max_cnt; /*!< max channel count for each pwm_timer group */
DEV_PWM_TIMER_HANDLER *int_ch_handler_ptr; /*!< interrupt handler pointer */
} DW_PWM_TIMER_CH_ISR, *DW_PWM_TIMER_CH_ISR_PTR;
/**
* @brief Structure definitions for DesignWare PWM_TIMER control
* @details Structure type for DesignWare PWM_TIMER implementation
*/
typedef struct {
uint32_t id; /*!< pwm_timer group id */
DW_PWM_TIMER_REG_PTR regs; /*!< pwm_timer port register */
uint32_t intno; /*!< pwm_timer interrupt vector number */
uint32_t ch_num; /*!< pwm_timer group channel count */
uint32_t clock; /*!< pwm_timer clock */
INT_HANDLER_T int_handler; /*!< pwm_timer interrupt handler pointer */
DW_PWM_TIMER_CH_ISR_PTR ch_isr; /*!< pwm_timer group channel callback pointer */
DEV_PWM_TIMER_MODE_PTR mode; /*!< pwm_timer group channel work mode array pointer*/
} DW_PWM_TIMER_CTRL, *DW_PWM_TIMER_CTRL_PTR;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name DesignWare PWM_TIMER Function Declaration
* @brief Contains declarations of designware pwm_timer functions.
* @details These are only used in pwm_timer object implementation source file
* @{
*/
extern int32_t dw_pwm_timer_open(DEV_PWM_TIMER *pwm_timer_obj);
extern int32_t dw_pwm_timer_close(DEV_PWM_TIMER *pwm_timer_obj);
extern int32_t dw_pwm_timer_read(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t *mode, uint32_t *freq, uint32_t *dc);
extern int32_t dw_pwm_timer_write(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t mode, uint32_t freq, uint32_t dc);
extern int32_t dw_pwm_timer_control(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t cmd, void *param);
extern int32_t dw_pwm_timer_isr_handler(DEV_PWM_TIMER *pwm_timer_obj, void *ptr);
#ifdef __cplusplus
}
#endif
#endif /* H_DW_PWM_TIMER */
/** @} */

View File

@@ -1,72 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_SDIO
#define H_DW_SDIO
#include "device/ip_hal/dev_sdio.h"
#include "arc/arc_builtin.h"
/**
* @brief Structure definitions for DesignWare SDIO control
* @details Structure type for DesignWare SDIO implementation
*/
typedef struct {
void *reg_base; /*!< sdio registers base */
uint32_t ref_clk; /* reference clk */
uint32_t intno; /* interrupt no */
uint32_t fifo_depth;
/* Variables which should be set during object implementation */
} DW_SDIO_CTRL, *DW_SDIO_CTRL_PTR;
/**
* @fn uint32_t dw_sdio_reg_read(DW_SDIO_CTRL_PTR sdio, uint32_t reg)
*/
Inline uint32_t dw_sdio_reg_read(DW_SDIO_CTRL_PTR sdio, uint32_t reg)
{
return arc_read_uncached_32((void *)((uint32_t)sdio->reg_base + reg));
}
/**
* @fn void dw_sdio_reg_write(DW_SDIO_CTRL_PTR sdio, uint32_t reg, uint32_t val)
*/
Inline void dw_sdio_reg_write(DW_SDIO_CTRL_PTR sdio, uint32_t reg, uint32_t val)
{
arc_write_uncached_32((void *)((uint32_t)sdio->reg_base + reg), val);
}
extern void dw_sdio_isr(DEV_SDIO *sdio_obj, void *ptr);
extern int32_t dw_sdio_cmd_poll(DEV_SDIO *sdio_obj, SDIO_CMD_PTR cmd, SDIO_DATA_PTR data);
extern int32_t dw_sdio_open(DEV_SDIO *sdio_obj, uint32_t card_number);
extern int32_t dw_sdio_close(DEV_SDIO *sdio_obj, uint32_t card_number);
extern int32_t dw_sdio_cd(DEV_SDIO *sdio_obj, uint32_t card_number);
extern int32_t dw_sdio_wp(DEV_SDIO *sdio_obj, uint32_t card_number);
extern int32_t dw_sdio_control(DEV_SDIO *sdio_obj, SDIO_CTRL_CMD_PTR ctrl_cmd, void *param);
#endif /* H_DW_SDIO */

View File

@@ -1,237 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_SDIO_HAL
#define H_DW_SDIO_HAL
/* register offset */
#define DWSDIO_REG_CTRL (0x000)
#define DWSDIO_REG_PWREN (0x004)
#define DWSDIO_REG_CLKDIV (0x008)
#define DWSDIO_REG_CLKSRC (0x00C)
#define DWSDIO_REG_CLKENA (0x010)
#define DWSDIO_REG_TMOUT (0x014)
#define DWSDIO_REG_CTYPE (0x018)
#define DWSDIO_REG_BLKSIZ (0x01C)
#define DWSDIO_REG_BYTCNT (0x020)
#define DWSDIO_REG_INTMASK (0x024)
#define DWSDIO_REG_CMDARG (0x028)
#define DWSDIO_REG_CMD (0x02C)
#define DWSDIO_REG_RESP0 (0x030)
#define DWSDIO_REG_RESP1 (0x034)
#define DWSDIO_REG_RESP2 (0x038)
#define DWSDIO_REG_RESP3 (0x03C)
#define DWSDIO_REG_MINTSTS (0x040)
#define DWSDIO_REG_RINTSTS (0x044)
#define DWSDIO_REG_STATUS (0x048)
#define DWSDIO_REG_FIFOTH (0x04C)
#define DWSDIO_REG_CDETECT (0x050)
#define DWSDIO_REG_WRTPRT (0x054)
#define DWSDIO_REG_GPIO (0x058)
#define DWSDIO_REG_TCMCNT (0x05C)
#define DWSDIO_REG_TBBCNT (0x060)
#define DWSDIO_REG_DEBNCE (0x064)
#define DWSDIO_REG_USRID (0x068)
#define DWSDIO_REG_VERID (0x06C)
#define DWSDIO_REG_HCON (0x070)
#define DWSDIO_REG_UHS_REG (0x074)
#define DWSDIO_REG_RST_N (0x078)
#define DWSDIO_REG_BMOD (0x080)
#define DWSDIO_REG_PLDMND (0x084)
#define DWSDIO_REG_DBADDR (0x088)
#define DWSDIO_REG_IDSTS (0x08C)
#define DWSDIO_REG_IDINTEN (0x090)
#define DWSDIO_REG_DSCADDR (0x094)
#define DWSDIO_REG_BUFADDR (0x098)
#define DWSDIO_REG_CARD_THR_CTRL (0x100)
#define DWSDIO_REG_UHS_REG_EXT (0x108)
#define DWSDIO_REG_DATA (0x200)
/* DW AHB SDIO bit definitions */
#define DWSDIO_CTRL_BIT_RESET_CTRL 0
#define DWSDIO_CTRL_RESET_CTRL (1 << DWSDIO_CTRL_BIT_RESET_CTRL)
#define DWSDIO_CTRL_BIT_RESET_FIFO 1
#define DWSDIO_CTRL_RESET_FIFO (1 << DWSDIO_CTRL_BIT_RESET_FIFO)
#define DWSDIO_CTRL_BIT_RESET_DMA 2
#define DWSDIO_CTRL_RESET_DMA (1 << DWSDIO_CTRL_BIT_RESET_DMA)
#define DWSDIO_CTRL_RESET_ALL (DWSDIO_CTRL_RESET_CTRL | DWSDIO_CTRL_RESET_FIFO | DWSDIO_CTRL_RESET_DMA)
#define DWSDIO_CTRL_BIT_INT_ENABLE 4
#define DWSDIO_CTRL_INT_ENABLE (1 << DWSDIO_CTRL_BIT_INT_ENABLE)
#define DWSDIO_CTRL_BIT_DMA_ENABLE 5
#define DWSDIO_CTRL_DMA_ENABLE (1 << DWSDIO_CTRL_BIT_DMA_ENABLE)
#define DWSDIO_CTRL_BIT_ODPULLUP 24
#define DWSDIO_CTRL_ODPULLUP (1 << DWSDIO_CTRL_BIT_ODPULLUP)
#define DWSDIO_CTRL_BIT_INTERNAL_DMA 25
#define DWSDIO_CTRL_INTERNAL_DMA (1 << DWSDIO_CTRL_BIT_INTERNAL_DMA)
/* Register CMD field CMD_INDEX */
#define DWSDIO_CMD_BIT_CMD_INDEX 0
#define DWSDIO_CMD_MASK_CMD_INDEX 0x0000003FU
/* Register CMD field RESPONSE_EXPECT */
#define DWSDIO_CMD_BIT_RESP_EXP 6
#define DWSDIO_CMD_RESP_EXP (1 << DWSDIO_CMD_BIT_RESP_EXP)
/* Register CMD field RESPONSE_LENGTH */
#define DWSDIO_CMD_BIT_RESP_LENGTH 7
#define DWSDIO_CMD_RESP_LENGTH (1 << DWSDIO_CMD_BIT_RESP_LENGTH)
/* Register CMD field CHECK_RESPONSE_CRC */
#define DWSDIO_CMD_BIT_CHECK_CRC 8
#define DWSDIO_CMD_CHECK_CRC (1 << DWSDIO_CMD_BIT_CHECK_CRC)
/* Register CMD field DATA_EXPECTED */
#define DWSDIO_CMD_BIT_DATA_EXP 9
#define DWSDIO_CMD_DATA_EXP (1 << DWSDIO_CMD_BIT_DATA_EXP)
/* Register CMD field READ-WRITE */
#define DWSDIO_CMD_BIT_RW 10
#define DWSDIO_CMD_RW (1 << DWSDIO_CMD_BIT_RW)
/* Register CMD field TRANSFER_MODE */
#define DWSDIO_CMD_BIT_XFER_MODE 11
#define DWSDIO_CMD_XFER_MODE (1 << DWSDIO_CMD_BIT_XFER_MODE)
/* Register CMD field SEND_AUTO_STOP */
#define DWSDIO_CMD_BIT_AUTO_STOP 12
#define DWSDIO_CMD_AUTO_STOP (1 << DWSDIO_CMD_BIT_AUTO_STOP)
/* Register CMD field WAIT_PRVDATA_COMPLETE */
#define DWSDIO_CMD_BIT_PRV_DAT_WAIT 13
#define DWSDIO_CMD_PRV_DAT_WAIT (1 << DWSDIO_CMD_BIT_PRV_DAT_WAIT)
/* Register CMD field STOP_ABORT_CMD */
#define DWSDIO_CMD_BIT_ABORT_STOP 14
#define DWSDIO_CMD_ABORT_STOP (1 << DWSDIO_CMD_BIT_ABORT_STOP)
/* Register CMD field SEND_INITIALIZATION */
#define DWSDIO_CMD_BIT_SEND_INIT 15
#define DWSDIO_CMD_SEND_INIT (1 << DWSDIO_CMD_BIT_SEND_INIT)
/* Register CMD field CARD_NUMBER */
#define DWSDIO_CMD_BIT_CARD_NO 16
#define DWSDIO_CMD_MASK_CARD_NO 0x001F0000U
/* Register CMD field UPDATE_CLOCK_REGISTERS_ONLY */
#define DWSDIO_CMD_BIT_BIT_UPD_CLK 21
#define DWSDIO_CMD_UPD_CLK (1 << DWSDIO_CMD_BIT_BIT_UPD_CLK)
/* Register CMD field READ_CEATA_DEVICE */
#define DWSDIO_CMD_BIT_READ_CEATA_DEVICE 22
#define DWSDIO_CMD_READ_CEATA_DEVICE (1 << DWSDIO_CMD_BIT_READ_CEATA_DEVICE)
/* Register CMD field CCS_EXPECTED */
#define DWSDIO_CMD_BIT_CCS_EXP 23
#define DWSDIO_CMD_CCS_EXP (1 << DWSDIO_CMD_BIT_CCS_EXP)
/* Register CMD field ENABLE_BOOT */
#define DWSDIO_CMD_BIT_ENABLE_BOOT 24
#define DWSDIO_CMD_ENABLE_BOOT (1 << DWSDIO_CMD_BIT_ENABLE_BOOT)
/* Register CMD field EXPECT_BOOT_ACK */
#define DWSDIO_CMD_BIT_BOOT_ACK_EXP 25
#define DWSDIO_CMD_BOOT_ACK_EXP (1 << DWSDIO_CMD_BIT_BOOT_ACK_EXP)
/* Register CMD field DISABLE_BOOT */
#define DWSDIO_CMD_BIT_DISABLE_BOOT 25
#define DWSDIO_CMD_DISBALE_BOOT (1 << DWSDIO_CMD_BIT_DISABLE_BOOT)
/* Register CMD field BOOT_MODE */
#define DWSDIO_CMD_BIT_BOOT_MODE 27
#define DWSDIO_CMD_BOOT_MODE (1 << DWSDIO_CMD_BIT_BOOT_MODE)
/* Register CMD field VOLT_SWITCH */
#define DWSDIO_CMD_BIT_VOLT_SWITCH 28
#define DWSDIO_CMD_VOLT_SWITCH (1 << DWSDIO_CMD_BIT_VOLT_SWITCH)
/* Register CMD field USE_HOLD_REG */
#define DWSDIO_CMD_BIT_USE_HOLD_REG 29
#define DWSDIO_CMD_USE_HOLD_REG (1 << DWSDIO_CMD_BIT_USE_HOLD_REG)
/* Register CMD field START_CMD */
#define DWSDIO_CMD_BIT_START 31
#define DWSDIO_CMD_START (1 << DWSDIO_CMD_BIT_START)
/* Register UHS_REG_EXT */
#define DWSDIO_UHS_REG_EXT_MASK_REFCLK (0xC0000000)
#define DWSDIO_UHS_REG_EXT_BIT_REFCLK 30
#define DWSDIO_UHS_REG_EXT_MASK_CLKDRIVE (0x01800000)
#define DWSDIO_UHS_REG_EXT_BIT_CLKDRIVE 23
#define DWSDIO_UHX_REG_EXT_MASK_CLKSAMPLE (0x007f0000)
#define DWSDIO_UHX_REG_EXT_BIT_CLKSAMPLE 16
#define DWSDIO_STATUS_BIT_FIFO (17)
#define DWSDIO_STATUS_FIFO_FULL (0x8)
#define DWSDIO_STATUS_FIFO_EMPTY (0x4)
#define DWSDIO_STATUS_MASK_FIFO (0x3ffe0000)
/* status bit */
#define DWSDIO_STATUS_DATA_BUSY (1 << 9)
#define DWSDIO_FIFOTH_BIT_RX_WMARK 16
#define DWSDIO_FIFOTH_MASK_RX_WMARK (0xfff << DWSDIO_FIFOTH_BIT_RX_WMARK)
#define DWSDIO_FIFOTH_BIT_TX_WMARK 0
#define DWSDIO_FIFOTH_MASK_TX_WMARK (0xfff)
#define DWSDIO_FIFOTH_BIT_DMA_M_SIZE 28
#define DWSDIO_FIFOTH_MASK_DMA_M_SIZE (0x7 << DWSDIO_FIFOTH_BIT_DMA_M_SIZE)
#define DWSDIO_FIFOTH_M_SIZE(x) ((x) << DWSDIO_FIFOTH_BIT_DMA_M_SIZE)
#define DWSDIO_FIFOTH_TX_WMASK(x) ((x))
#define DWSDIO_FIFOTH_RX_WMASK(x) ((x) << DWSDIO_FIFOTH_BIT_RX_WMARK)
/* interrupt status bit */
#define DWSDIO_INT_CAD (0x1U) // Card Detected
#define DWSDIO_INT_RE (0x2U) // Response error
#define DWSDIO_INT_CD (0x4U) // Command Done
#define DWSDIO_INT_DTO (0x8U) // Data Transfer Over
#define DWSDIO_INT_TXDR (0x10U) // Transmit FiFo Data Request
#define DWSDIO_INT_RXDR (0x20U) // Receive Fifo Data request
#define DWSDIO_INT_RCRC (0x40U) // Response CRC error
#define DWSDIO_INT_DCRC (0x80U) // Data CRC error
#define DWSDIO_INT_RTO (0x100U) // Response Timeout
#define DWSDIO_INT_DRTO (0x200U) // Data read Timeout
#define DWSDIO_INT_HTO (0x400U) // Data starvation by Host timeout
#define DWSDIO_INT_FRUN (0x800U) // Fifo underrun / overrun error
#define DWSDIO_INT_HLE (0x1000U) // Hardware Locked write error
#define DWSDIO_INT_SBE (0x2000U) // Start bit error
#define DWSDIO_INT_ACD (0x4000U) // Auto Command Done
#define DWSDIO_INT_EBE (0x8000U) // End bit error
#define DWSDIO_INT_ALL (0xFFFF)
#define DWSDIO_INT_DATA_ERR (DWSDIO_INT_SBE | DWSDIO_INT_EBE | DWSDIO_INT_HLE | \
DWSDIO_INT_FRUN | DWSDIO_INT_DCRC)
#define DWSDIO_INT_DATA_TMO (DWSDIO_INT_DRTO | DWSDIO_INT_HTO)
#define DWSDIO_ENUMERATION_FREQ (400000) /* 400 Khz for card enumeration */
#endif /* H_DW_SDIO_HAL */

View File

@@ -1,175 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_SPI
#define H_DW_SPI
#include "device/ip_hal/dev_spi.h"
#include "arc/arc_exception.h"
/**
* if this header file is included,
* will indicate that this designware spi device
* is used
*/
#define DEVICE_USE_DESIGNWARE_SPI
#define DW_SPI_IN_FREE (0) /*!< Currently not in spi transfer */
#define DW_SPI_IN_XFER (DEV_IN_TX | DEV_IN_RX | DEV_IN_XFER) /*!< Currently in spi transfer */
#define DW_SPI_IN_TX (DEV_IN_TX | DEV_IN_XFER) /*!< Currently in spi tx */
#define DW_SPI_IN_RX (DEV_IN_RX | DEV_IN_XFER) /*!< Currently in spi rx */
#define DW_SPI_GINT_DISABLED (0) /*!< designware interrupt disabled for control spi irq/fiq */
#define DW_SPI_GINT_ENABLE (1 << 0) /*!< designware interrupt enabled for control spi irq/fiq */
#define DW_SPI_MASTER_SUPPORTED (0x1) /*!< Support Designware SPI Master Mode */
#define DW_SPI_SLAVE_SUPPORTED (0x2) /*!< Support Designware SPI Slave Mode */
/*!< Support Designware SPI Both Master and Slave Mode */
#define DW_SPI_BOTH_SUPPORTED (DW_SPI_MASTER_SUPPORTED | DW_SPI_SLAVE_SUPPORTED)
#define DW_SPI_INVALID_INTNO (DEV_INTNO_INVALID)
/**
* detailed description of DesignWare SPI register information
*/
/**
* @brief Structure definitions for DesignWare SPI register
* @details Structure type for DesignWare SPI
* block register information, implementation
*/
typedef volatile struct {
/*!< Control Register */
/*!< SPI Control Register 0 (0x0) */
uint32_t CTRLR0;
/*!< SPI Control Register 1 (0x4) */
uint32_t CTRLR1;
/*!< Enable Register */
/*!< SPI Enable Register (0x8) */
uint32_t SSIENR;
/*!< SPI Microwire Control Register (0xC) */
uint32_t MWCR;
/*!< SPI Slave Enable Register (0x10) */
uint32_t SER;
/*!< SPI Baud Rate Select Register (0x14) */
uint32_t BAUDR;
/*!< TX and RX FIFO Control Register */
/*!< SPI Transmit FIFO Threshold Level Register (0x18) */
uint32_t TXFTLR;
/*!< SPI Receive FIFO Threshold Level Register (0x1C) */
uint32_t RXFTLR;
/*!< SPI Transmit FIFO Level Register (0x20) */
uint32_t TXFLR;
/*!< SPI Receive FIFO Level Register (0x24) */
uint32_t RXFLR;
/*!< SPI Status Register (0x28) */
uint32_t SR;
/*!< Interrupt Enable/Disable/Control Registers */
/*!< SPI Interrupt Mask Register (0x2C) */
uint32_t IMR;
/*!< SPI Interrupt Status Register (0x30) */
uint32_t ISR;
/*!< SPI Raw Interrupt Status Register (0x34) */
uint32_t RISR;
/*!< SPI Transmit FIFO Overflow Interrupt Clear Register (0x38) */
uint32_t TXOICR;
/*!< SPI Receive FIFO Overflow Interrupt Clear Register (0x3C) */
uint32_t RXOICR;
/*!< SPI Receive FIFO Underflow Interrupt Clear Register (0x40) */
uint32_t RXUICR;
/*!< SPI Multi-Master Interrupt Clear Register (0x44) */
uint32_t MSTICR;
/*!< SPI Interrupt Clear Register (0x48) */
uint32_t ICR;
/*!< DMA Control Register (0x4C) */
uint32_t DMACR;
/*!< DMA Transmit Data Level (0x50) */
uint32_t DMATDLR;
/*!< DMA Receive Data Level (0x54) */
uint32_t DMARDLR;
/*!< SPI Identification Register (0x58) */
uint32_t IDR;
/*!< SPI CoreKit ID Register (Value after Reset : 0x3332322A) (0x5C) */
uint32_t SSI_VER_ID;
/*!< Data Register */
/*!< SPI DATA Register for both Read and Write (0x60) */
uint32_t DATAREG;
/*!< More SPI DATA Register for both Read and Write (0x64-0xEC) */
uint32_t DRS[35];
/** 0xF0, RxD Sample Delay Register */
uint32_t RX_SAMPLE_DLY;
/** 0xF4, SPI Control Register */
uint32_t SPI_CTRLR0;
} DW_SPI_REG, *DW_SPI_REG_PTR;
/** Designware SPI Message Transfer */
typedef struct {
uint32_t xfer_len;
uint32_t tx_idx;
uint32_t rx_idx;
uint32_t nbytes;
DEV_SPI_TRANSFER *tx_xfer;
DEV_SPI_TRANSFER *rx_xfer;
} DW_SPI_TRANSFER, *DW_SPI_TRANSFER_PTR;
/**
* @brief Structure definitions for DesignWare SPI control
* @details Structure type for DesignWare SPI implementation
*/
typedef struct {
DW_SPI_REG *dw_spi_regs; /*!< spi register */
/* Variables which should be set during object implementation */
uint32_t support_modes; /*!< supported spi modes */
uint32_t intno; /*!< interrupt no */
uint32_t dw_apb_bus_freq; /*!< spi ip apb bus frequency */
uint32_t rx_sampledly; /*!< RxD Sample Delay */
uint32_t tx_fifo_len; /*!< transmit fifo length */
uint32_t rx_fifo_len; /*!< receive fifo length */
INT_HANDLER_T dw_spi_int_handler; /*!< spi interrupt handler */
/* Variables which always change during spi operation */
uint32_t int_status; /*!< spi interrupt status */
DW_SPI_TRANSFER dw_xfer; /*!< designware spi transfer */
} DW_SPI_CTRL, *DW_SPI_CTRL_PTR;
#ifdef __cplusplus
extern "C" {
#endif
extern int32_t dw_spi_open(DEV_SPI *spi_obj, uint32_t mode, uint32_t param);
extern int32_t dw_spi_close(DEV_SPI *spi_obj);
extern int32_t dw_spi_control(DEV_SPI *spi_obj, uint32_t ctrl_cmd, void *param);
extern int32_t dw_spi_write(DEV_SPI *spi_obj, const void *data, uint32_t len);
extern int32_t dw_spi_read(DEV_SPI *spi_obj, void *data, uint32_t len);
extern void dw_spi_isr(DEV_SPI *spi_obj, void *ptr);
#ifdef __cplusplus
}
#endif
#endif /* H_DW_SPI */

View File

@@ -1,113 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_SPI_HAL
#define H_DW_SPI_HAL
#include "device/designware/dw_spi_hal_cfg.h"
/* DW APB SPI bit definitions */
/**
* DesignWare SPI hal ctrl0 macros,
* include dfs, scph, scppl, tmod, etc
*/
#define DW_SPI_CTRLR0_DFS_MASK (0xf)
#define DW_SPI_CTRLR0_SC_OFS (6)
#define DW_SPI_CTRLR0_SC_MASK (0xC0)
#define DW_SPI_CTRLR0_SCPH_HIGH (0x40)
#define DW_SPI_CTRLR0_SCPH_LOW (0)
#define DW_SPI_CTRLR0_SCPOL_HIGH (0x80)
#define DW_SPI_CTRLR0_SCPOL_LOW (0)
#define DW_SPI_CTRLR0_TMOD_MASK (0x300)
#define DW_SPI_TMOD_TRANSMIT_RECEIVE (0)
#define DW_SPI_TMOD_TRANSMIT_ONLY (0x100)
#define DW_SPI_TMOD_RECEIVE_ONLY (0x200)
#define DW_SPI_TMOD_EEPROM_READ_ONLY (0x300)
#define DW_SPI_CTRLR0_FRF_MOTOROLA (0x0)
#define DW_SPI_CTRLR0_FRF_TI (0x10)
#define DW_SPI_CTRLR0_FRF_MICROWIRE (0x20)
#define DW_SPI_CTRLR0_SLV_OE_DISABLE (1 << 10)
#define DW_SPI_CTRLR0_SLV_OE_ENABLE (0)
/**
* DesignWare SPI hal Interrupt Status Flags
*/
#define DW_SPI_TX_OVERFLOW_ERROR (0x2)
#define DW_SPI_RX_UNDERFLOW_ERROR (0x4)
#define DW_SPI_RX_OVERFLOW_ERROR (0x8)
#define DW_SPI_ISR_RX_FIFO_INT_MASK (0x10)
#define DW_SPI_ISR_TX_FIFO_INT_MASK (0x1)
#define DW_SPI_ISR_TX_OVERFLOW_INT_MASK (0x2)
#define DW_SPI_ISR_RX_UNDERFLOW_INT_MASK (0x4)
#define DW_SPI_ISR_RX_OVERFLOW_INT_MASK (0x8)
/**
* DesignWare SPI hal Status Flags
*/
#define DW_SPI_SR_DCOL (0x40)
#define DW_SPI_SR_TXE (0x20)
#define DW_SPI_SR_RFF (0x10)
#define DW_SPI_SR_RFNE (0x8)
#define DW_SPI_SR_TFE (0x4)
#define DW_SPI_SR_TFNF (0x2)
#define DW_SPI_SR_BUSY (0x1)
/**
* DesignWare SPI hal ssi enable macros
*/
/* Macros */
#define DW_SPI_SSI_ENABLE (1) /*!< SSI Enable */
#define DW_SPI_SSI_DISABLE (0) /*!< SSI Disable */
/**
* DesignWare SPI hal interrupt mask macros
*/
#define DW_SPI_IMR_MSTIM (0x20) /*!< Multi-Master Contention Interrupt Mask */
#define DW_SPI_IMR_RXFIM (0x10) /*!< Receive FIFO Full Interrupt Mask */
#define DW_SPI_IMR_RXOIM (0x08) /*!< Receive FIFO Overflow Interrupt Mask */
#define DW_SPI_IMR_RXUIM (0x04) /*!< Receive FIFO Underflow Interrupt Mask */
#define DW_SPI_IMR_TXOIM (0x02) /*!< Transmit FIFO Overflow Interrupt Mask */
#define DW_SPI_IMR_TXEIM (0x01) /*!< Transmit FIFO Empty Interrupt Mask */
#define DW_SPI_IMR_XFER (DW_SPI_IMR_TXEIM | DW_SPI_IMR_RXFIM | DW_SPI_IMR_TXOIM | DW_SPI_IMR_RXOIM | DW_SPI_IMR_RXUIM)
#define DW_SPI_SSI_IDLE (1)
#define DW_SPI_SPI_TRANSMIT (1)
#define DW_SPI_SPI_RECEIVE (2)
#define DW_SPI_SSI_MASTER (1)
#define DW_SPI_SSI_SLAVE (0)
#endif /* H_DW_SPI_HAL */

View File

@@ -1,46 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_SPI_HAL_CFG
#define H_DW_SPI_HAL_CFG
#ifndef DW_SPI_CALC_FIFO_LEN_ENABLE
#define DW_SPI_CALC_FIFO_LEN_ENABLE (1) /*!< Defaultly enable calculate fifo length */
#endif
#ifndef DW_SPI_MAX_FIFO_LENGTH
#define DW_SPI_MAX_FIFO_LENGTH (256) /*!< Max FIFO depth for designware SPI device */
#endif
#ifndef DW_SPI_MIN_FIFO_LENGTH
#define DW_SPI_MIN_FIFO_LENGTH (2) /*!< Min FIFO depth for designware SPI device */
#endif
#endif /* H_DW_SPI_HAL_CFG */

View File

@@ -1,94 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_TRNG
#define H_DW_TRNG
#include "device/ip_hal/dev_trng.h"
#include "arc/arc_exception.h"
#ifndef TRNG_VERSION_NIST
#define DW_TRNG_INVALID_INTNO (DEV_INTNO_INVALID)
// DesignWare TRNG register structure
typedef volatile struct {
uint32_t CTRL; // (0x0)
uint32_t STAT; // (0x4)
uint32_t MODE; // (0x8)
uint32_t SMODE; // (0xC)
uint32_t IE; // (0x10)
uint32_t ISTAT; // (0x14)
uint32_t COREKIT_REL; // (0x18)
uint32_t FEATURES; // (0x1C)
uint32_t RAND0; // (0x20)
uint32_t RAND1; // (0x24)
uint32_t RAND2; // (0x28)
uint32_t RAND3; // (0x2C)
uint32_t RAND4; // (0x30)
uint32_t RAND5; // (0x34)
uint32_t RAND6; // (0x38)
uint32_t RAND7; // (0x3C)
uint32_t SEED0; // (0x40)
uint32_t SEED1; // (0x44)
uint32_t SEED2; // (0x48)
uint32_t SEED3; // (0x4C)
uint32_t SEED4; // (0x50)
uint32_t SEED5; // (0x54)
uint32_t SEED6; // (0x58)
uint32_t SEED7; // (0x5C)
uint32_t AUTO_RQSTS; // (0x60)
uint32_t AUTO_AGE; // (0x64)
uint32_t BUILD_CONFIG; // (0x68)
} DW_TRNG_REG, *DW_TRNG_REG_PTR;
typedef struct {
DW_TRNG_REG_PTR dw_trng_regs; /*!< dw trng register */
uint32_t intno; /*!< interrupt vector number */
INT_HANDLER_T dw_trng_int_handler; /*!< interrupt handler */
uint32_t int_status; /*!< interrupt status */
} DW_TRNG_CTRL, *DW_TRNG_CTRL_PTR;
#ifdef __cplusplus
extern "C" {
#endif
extern int32_t dw_trng_open(DEV_TRNG_PTR trng_obj);
extern int32_t dw_trng_close(DEV_TRNG_PTR trng_obj);
extern int32_t dw_trng_control(DEV_TRNG_PTR trng_obj, uint32_t ctrl_cmd, void *param);
extern int32_t dw_trng_read(DEV_TRNG_PTR trng_obj, uint32_t *data_buf);
extern void dw_trng_isr(DEV_TRNG_PTR trng_obj, void *ptr);
#ifdef __cplusplus
}
#endif
#endif /* TRNG_VERSION_NIST */
#endif /* H_DW_TRNG */

View File

@@ -1,122 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_UART
#define H_DW_UART
#include "device/ip_hal/dev_uart.h"
#include "arc/arc_exception.h"
/**
* if this header file is included,
* will indicate that this designware uart device
* is used
*/
#define DEVICE_USE_DESIGNWARE_UART
/**
* contains definitions of DesignWare UART register structure.
*/
/**
* @brief Structure definitions for DesignWare UART register
* @details Structure type for DesignWare UART
* block register information, implementation
*/
typedef volatile struct {
uint32_t DATA; /*!< data in/out and DLL */
uint32_t IER; /*!< Interrupt enable register and DLH */
uint32_t IIR; /*!< Interrupt Id register and FCR */
uint32_t LCR; /*!< Line control Register */
uint32_t MCR; /*!< Modem control register */
uint32_t LSR; /*!< Line Status Register */
uint32_t MSR; /*!< Modem status Register */
uint32_t SCRATCHPAD; /*!< Uart scratch pad register */
uint32_t LPDLL; /*!< Low Power Divisor Latch (Low) Reg */
uint32_t LPDLH; /*!< Low Power Divisor Latch (High) Reg */
uint32_t RES1[2]; /*!< Reserved */
uint32_t SHR[16]; /*!< Shadow data register(SRBR and STHR) */
uint32_t FAR; /*!< FIFO Access register */
uint32_t TFR; /*!< Transmit FIFO Read */
uint32_t RFW; /*!< Receive FIFO write */
uint32_t USR; /*!< UART status register */
uint32_t TFL; /*!< Transmit FIFO level */
uint32_t RFL; /*!< Receive FIFO level */
uint32_t SRR; /*!< Software reset register */
uint32_t SRTS; /*!< Shadow request to send */
uint32_t SBCR; /*!< Shadow break control */
uint32_t SDMAM; /*!< Shadow DMA mode */
uint32_t SFE; /*!< Shadow FIFO enable */
uint32_t SRT; /*!< Shadow RCVR Trigger */
uint32_t STET; /*!< Shadow TX empty register */
uint32_t HTX; /*!< Halt TX */
uint32_t DMASA; /*!< DMA Software ACK */
uint32_t RES2[18]; /*!< Reserved */
uint32_t CPR; /*!< Camponent parameter register */
uint32_t UCV; /*!< UART Component Version */
uint32_t CTR; /*!< Component typw register */
} DW_UART_REG, *DW_UART_REG_PTR;
#define DW_UART_GINT_DISABLED (0) /*!< designware interrupt disabled for control uart irq/fiq */
#define DW_UART_GINT_ENABLE (1 << 0) /*!< designware interrupt enabled for control uart irq/fiq */
#define DW_UART_TXINT_ENABLE (1 << 1) /*!< designware interrupt enabled for control transmit process */
#define DW_UART_RXINT_ENABLE (1 << 2) /*!< designware interrupt enabled for control transmit process */
#define DW_UART_INVALID_INTNO (DEV_INTNO_INVALID)
/**
* @brief Structure definitions for DesignWare UART control structure
* @details Structure type for DesignWare UART implementation
*/
typedef struct {
uint32_t dw_uart_regbase; /*!< uart ip register base */
uint32_t dw_apb_bus_freq; /*!< uart ip apb bus frequency */
uint32_t intno; /*!< uart interrupt vector number */
INT_HANDLER_T dw_uart_int_handler; /*!< uart interrupt handler */
uint32_t tx_fifo_len; /*!< transmit fifo length, set by user in object implementation */
uint32_t rx_fifo_len; /*!< receive fifo length, set by user in object implementation */
uint32_t int_status; /*!< interrupt status for designware uart */
} DW_UART_CTRL, *DW_UART_CTRL_PTR;
#ifdef __cplusplus
extern "C" {
#endif
extern int32_t dw_uart_open(DEV_UART *uart_obj, uint32_t baud);
extern int32_t dw_uart_close(DEV_UART *uart_obj);
extern int32_t dw_uart_control(DEV_UART *uart_obj, uint32_t ctrl_cmd, void *param);
extern int32_t dw_uart_write(DEV_UART *uart_obj, const void *data, uint32_t len);
extern int32_t dw_uart_read(DEV_UART *uart_obj, void *data, uint32_t len);
extern void dw_uart_isr(DEV_UART *uart_obj, void *ptr);
#ifdef __cplusplus
}
#endif
#endif /* H_DW_UART */

View File

@@ -1,203 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DW_UART_HAL
#define H_DW_UART_HAL
/* DW APB UART bit definitions */
/**
* DesignWare UART hal IER related macros
*/
/* IER */
#define DW_UART_IER_DATA_AVAIL (0x01)
#define DW_UART_IER_XMIT_EMPTY (0x02)
#define DW_UART_IER_LINE_STATUS (0x04)
#define DW_UART_IER_MDM_STATUS (0x08)
#define DW_UART_IER_PTIME (0x80)
/**
* DesignWare UART hal IIR related macros
*/
/* IIR */
/* IIR READ */
#define DW_UART_IIR_IP (0x01)
#define DW_UART_IIR_MASK (0x0E)
#define DW_UART_IIR_READ_FIFO_ENABLE (0xC0)
/* Possible interrupt IIR_MASK values */
#define DW_UART_IIR_MDM_STATUS (0x00)
#define DW_UART_IIR_XMIT_EMPTY (0x02)
#define DW_UART_IIR_DATA_AVAIL (0x04)
#define DW_UART_IIR_LINE_STATUS (0x06)
#define DW_UART_IIR_RX_TIMEOUT (0x0C)
#define DW_UART_IIR_INT_ID_MASK (0x0f)
/* IIR WRITE */
#define DW_UART_IIR_FIFO_ENABLE (0x01)
#define DW_UART_IIR_RCVR_FIFO_RESET (0x02)
#define DW_UART_IIR_XMIT_FIFO_RESET (0x04)
#define DW_UART_IIR_DMA_MODE_SELECT (0x08)
#define DW_UART_IIR_RCV_TRIGGER_MASK (0xC0)
/* Values for IIR receive trigger */
#define DW_UART_IIR_TRIGGER_LEVEL_1_CHAR (0x00)
#define DW_UART_IIR_TRIGGER_LEVEL_1_4_FULL (0x40)
#define DW_UART_IIR_TRIGGER_LEVEL_1_2_FULL (0x80)
#define DW_UART_IIR_TRIGGER_LEVEL_2_LESS_FULL (0xC0)
/**
* DesignWare UART hal LCR related macros
*/
/* LCR */
#define DW_UART_LCR_WORD_LEN_MASK (0x03)
#define DW_UART_LCR_STOP_BIT_MASK (0x04)
#define DW_UART_LCR_PARITY_MASK (0x38)
#define DW_UART_LCR_DPS_MASK (0x3F)
#define DW_UART_LCR_STICK_PARITY (0x20)
#define DW_UART_LCR_BREAK (0x40)
#define DW_UART_LCR_DLAB (0x80)
/* Word length values */
#define DW_UART_LCR_WORD_LEN5 (0x00)
#define DW_UART_LCR_WORD_LEN6 (0x01)
#define DW_UART_LCR_WORD_LEN7 (0x02)
#define DW_UART_LCR_WORD_LEN8 (0x03)
/* stop bit values */
#define DW_UART_LCR_1_STOP_BIT (0x00)
#define DW_UART_LCR_1D5_STOP_BIT (0x04)
#define DW_UART_LCR_2_STOP_BIT (0x04)
/* Parity bit values */
#define DW_UART_LCR_PARITY_NONE (0x00)
#define DW_UART_LCR_PARITY_ODD (0x08)
#define DW_UART_LCR_PARITY_EVEN (0x18)
#define DW_UART_LCR_PARITY_MARK (0x28)
#define DW_UART_LCR_PARITY_SPACE (0x38)
/**
* DesignWare UART hal MCR related macros
*/
/* MCR */
#define DW_UART_MCR_DTR (0x01)
#define DW_UART_MCR_RTS (0x02)
#define DW_UART_MCR_LOOPBACK (0x10)
#define DW_UART_MCR_AFCE (0x20)
#define DW_UART_MCR_SIRE (0x40)
/**
* DesignWare UART hal LSR related macros
*/
/* LSR */
#define DW_UART_LSR_DR (0x01)
#define DW_UART_LSR_OVERRUN (0x02)
#define DW_UART_LSR_PARITYERR (0x04)
#define DW_UART_LSR_FRAMEERR (0x08)
#define DW_UART_LSR_BREAKRCVD (0x10)
#define DW_UART_LSR_TXD_EMPTY (0x20)
#define DW_UART_LSR_TX_STATUS (0x40)
#define DW_UART_LSR_RX_FIFOERR (0x80)
/**
* DesignWare UART hal MSR related macros
*/
/* MSR */
#define DW_UART_MSR_DCTS (0x01)
#define DW_UART_MSR_DDSR (0x02)
#define DW_UART_MSR_TERI (0x04)
#define DW_UART_MSR_DDCD (0x08)
#define DW_UART_MSR_CTS (0x10)
#define DW_UART_MSR_DSR (0x20)
#define DW_UART_MSR_RIC (0x40)
#define DW_UART_MSR_DCD (0x80)
/**
* DesignWare UART hal FCR related macros
*/
/* FCR */
#define DW_UART_FCR_FEN (0x01)
#define DW_UART_FCR_RFR (0x02)
#define DW_UART_FCR_TFR (0x04)
#define DW_UART_FCR_DMS (0x08)
#define DW_UART_FCR_RTL (0xC0)
/**
* DesignWare UART hal USR related macros
*/
/* USR */
#define DW_UART_USR_BUSY (0x01)
#define DW_UART_USR_TFNF (0x02)
#define DW_UART_USR_TFE (0x04)
#define DW_UART_USR_RFNE (0x08)
#define DW_UART_USR_RFF (0x10)
/**
* DesignWare UART hal SFE related macros
*/
/* SFE */
#define DW_UART_SFE_SHADOW_FIFO_ENABLE (0x01)
/**
* DesignWare UART hal SRR related macros
*/
/* SRR */
#define DW_UART_SRR_UR (0x01)
#define DW_UART_SRR_RFR (0x02)
#define DW_UART_SRR_XFR (0x04)
/**
* DesignWare UART hal SRT related macros
*/
/* SRT */
#define DW_UART_SRT_TRIGGER_LEVEL_1_CHAR (0x00)
#define DW_UART_SRT_TRIGGER_LEVEL_1_4_FULL (0x01)
#define DW_UART_SRT_TRIGGER_LEVEL_1_2_FULL (0x02)
#define DW_UART_SRT_TRIGGER_LEVEL_2_LESS_FULL (0x03)
/**
* DesignWare UART hal STET related macros
*/
/* STET*/
#define DW_UART_STET_FIFO_EMPTY (0x00)
#define DW_UART_STET_2_CHARS_IN_FIFO (0x01)
#define DW_UART_STET_1_4_FULL (0x02)
#define DW_UART_STET_1_2_FULL (0x03)
/**
* DesignWare UART hal CPR related macros
*/
/* CPR*/
#define DW_UART_CPR_FIFO_STAT (1 << 10)
#define DW_UART_CPR_FIFO_MODE_OFS (16)
#define DW_UART_CPR_FIFO_MODE_MASK (0xFF)
#define DW_UART_CPR_FIFO_MODE (0xFF0000)
#endif /* H_DW_UART_HAL */

View File

@@ -1,176 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @defgroup DEVICE_HAL_COMMON Common Device Layer Definitions
* @ingroup DEVICE_HAL_DEF
* @brief Common definitions for device layer (@ref dev_common.h)
*
* @{
*
* @file
* @brief Header file to define common definitions for device layer
* @details Here in this file provide definitions that need by other
* devices in device layer
*/
#ifndef H_DEV_COMMON
#define H_DEV_COMMON
#include "embARC_toolchain.h"
/**
* @defgroup DEVICE_HAL_COMMON_DEVSTATE Common Device State
* @ingroup DEVICE_HAL_COMMON
* @brief Definitions for device state
* @details Common types and macro definitions for device open/close,
* device working good/error, used in @ref DEVICE_HAL_UART, @ref DEVICE_HAL_SPI,
* @ref DEVICE_HAL_IIC, @ref DEVICE_HAL_GPIO
* @{
*/
/*
* macros for device open and close state
*/
#define DEV_CLOSED (0) /*!< Indicate that device was closed */
#define DEV_OPENED (1) /*!< Indicate that the device was opened */
/*
* macros for device good and error state
*/
#define DEV_GOOD (0) /*!< Indicate device is good */
#define DEV_ERROR (1) /*!< Indicate device error */
/** @} */
/**
* @defgroup DEVICE_HAL_COMMON_DEVMTHD Common Device Working Method
* @ingroup DEVICE_HAL_COMMON
* @brief Definitions for device working method(interrupt or poll)
* @details Common macro definitions for working method,
* interrupt or poll method,used in @ref DEVICE_HAL_UART, @ref DEVICE_HAL_SPI,
* @ref DEVICE_HAL_IIC, @ref DEVICE_HAL_GPIO
* @{
*/
/*
* macros for device working method
*/
#define DEV_POLL_METHOD (0) /*!< Indicate that the device running in poll method */
#define DEV_INTERRUPT_METHOD (1) /*!< Indicate that the device running in interrupt method */
/** @} */
/**
* @defgroup DEVICE_HAL_COMMON_DEVMODE Common Device Working Mode
* @ingroup DEVICE_HAL_COMMON
* @brief Definitions for device working mode(master or slave)
* @details Common macro definitions for working mode, Master or Slave mode,
* used in @ref DEVICE_HAL_IIC, @ref DEVICE_HAL_SPI.
* @{
*/
/*
* macros for device working mode
*/
#define DEV_MASTER_MODE (0) /*!< Indicate that the device working as master */
#define DEV_SLAVE_MODE (1) /*!< Indicate that the device working as slave */
/** @} */
/**
* @defgroup DEVICE_HAL_COMMON_DEVSTATUS Common Device Status
* @ingroup DEVICE_HAL_COMMON
* @brief Definitions for device status, 1 bit for 1 function
* @{
*/
#define DEV_DISABLED (0) /*!< Bit 0 for device enabled state, disabled */
#define DEV_ENABLED (1 << 0) /*!< Bit 0 for device enabled state, enabled */
#define DEV_IN_TX (1 << 1) /*!< Bit 1 for device in transmit state */
#define DEV_IN_RX (1 << 2) /*!< Bit 2 for device in receive state */
#define DEV_IN_XFER (1 << 3) /*!< Bit 3 for device in transfer state */
#define DEV_IN_TX_ABRT (1 << 4) /*!< Bit 4 for device in transmit abort state */
#define DEV_IN_RX_ABRT (1 << 5) /*!< Bit 5 for device in receive abort state */
#define DEV_IN_XFER_ABRT (1 << 6) /*!< Bit 6 for device in transfer abort state */
/** @} */
/**
* Invalid Interrupt Vector Number
* When interrupt number is set to this value,
* all interrupt related function in the device
* driver source code shouldn't be called,
* that means the interrupt processing maybe done
* in outside of device driver, maybe done in the device
* object instantiation
*/
#define DEV_INTNO_INVALID (0xFFFFFFFF)
/**
* @defgroup DEVICE_HAL_COMMON_DEFCMD Common Device Defining Command
* @ingroup DEVICE_HAL_COMMON
* @brief Definitions for defining command code
* @details Common macro definitions to define command code,
* in system code, use @ref DEV_SET_SYSCMD to define command code.
* in user code, use @ref DEV_SET_USRCMD to define command code.
* So that there will be no conflicts in system and user defined command code.
* this used used in @ref DEVICE_HAL_UART, @ref DEVICE_HAL_SPI,
* @ref DEVICE_HAL_IIC, @ref DEVICE_HAL_GPIO, and in user code
* @{
*/
/*
* macros for control command base
*/
#define DEV_SYS_CMDBSE (0x00000000) /*!< default system device control command base(defined by embARC) */
#define DEV_USR_CMDBSE (0x80000000) /*!< default user device control command base(defined by user) in user implementing */
#define DEV_SET_SYSCMD(cmd) (DEV_SYS_CMDBSE | (cmd)) /*!< set device system control command */
#define DEV_SET_USRCMD(cmd) (DEV_USR_CMDBSE | (cmd)) /*!< set device user control command */
#define CONV2VOID(param) ((void *)(param)) /*!< convert param into void * type */
/** @} */
/**
* Common Device Buffer Structure
*/
typedef struct {
void *buf; /*!< buffer pointer */
uint32_t len; /*!< buffer length in bytes */
uint32_t ofs; /*!< current offset in buffer */
} DEV_BUFFER;
/** Init device buffer */
#define DEV_BUFFER_INIT(devbuf, buffer, size) { \
(devbuf)->buf = (void *)(buffer); \
(devbuf)->len = (uint32_t)(size); \
(devbuf)->ofs = (uint32_t)(0); \
}
/**
* Device callback function typedef.
* This is usually used in device callback settings,
* and @b ptr should be the device object pointer,
* such as DEV_IIC * */
typedef void (*DEV_CALLBACK) (void *ptr);
/** @} */
#endif /* H_DEV_COMMON */

View File

@@ -1,124 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_DEV_PINMUX
#define H_DEV_PINMUX
#include "embARC_toolchain.h"
#define IO_PINMUX_ENABLE 1
#define IO_PINMUX_DISABLE 0
typedef enum {
ARDUINO_PIN_0 = 0,
ARDUINO_PIN_1,
ARDUINO_PIN_2,
ARDUINO_PIN_3,
ARDUINO_PIN_4,
ARDUINO_PIN_5,
ARDUINO_PIN_6,
ARDUINO_PIN_7,
ARDUINO_PIN_8,
ARDUINO_PIN_9,
ARDUINO_PIN_10,
ARDUINO_PIN_11,
ARDUINO_PIN_12,
ARDUINO_PIN_13,
ARDUINO_PIN_AD0,
ARDUINO_PIN_AD1,
ARDUINO_PIN_AD2,
ARDUINO_PIN_AD3,
ARDUINO_PIN_AD4,
ARDUINO_PIN_AD5,
ARDUINO_PIN_NONE
} ARDUINO_PIN;
typedef enum {
PMOD_0 = 0,
PMOD_1,
PMOD_2,
PMOD_3,
PMOD_4,
PMOD_5,
PMOD_6,
PMOD_A = 0,
PMOD_B,
PMOD_C,
PMOD_D,
PMOD_E,
PMOD_NUM_NONE,
} PMOD_PORT;
typedef enum {
PMOD_GPIO = 0,
PMOD_UART,
PMOD_SPI,
PMOD_I2C,
PMOD_PWM_MODE1,
PMOD_PWM_MODE2,
PMOD_PWM_MODE3,
PMOD_NONE
} PMOD_TYPE;
typedef enum {
ARDUINO_GPIO = 0,
ARDUINO_UART,
ARDUINO_SPI,
ARDUINO_I2C,
ARDUINO_PWM,
ARDUINO_ADC,
ARDUINO_NONE
} ARDUINO_TYPE;
typedef enum {
PINMUX_TYPE_DEFAULT = 0,
PINMUX_TYPE_ARDUINO,
PINMUX_TYPE_PMOD,
PINMUX_TYPE_MIKRO,
PINMUX_TYPE_NONE
} PINMUX_TYPE;
#ifdef __cplusplus
extern "C" {
#endif
extern void io_mux_init(void);
extern int32_t io_pmod_config(uint32_t pmod, uint32_t type, uint32_t config);
extern int32_t io_mikro_config(uint32_t config);
extern int32_t io_arduino_config(uint32_t pin_num, uint32_t type, uint32_t config);
extern int32_t io_arduino_config_spi(uint32_t config);
extern int32_t io_arduino_config_uart(uint32_t config);
extern int32_t io_arduino_config_i2c(uint32_t config);
#ifdef __cplusplus
}
#endif
#endif /* H_DEV_PINMUX */

View File

@@ -1,498 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @defgroup DEVICE_HAL_GPIO GPIO Device HAL Interface
* @ingroup DEVICE_HAL_DEF
* @brief Definitions for gpio device hardware layer (@ref dev_gpio.h)
* @details Provide interfaces for gpio driver to implement
*
* @{
*
* @file
* @brief Definitions for gpio device hardware layer
* @details Provide common definitions for gpio device,
* then the software developer can develop gpio driver
* following these definitions, and the applications
* can directly call this definition to realize functions
*
*/
#ifndef H_DEV_GPIO
#define H_DEV_GPIO
#include "device/dev_common.h"
/**
* @defgroup DEVICE_HAL_GPIO_DEFDIR GPIO Port Direction Definition
* @ingroup DEVICE_HAL_GPIO
* @brief Macros definitions for gpio port
* @{
*/
/*
* defines for gpio directions
*/
#define GPIO_DIR_INPUT (0) /*!< gpio works as input */
#define GPIO_DIR_OUTPUT (1) /*!< gpio works as output */
/** @} */
/**
* @defgroup DEVICE_HAL_GPIO_PINDEF GPIO Pin definitions
* @ingroup DEVICE_HAL_GPIO
* @brief Macros definitions for gpio pins
* @{
*/
/** Macro to define a gpio pin, start from 0 */
#define DEV_GPIO_PIN_DEF(pin) ((pin) & 0xFFFF)
/** gpio pin defintions */
typedef enum {
DEV_GPIO_PIN_0 = 0, /*!< GPIO Pin 0 */
DEV_GPIO_PIN_1, /*!< GPIO Pin 1 */
DEV_GPIO_PIN_2, /*!< GPIO Pin 2 */
DEV_GPIO_PIN_3, /*!< GPIO Pin 3 */
DEV_GPIO_PIN_4, /*!< GPIO Pin 4 */
DEV_GPIO_PIN_5, /*!< GPIO Pin 5 */
DEV_GPIO_PIN_6, /*!< GPIO Pin 6 */
DEV_GPIO_PIN_7, /*!< GPIO Pin 7 */
DEV_GPIO_PIN_8, /*!< GPIO Pin 8 */
DEV_GPIO_PIN_9, /*!< GPIO Pin 9 */
DEV_GPIO_PIN_10, /*!< GPIO Pin 10 */
DEV_GPIO_PIN_11, /*!< GPIO Pin 11 */
DEV_GPIO_PIN_12, /*!< GPIO Pin 12 */
DEV_GPIO_PIN_13, /*!< GPIO Pin 13 */
DEV_GPIO_PIN_14, /*!< GPIO Pin 14 */
DEV_GPIO_PIN_15, /*!< GPIO Pin 15 */
DEV_GPIO_PIN_16, /*!< GPIO Pin 16 */
DEV_GPIO_PIN_17, /*!< GPIO Pin 17 */
DEV_GPIO_PIN_18, /*!< GPIO Pin 18 */
DEV_GPIO_PIN_19, /*!< GPIO Pin 19 */
DEV_GPIO_PIN_20, /*!< GPIO Pin 20 */
DEV_GPIO_PIN_21, /*!< GPIO Pin 21 */
DEV_GPIO_PIN_22, /*!< GPIO Pin 22 */
DEV_GPIO_PIN_23, /*!< GPIO Pin 23 */
DEV_GPIO_PIN_24, /*!< GPIO Pin 24 */
DEV_GPIO_PIN_25, /*!< GPIO Pin 25 */
DEV_GPIO_PIN_26, /*!< GPIO Pin 26 */
DEV_GPIO_PIN_27, /*!< GPIO Pin 27 */
DEV_GPIO_PIN_28, /*!< GPIO Pin 28 */
DEV_GPIO_PIN_29, /*!< GPIO Pin 29 */
DEV_GPIO_PIN_30, /*!< GPIO Pin 30 */
DEV_GPIO_PIN_31, /*!< GPIO Pin 31 */
DEV_GPIO_PIN_NC = 0xFFFFFFFF /*!< GPIO Pin Not Connected */
} DEV_GPIO_PIN;
/** Macro to define a gpio port, start from 0 */
#define DEV_GPIO_PORT_DEF(port) ((port) & 0xFFFF)
/** Macro to define a gpio port-pin(such as P0.0 or PA.0, start from 0 */
#define DEV_GPIO_PORT_PIN_DEF(port, pin) (((port) << 16) | ((pin) & 0xFFFF))
/** gpio port defintions */
typedef enum {
DEV_GPIO_PORT_0 = 0, /*!< GPIO Port 0 */
DEV_GPIO_PORT_1, /*!< GPIO Port 1 */
DEV_GPIO_PORT_2, /*!< GPIO Port 2 */
DEV_GPIO_PORT_3, /*!< GPIO Port 3 */
DEV_GPIO_PORT_4, /*!< GPIO Port 4 */
DEV_GPIO_PORT_5, /*!< GPIO Port 5 */
DEV_GPIO_PORT_6, /*!< GPIO Port 6 */
DEV_GPIO_PORT_7, /*!< GPIO Port 7 */
DEV_GPIO_PORT_8, /*!< GPIO Port 8 */
DEV_GPIO_PORT_9, /*!< GPIO Port 9 */
DEV_GPIO_PORT_10, /*!< GPIO Port 10 */
DEV_GPIO_PORT_A = 0, /*!< GPIO Port A */
DEV_GPIO_PORT_B = 1, /*!< GPIO Port B */
DEV_GPIO_PORT_C = 2, /*!< GPIO Port C */
DEV_GPIO_PORT_D = 3, /*!< GPIO Port D */
DEV_GPIO_PORT_E = 4, /*!< GPIO Port E */
DEV_GPIO_PORT_F = 5, /*!< GPIO Port F */
DEV_GPIO_PORT_G = 6, /*!< GPIO Port G */
DEV_GPIO_PORT_H = 7, /*!< GPIO Port H */
DEV_GPIO_PORT_I = 8, /*!< GPIO Port I */
DEV_GPIO_PORT_J = 9, /*!< GPIO Port J */
DEV_GPIO_PORT_K = 10, /*!< GPIO Port K */
DEV_GPIO_PORT_NC = 0xFFFFFFFF /*!< GPIO Port Not Connected */
} DEV_GPIO_PORT;
/** @} */
/**
* @defgroup DEVICE_HAL_GPIO_CTRLCMD GPIO Device Control Commands
* @ingroup DEVICE_HAL_GPIO
* @brief Definitions for gpio control command, used in @ref DEV_GPIO::gpio_control "GPIO IO Control"
* @details These commands defined here can be used in user code directly.
* - Parameters Usage
* - For passing parameters like integer, just use uint32_t/int32_t to directly pass values
* - For passing parameters for a structure, please use pointer to pass values
* - For getting some data, please use pointer to store the return data
* - Common Return Values
* - @ref E_OK, Control device successfully
* - @ref E_CLSED, Device is not opened
* - @ref E_OBJ, Device object is not valid or not exists
* - @ref E_PAR, Parameter is not valid for current control command
* - @ref E_SYS, Control device failed, due to hardware issues such as device is disabled
* - @ref E_NOSPT, Control command is not supported or not valid
* @{
*/
/**
* Set the @ref DEV_GPIO_INFO::direction "direction" of masked bits of gpio port into @ref GPIO_DIR_INPUT "input"
* - Param type : uint32_t
* - Param usage : 1 in each bit will be masked.
* - Return value explanation :
*/
#define GPIO_CMD_SET_BIT_DIR_INPUT DEV_SET_SYSCMD(0)
/**
* Set the @ref DEV_GPIO_INFO::direction "direction" of masked bits of gpio port into @ref GPIO_DIR_OUTPUT "output"
* - Param type : uint32_t
* - Param usage : 1 in each bit will be masked.
* - Return value explanation :
*/
#define GPIO_CMD_SET_BIT_DIR_OUTPUT DEV_SET_SYSCMD(1)
/**
* Get @ref DEV_GPIO_INFO::direction "gpio port direction".
* - Param type : uint32_t
* - Param usage : 1 bit for 1 bit of gpio port, 0 for input, 1 for output
* - Return value explanation :
*/
#define GPIO_CMD_GET_BIT_DIR DEV_SET_SYSCMD(2)
/**
* Set gpio interrupt configuration for each bit.
* - Param type : @ref DEV_GPIO_INT_CFG *
* - Param usage : store gpio interrupt configuration for each bit.
* - Return value explanation :
*/
#define GPIO_CMD_SET_BIT_INT_CFG DEV_SET_SYSCMD(3)
/**
* Get gpio interrupt configuration for each bit.
* - Param type : @ref DEV_GPIO_INT_CFG *
* - Param usage : First set int_bit_mask in DEV_GPIO_INT_CFG structure to
* the mask of which bit of GPIO you want to get. And the interrupt configuration
* will be stored in the structure DEV_GPIO_INT_CFG, each bit stand for each bit of port.
* - Return value explanation :
*/
#define GPIO_CMD_GET_BIT_INT_CFG DEV_SET_SYSCMD(4)
/**
* Set gpio service routine for each bit.
* - Param type : @ref DEV_GPIO_BIT_ISR *
* - Param usage : store gpio handler information for each bit, int handler's param will be DEV_GPIO *.
* - Return value explanation :
*/
#define GPIO_CMD_SET_BIT_ISR DEV_SET_SYSCMD(5)
/**
* Get gpio service routine for each bit.
* - Param type : @ref DEV_GPIO_BIT_ISR *
* - Param usage : By passing int_bit_ofs in DEV_GPIO_BIT_ISR,
* it will return interrupt handler for this bit and store it in int_bit_handler.
* - Return value explanation :
*/
#define GPIO_CMD_GET_BIT_ISR DEV_SET_SYSCMD(6)
/**
* Enable gpio interrupt of the masked bits.
* - Param type : uint32_t
* - Param usage : 1 in each bit will be masked.
* - Return value explanation :
*/
#define GPIO_CMD_ENA_BIT_INT DEV_SET_SYSCMD(7)
/**
* Disable gpio interrupt of the masked bits.
* - Param type : uint32_t
* - Param usage : 1 in each bit will be masked.
* - Return value explanation :
*/
#define GPIO_CMD_DIS_BIT_INT DEV_SET_SYSCMD(8)
/**
* Get @ref DEV_GPIO_INFO::method "gpio interrupt enable status".
* - Param type : uint32_t *
* - Param usage : 1 bit for 1 bit of gpio port, 0 for poll, 1 for interrupt
* - Return value explanation :
*/
#define GPIO_CMD_GET_BIT_MTHD DEV_SET_SYSCMD(9)
/**
* Toggle GPIO output of the masked bits(pins).
* - Param type : uint32_t
* - Param usage : 1 in each bit will be masked.
* - Return value explanation :
*/
#define GPIO_CMD_TOGGLE_BITS DEV_SET_SYSCMD(10)
/** @} */
/**
* @defgroup DEVICE_HAL_GPIO_INT_CFG_SET GPIO Device Int Configuration Settings
* @ingroup DEVICE_HAL_GPIO
* @brief Structure and macro definitions for gpio interrupt
* @{
*/
/* GPIO Mask Defintions */
/** Mask none bits of the max 32bits */
#define GPIO_BITS_MASK_NONE (0)
/** Mask all bits of the max 32bits */
#define GPIO_BITS_MASK_ALL (0XFFFFFFFF)
/* GPIO Interrupt Type Related Definitions */
/** Level sensitive interrupt type for 1 bit */
#define GPIO_INT_LEVEL_TRIG (0)
/** Edge sensitive interrupt type for 1 bit */
#define GPIO_INT_EDGE_TRIG (1)
/** Level sensitive interrupt type for all 32 bits */
#define GPIO_INT_LEVEL_TRIG_ALL (0)
/** Edge sensitive interrupt type for all 32 bits */
#define GPIO_INT_EDGE_TRIG_ALL (0XFFFFFFFF)
/* For bit settings */
/** Set bit interrupt type of gpio into level sensitive */
#define GPIO_INT_BIT_LEVEL_TRIG(bit_ofs) (GPIO_INT_LEVEL_TRIG << (bit_ofs))
/** Set bit interrupt type of gpio into edge sensitive */
#define GPIO_INT_BIT_EDGE_TRIG(bit_ofs) (GPIO_INT_EDGE_TRIG << (bit_ofs))
/* For bits settings */
/** Set interrupt type of masked bits of gpio into level sensitive */
#define GPIO_INT_BITS_LEVEL_TRIG(bit_mask) (GPIO_INT_LEVEL_TRIG_ALL & (bit_mask))
/** Set bit interrupt type of gpio into edge sensitive */
#define GPIO_INT_BITS_EDGE_TRIG(bit_mask) (GPIO_INT_EDGE_TRIG_ALL & (bit_mask))
/* GPIO Interrupt Polarity Related Definitions */
/** GPIO Interrupt polarity type enum */
typedef enum gpio_int_polarity {
/* Polarity for 1 bit */
GPIO_INT_ACTIVE_LOW = 0, /*!< Active low for level-sensitive interrupt for 1 bit */
GPIO_INT_FALLING_EDGE = 0, /*!< Falling-edge for edge-sensitive interrupt for 1 bit */
GPIO_INT_ACTIVE_HIGH = 1, /*!< Active high for level-sensitive interrupt for 1 bit */
GPIO_INT_RISING_EDGE = 1, /*!< Rising-edge for edge-sensitive interrupt for 1 bit */
/* Polartiy for all 32 bits */
GPIO_INT_ACTIVE_LOW_ALL = 0, /*!< Active low for level-sensitive interrupt for all bits */
GPIO_INT_FALLING_EDGE_ALL = 0, /*!< Falling-edge for edge-sensitive interrupt for all bits */
GPIO_INT_ACTIVE_HIGH_ALL = 0XFFFFFFFF, /*!< Active high for level-sensitive interrupt for all bits */
GPIO_INT_RISING_EDGE_ALL = 0XFFFFFFFF /*!< Rising-edge for edge-sensitive interrupt for all bits */
} GPIO_INT_POLARITY;
/* For bit settings */
/** Set bit polarity of gpio into active low */
#define GPIO_INT_BIT_POL_ACT_LOW(bit_ofs) (GPIO_INT_ACTIVE_LOW << (bit_ofs))
/** Set bit polarity of gpio into active high */
#define GPIO_INT_BIT_POL_ACT_HIGH(bit_ofs) (GPIO_INT_ACTIVE_HIGH << (bit_ofs))
/** Set bit polarity of gpio into falling edge */
#define GPIO_INT_BIT_POL_FALL_EDGE(bit_ofs) (GPIO_INT_FALLING_EDGE << (bit_ofs))
/** Set bit polarity of gpio into rising edge */
#define GPIO_INT_BIT_POL_RISE_EDGE(bit_ofs) (GPIO_INT_RISING_EDGE << (bit_ofs))
/* For bits settings */
/** Set polarity of masked bits of gpio into active low */
#define GPIO_INT_BITS_POL_ACT_LOW(bit_mask) (GPIO_INT_ACTIVE_LOW_ALL & (bit_mask))
/** Set polarity of masked bits of gpio into active high */
#define GPIO_INT_BITS_POL_ACT_HIGH(bit_mask) (GPIO_INT_ACTIVE_HIGH_ALL & (bit_mask))
/** Set polarity of masked bits of gpio into falling edge */
#define GPIO_INT_BITS_POL_FALL_EDGE(bit_mask) (GPIO_INT_FALLING_EDGE_ALL & (bit_mask))
/** Set polarity of masked bits of gpio into rising edge */
#define GPIO_INT_BITS_POL_RISE_EDGE(bit_mask) (GPIO_INT_RISING_EDGE_ALL & (bit_mask))
/* GPIO Interrupt Debounce Related Definitions */
/* For bit settings */
/** Disable debounce circuitry for 1 bit */
#define GPIO_INT_NO_DEBOUNCE (0)
/** Enable debounce circuitry for 1 bit */
#define GPIO_INT_DEBOUNCE (1)
/* For bits settings */
/** Disable debounce circuitry for all bits */
#define GPIO_INT_NO_DEBOUNCE_ALL (0)
/** Enable debounce circuitry for all bits */
#define GPIO_INT_DEBOUNCE_ALL (0XFFFFFFFF)
/* For bit settings */
/** Set bit interrupt debounce of gpio into enabled */
#define GPIO_INT_BIT_ENA_DEBOUNCE(bit_ofs) (GPIO_INT_DEBOUNCE << (bit_ofs))
/** Set bit interrupt debounce of gpio into disabled */
#define GPIO_INT_BIT_DIS_DEBOUNCE(bit_ofs) (GPIO_INT_NO_DEBOUNCE << (bit_ofs))
/* For bits settings */
/** Set bit interrupt debounce of gpio into enabled */
#define GPIO_INT_BITS_ENA_DEBOUNCE(bit_mask) (GPIO_INT_DEBOUNCE_ALL & (bit_mask))
/** Set bit interrupt debounce of gpio into disabled */
#define GPIO_INT_BITS_DIS_DEBOUNCE(bit_mask) (GPIO_INT_NO_DEBOUNCE_ALL & (bit_mask))
/** GPIO interrupt configuration */
typedef struct {
uint32_t int_bit_mask; /*!< interrupt bit mask for gpio */
uint32_t int_bit_type; /*!< @ref GPIO_INT_LEVEL_TRIG "level sensitive" or @ref GPIO_INT_EDGE_TRIG "edge sensitive" for each gpio bit */
uint32_t int_bit_polarity; /*!< active high or low, refer to @ref GPIO_INT_POLARITY for each gpio bit */
uint32_t int_bit_debounce; /*!< @ref GPIO_INT_DEBOUNCE "enable" or @ref GPIO_INT_NO_DEBOUNCE "disable" debounce logic for each gpio bit */
} DEV_GPIO_INT_CFG, *DEV_GPIO_INT_CFG_PTR;
/** Default interrupt configuration for all gpio bits */
static const DEV_GPIO_INT_CFG gpio_int_cfg_default = \
{ GPIO_BITS_MASK_ALL, GPIO_INT_LEVEL_TRIG_ALL, \
GPIO_INT_ACTIVE_LOW_ALL, GPIO_INT_NO_DEBOUNCE_ALL };
/** GPIO interrupt handler or Interrupt Service Routine(ISR) */
typedef void (*DEV_GPIO_HANDLER) (void *ptr);
/** interrupt handler for each port bit */
typedef struct {
uint32_t int_bit_ofs; /*!< int bit offset */
DEV_GPIO_HANDLER int_bit_handler; /*!< interrupt handler */
} DEV_GPIO_BIT_ISR, *DEV_GPIO_BIT_ISR_PTR;
/** @} */
/**
* @defgroup DEVICE_HAL_GPIO_DEVSTRUCT GPIO Device Interface Definition
* @ingroup DEVICE_HAL_GPIO
* @brief Structure and macro definitions for gpio device structure
* @details This structure will be used in user implemented code, which was called
* @ref DEVICE_IMPL "Device Driver Implement Layer" for gpio to use in implementation code.
* Application developer should use the GPIO API provided here to access to GPIO devices.
* BSP developer should follow the API definition to implement GPIO device drivers.
* @{
*/
/**
* @brief Gpio information struct definition
* @details Informations about gpio open count, working status
* gpio registers and control block, gpio io direction and interrupt/poll for each bit of gpio
* @note Only available for gpio with max 32bits
*/
typedef struct {
void *gpio_ctrl; /*!< gpio control related pointer, implemented by bsp developer, and this should be set during gpio object implementation */
uint32_t opn_cnt; /*!< gpio open count, open it will increase 1, close it will decrease 1, 0 for close, >0 for open */
uint32_t direction; /*!< each bit direction of this GPIO, default all @ref GPIO_DIR_INPUT "input" for first open */
uint32_t method; /*!< int/poll method for each bit of GPIO, 0 for poll, 1 for interrupt, default all @ref DEV_POLL_METHOD "poll" for first open */
uint32_t bitofs; /*!< current in response interrupt pin offset */
void *extra; /*!< a extra pointer to get hook to applications which should not used by bsp developer,
this should be NULL for first open and you can @ref DEV_GPIO_INFO_SET_EXTRA_OBJECT "set"
or \ref DEV_GPIO_INFO_GET_EXTRA_OBJECT "get" the extra information pointer */
} DEV_GPIO_INFO, *DEV_GPIO_INFO_PTR;
/** Set extra information pointer of gpio info */
#define DEV_GPIO_INFO_SET_EXTRA_OBJECT(gpio_info_ptr, extra_info) (gpio_info_ptr)->extra = (void *)(extra_info)
/** Get extra information pointer of gpio info */
#define DEV_GPIO_INFO_GET_EXTRA_OBJECT(gpio_info_ptr) ((gpio_info_ptr)->extra)
/** Method of all gpio bits set to poll */
#define DEV_GPIO_BITS_MTHD_POLL (0)
/** Method of all gpio bits set to interrupt */
#define DEV_GPIO_BITS_MTHD_INTERRUPT (0xFFFFFFFF)
/** Default method of all gpio bits should be poll for first open */
#define DEV_GPIO_BITS_MTHD_DEFAULT (DEV_GPIO_BITS_MTHD_POLL)
/**
* @brief Definitions for gpio device interface
* @details Define gpio device interface, like gpio information structure,
* fuctions to open/close/control gpio, write or read data via gpio
* @note All this details are implemented by user in user porting code
*/
typedef struct {
DEV_GPIO_INFO gpio_info; /*!< gpio device information */
int32_t (*gpio_open)(uint32_t dir); /*!< open gpio device with pre-defined gpio direction */
int32_t (*gpio_close)(void); /*!< close gpio device */
int32_t (*gpio_control)(uint32_t ctrl_cmd, void *param); /*!< control gpio device */
int32_t (*gpio_write)(uint32_t val, uint32_t mask); /*!< write gpio device with val, only write the masked bits */
int32_t (*gpio_read)(uint32_t *val, uint32_t mask); /*!< read gpio device val, only read the masked bits */
} DEV_GPIO, *DEV_GPIO_PTR;
/**
* @fn int32_t *DEV_GPIO::gpio_open(uint32_t dir)
* @details Open a gpio device with pre-defined io direction.
* @param[in] dir Gpio direction for each bit
* @retval E_OK Open successfully without any issues
* @retval E_OPNED If device was opened before with different parameters,
* then just increase the @ref DEV_GPIO_INFO::opn_cnt "opn_cnt" and return @ref E_OPNED
* @retval E_OBJ Device object is not valid
* @retval E_PAR Parameter is not valid
* @retval E_NOSPT Open settings are not supported
*/
/**
* @fn int32_t *DEV_GPIO::gpio_close(void)
* @details Close a gpio device, just decrease the @ref DEV_GPIO_INFO::opn_cnt "opn_cnt",
* if @ref DEV_GPIO_INFO::opn_cnt "opn_cnt" equals 0, then close the device
* @retval E_OK Close successfully without any issues(including scenario that device is already closed)
* @retval E_OPNED Device is still opened, the device @ref DEV_GPIO_INFO::opn_cnt "opn_cnt" decreased by 1
* @retval E_OBJ Device object is not valid
*/
/**
* @fn int32_t *DEV_GPIO::gpio_control(uint32_t ctrl_cmd, void *param)
* @details Control an gpio device by ctrl_cmd, with passed param.
* you can control gpio device using predefined gpio control commands defined using @ref DEV_SET_SYSCMD
* (which must be implemented by bsp developer), such as @ref GPIO_CMD_SET_BIT_DIR_INPUT
* "change masked gpio direction to input", and @ref DEVICE_HAL_GPIO_CTRLCMD "more".
* And you can also control gpio device using your own specified commands defined using @ref DEV_SET_USRCMD,
* but these specified commands should be defined in your own gpio device driver implementation.
* @param[in] ctrl_cmd @ref DEVICE_HAL_GPIO_CTRLCMD "control command", to change or get some thing related to gpio
* @param[in,out] param Parameters that maybe argument of the command, or return values of the command
* @retval E_OK Control device successfully
* @retval E_CLSED Device is not opened
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid for current control command
* @retval E_SYS Control device failed, due to hardware issues
* @retval E_CTX Control device failed, due to different reasons like in transfer state
* @retval E_NOSPT Control command is not supported or not valid, such as interrupt is not supported
*/
/**
* @fn int32_t *DEV_GPIO::gpio_write(uint32_t val, uint32_t mask)
* @details Write gpio with val, and only change the masked bits of gpio.
* @param[in] val Data that need to write to gpio
* @param[in] mask gpio bit mask
* @retval E_OK Write gpio successfully without any issues
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid
*/
/**
* @fn int32_t *DEV_GPIO::gpio_read(uint32_t *val, uint32_t mask)
* @details Read the masked gpio value
* @param[out] val Pointer to data need to read from gpio
* @param[in] mask GPIO bit mask
* @retval E_OK Read gpio data successfully without any issues
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid
*/
/** @} */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get an @ref DEV_GPIO "gpio device" by gpio device id.
* For how to use gpio device hal refer to @ref DEV_GPIO "Functions in gpio device structure"
* @param[in] gpio_id ID of gpio, defined by user
* @retval !NULL Pointer to an @ref DEV_GPIO "gpio device structure"
* @retval NULL Failed to find the gpio device by gpio_id
* \note Need to implemented in user code
*/
extern DEV_GPIO_PTR gpio_get_dev(int32_t gpio_id);
#ifdef __cplusplus
}
#endif
#endif /* H_DEV_GPIO */
/** @} */

View File

@@ -1,465 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @defgroup DEVICE_HAL_I2S I2S Device HAL Interface
* @ingroup DEVICE_HAL_DEF
* @brief Definitions for I2S device hardware layer (@ref dev_i2s.h)
* @details Provide unified APIs for I2S driver to implement.
*
* @{
*
* @file
* @brief Definitions for I2S device hardware layer
* @details Provide common definitions for I2S device,
* then software developer can develop I2S driver
* following this definitions, and the applications
* can directly call this definition to realize functions
*
*/
#ifndef H_DEV_I2S
#define H_DEV_I2S
#include "device/dev_common.h"
/**
* @defgroup DEVICE_HAL_I2S_CFG I2S Related Configurations
* @ingroup DEVICE_HAL_I2S
* @brief Type and macro definitions for I2S device
* @{
*/
/**
* @defgroup I2S_AUD_DATA_RES I2S Audio Data Resolution
* @ingroup DEVICE_HAL_I2S_CFG
* @brief Definitions for I2S audio data resolution
* @{
*/
typedef enum {
I2S_AUD_DATA_NA = 0, /*!< N/A data resolution */
I2S_AUD_DATA_12B = 1, /*!< 12 bits audio data resolution */
I2S_AUD_DATA_16B = 2, /*!< 16 bits audio data resolution */
I2S_AUD_DATA_20B = 3, /*!< 20 bits audio data resolution */
I2S_AUD_DATA_24B = 4, /*!< 24 bits audio data resolution */
I2S_AUD_DATA_32B = 5 /*!< 32 bits audio data resolution */
} I2S_AUD_DATA_RES;
/** @} */
/**
* @defgroup I2S_AUD_SAMPLE_RATE I2S Audio Sampling Rate
* @ingroup DEVICE_HAL_I2S_CFG
* @brief Definitions for I2S audio sampling rate
* @{
*/
typedef enum {
I2S_AUD_SR_NA = 0, /*!< N/A audio sample rate */
I2S_AUD_SR_16K = 1, /*!< 16KHz audio sample rate */
I2S_AUD_SR_32K = 2, /*!< 32KHz audio sample rate */
I2S_AUD_SR_44_1K = 3, /*!< 44.1KHz audio sample rate */
I2S_AUD_SR_48K = 4, /*!< 48KHz audio sample rate */
I2S_AUD_SR_96K = 5, /*!< 96KHz audio sample rate */
I2S_AUD_SR_192K = 6 /*!< 192KHz audio sample rate */
} I2S_AUD_SAMPLE_RATE;
/** @} */
/**
* @defgroup I2S_DEVICE_TYPE I2S Device Type
* @ingroup DEVICE_HAL_I2S_CFG
* @brief Definitions for I2S device type
* @{
*/
typedef enum {
I2S_DEVICE_TRANSMITTER = 0, /*!< I2S TX device */
I2S_DEVICE_RECEIVER = 1 /*!< I2S RX device */
} I2S_DEVICE_TYPE;
/** @} */
/**
* @defgroup I2S_WORKING_STATE I2S Working State
* @ingroup DEVICE_HAL_I2S_CFG
* @brief Definitions for I2S working state
* @{
*/
typedef enum {
I2S_FREE = 0, /*!< Currently in I2S device free state */
I2S_IN_TX = 1, /*!< Currently in I2S master transmit state */
I2S_IN_RX = 2 /*!< Currently in I2S master receive state */
} I2S_WORKING_STATE;
/** @} */
/**
* @defgroup I2S_ERROR_STATE I2S Error State
* @ingroup DEVICE_HAL_I2S_CFG
* @brief Definitions for I2S error state
* @{
*/
typedef enum {
I2S_ERR_NONE = 0, /*!< Currently in I2S device free state */
I2S_ERR_RX_OVERRUN = 1, /*!< RX FIFO data overrun */
I2S_ERR_TX_OVERRUN = 2, /*!< TX FIFO data overrun */
I2S_ERR_UNDEF = 3 /*!< Undefined error cases */
} I2S_ERROR_STATE;
/** @} */
/** @} */
/**
* @defgroup DEVICE_HAL_I2S_CTRLCMD I2S Device Control Commands
* @ingroup DEVICE_HAL_I2S
* @brief Definitions for I2S control command, used in @ref DEV_I2S::i2s_control "I2S Control"
* @details These commands defined here can be used in user code directly.
* - Parameters Usage
* - For passing parameters like integer, just use uint32_t/int32_t to directly pass values
* - For passing parameters for a structure, please use pointer to pass values
* - For getting some data, please use pointer to store the return data
* - Common Return Values
* - @ref E_OK, Control device successfully
* - @ref E_CLSED, Device is not opened
* - @ref E_OBJ, Device object is not valid or not exists
* - @ref E_PAR, Parameter is not valid for current control command
* - @ref E_SYS, Control device failed, due to hardware issues such as device is disabled
* - @ref E_CTX, Control device failed, due to different reasons like in transfer state
* - @ref E_NOSPT, Control command is not supported or not valid
* @{
*/
/** Define I2S control commands for common usage */
#define DEV_SET_I2S_SYSCMD(cmd) DEV_SET_SYSCMD((cmd))
/** Define I2S control commands for master usage */
#define DEV_SET_I2S_MST_SYSCMD(cmd) DEV_SET_SYSCMD(0x00010000 | (cmd))
/* ++++ Common commands for SPI Device ++++ */
/**
* Get @ref DEV_I2S_INFO::status "current device status"
* - Param type : uint32_t *
* - Param usage : store result of current status
* - Return value explanation :
*/
#define I2S_CMD_GET_STATUS DEV_SET_I2S_SYSCMD(0)
/**
* Set @ref DEV_I2S_CBS::tx_cb "I2S transmit success callback" function
* when all required bytes are transmitted for interrupt method
* - Param type : @ref DEV_CALLBACK * or NULL
* - Param usage : transmit success callback function for I2S
* - Return value explanation :
*/
#define I2S_CMD_SET_TXCB DEV_SET_I2S_SYSCMD(1)
/**
* Set @ref DEV_I2S_CBS::rx_cb "I2S receive success callback" function
* when all required bytes are received for interrupt method
* - Param type : @ref DEV_CALLBACK * or NULL
* - Param usage : receive success callback function for I2S
* - Return value explanation :
*/
#define I2S_CMD_SET_RXCB DEV_SET_I2S_SYSCMD(2)
/**
* Set @ref DEV_I2S_CBS::err_cb "I2S transfer error callback" function
* when something error happened for interrupt method
* - Param type : @ref DEV_CALLBACK * or NULL
* - Param usage : transfer error callback function for I2S
* - Return value explanation :
*/
#define I2S_CMD_SET_ERRCB DEV_SET_I2S_SYSCMD(3)
/**
* Enable or disable transmit interrupt
* - Param type : uint32_t
* - Param usage : enable(none-zero) or disable(zero) flag
* - Return value explanation :
*/
#define I2S_CMD_SET_TXINT DEV_SET_I2S_SYSCMD(4)
/**
* Enable or disable receive interrupt
* - Param type : uint32_t
* - Param usage : enable(none-zero) or disable(zero) flag
* - Return value explanation :
*/
#define I2S_CMD_SET_RXINT DEV_SET_I2S_SYSCMD(5)
/**
* Do a software reset for I2S device, it will stop current transfer,
* and clear error state and bring device to normal state, set next condition to STOP
* - Param type : NULL
* - Param usage :
* - Return value explanation :
*/
#define I2S_CMD_RESET DEV_SET_I2S_SYSCMD(6)
/**
* Flush I2S device transmit buffer or fifo
* - Param type : NULL
* - Param usage :
* - Return value explanation :
*/
#define I2S_CMD_FLUSH_TX DEV_SET_I2S_SYSCMD(7)
/**
* Flush I2S device receive buffer or fifo
* - Param type : NULL
* - Param usage :
* - Return value explanation :
*/
#define I2S_CMD_FLUSH_RX DEV_SET_I2S_SYSCMD(8)
/**
* Enable I2S device
* - Param type : Device channel nummber
* - Param usage : Specified device channel number
* - Return value explanation :
*/
#define I2S_CMD_ENA_DEV DEV_SET_I2S_SYSCMD(9)
/**
* Disable I2S device, when device is disabled,
* only @ref I2S_CMD_ENA_DEV, @ref I2S_CMD_DIS_DEV,
* @ref I2S_CMD_GET_STATUS and @ref I2S_CMD_RESET
* commands can be executed, other commands will return @ref E_SYS
* - Param type : Device channel nummber
* - Param usage : Specified device channel number
* - Return value explanation :
*/
#define I2S_CMD_DIS_DEV DEV_SET_I2S_SYSCMD(10)
/**
* Set buffer for interrupt transmit, and it will set @ref DEV_I2S_INFO::tx_buf "tx_buf".
* - I2S transmitter command @n
* If setting TX buffer to NULL, when tx interrupt is enabled and entered into tx interrupt,
* it will automatically disable the tx interrupt, so when you want to transfer something, you need to set the
* tx buffer to Non-NULL and enable tx interrupt, when the tx buffer is sent, it will disable the tx interrupt
* and call tx callback function if available.
* - Param type : DEV_BUFFER * or NULL
* - Param usage : buffer structure pointer, if param is NULL, then it will set tx_buf to NULL
* - Return value explanation :
*/
#define I2S_CMD_SET_TXINT_BUF DEV_SET_I2S_SYSCMD(11)
/**
* Set buffer for interrupt receive, and it will set @ref DEV_I2S_INFO::rx_buf "rx_buf"
* - I2S receiver command @n
* Similiar to @ref I2S_CMD_SET_TXINT_BUF
* - Param type : DEV_BUFFER * or NULL
* - Param usage : buffer structure pointer, if param is NULL, then it will set rx_buf to NULL
* - Return value explanation :
*/
#define I2S_CMD_SET_RXINT_BUF DEV_SET_I2S_SYSCMD(12)
/**
* Set buffer empty threshold in the TX FIFO, these bit program the empty trigger level in the TX FIFO
* - I2S transmitter command @n
* These command is used to set trigger level in the TX FIFO at which empty threshold reached flag/interrupt
* is generated.
* - Param type : uint32_t
* - Param usage : Specified trigger level value (16b) + channel (16b)
* - Return value explanation :
*/
#define I2S_CMD_SET_TXCHET_BUF DEV_SET_I2S_SYSCMD(13)
/**
* Set buffer available data threshold in the TX FIFO, these bit program the trigger level in the RX FIFO
* - I2S receiver command @n
* These command is used to set trigger level in the RX FIFO at which received data available flag/interrupt
* is generated.
* - Param type : uint32_t
* - Param usage : Specified trigger level value (16b) + channel (16b)
* - Return value explanation :
*/
#define I2S_CMD_SET_RXCHDT_BUF DEV_SET_I2S_SYSCMD(14)
/* ++++ Master only commands for I2S Device ++++ */
/**
* Enable or disable clock for master
* - Param type : uint32_t
* - Param usage : enable(none-zero) or disable(zero) flag
* - Return value explanation :
*/
#define I2S_CMD_MST_SET_CLK DEV_SET_I2S_MST_SYSCMD(0)
/**
* Program the number of sclk cycles for word select line stays
* - Param type : uint32_t
* - Param usage : clock cycles
* - Return value explanation :
*/
#define I2S_CMD_MST_SET_WSS DEV_SET_I2S_MST_SYSCMD(1)
/**
* Program the number of gating of sclk cycles for word select line stays
* - Param type : uint32_t
* - Param usage : gating of sclk cycles
* - Return value explanation :
*/
#define I2S_CMD_MST_SET_SCLKG DEV_SET_I2S_MST_SYSCMD(2)
/** @} */
/**
* @defgroup DEVICE_HAL_I2S_CALLBACK I2S Interrupt Callback Functions
* @ingroup DEVICE_HAL_I2S
* @brief Structure definition for I2S device callback
* @{
*/
typedef struct {
DEV_CALLBACK tx_cb; /*!< I2S data transmit success required bytes callback */
DEV_CALLBACK rx_cb; /*!< I2S data receive success required bytes callback */
DEV_CALLBACK err_cb; /*!< I2S error callback */
} DEV_I2S_CBS, *DEV_I2S_CBS_PTR;
/** @} */
/**
* @defgroup DEVICE_HAL_I2S_DEVSTRUCT I2S Device Structure
* @ingroup DEVICE_HAL_I2S
* @brief Definitions for I2S device structure.
* @details This structure will be used in user implemented code, which was called
* Device Driver Implement Layer for I2S to realize in user code.
* @{
*/
/**
* @brief I2S information struct definition
* @details Informations about I2S open state, working state,
* baurate, I2S registers, working method, interrupt number
*/
typedef struct {
void *i2s_ctrl; /*!< I2S control related pointer, implemented by BSP developer, and this should be set during i2s object implementation */
void *i2s_config; /*!< I2S device configuration, implemented by BSP developer, and this shoud be set in object implementation */
uint32_t opn_cnt; /*!< I2S open count, open it will increase 1, close it will decrease 1, 0 for close, >0 for open */
uint32_t status; /*!< current working status, refer to @ref DEVICE_HAL_COMMON_DEVSTATUS, this should be @ref DEV_ENABLED for first open */
uint32_t device; /*!< device type, refer to @ref I2S_DEVICE_TYPE, this should be set for object initialization */
uint32_t mode; /*!< current working mode, which can be @ref DEV_MASTER_MODE "master mode" or @ref DEV_SLAVE_MODE "slave mode" */
uint32_t cur_state; /*!< @ref I2S_WORKING_STATE "current working state for I2S device", this should be @ref I2S_FREE for first open */
uint32_t err_state; /*!< @ref I2S_ERROR_STATE "current error state for I2S device", this should be @ref I2S_ERR_NONE for first open */
DEV_BUFFER tx_buf; /*!< transmit buffer via interrupt, this should be all zero for first open */
DEV_BUFFER rx_buf; /*!< receive buffer via interrupt, this should be all zero for first open */
DEV_I2S_CBS i2s_cbs; /*!< I2S callbacks, for both master and slave mode, this should be all NULL for first open */
void *extra; /*!< a extra pointer to get hook to applications which should not used by BSP developer,
this should be NULL for first open and you can @ref DEV_I2S_INFO_SET_EXTRA_OBJECT "set"
or @ref DEV_I2S_INFO_GET_EXTRA_OBJECT "get" the extra information pointer */
} DEV_I2S_INFO, *DEV_I2S_INFO_PTR;
/** Set extra information pointer of I2S */
#define DEV_I2S_INFO_SET_EXTRA_OBJECT(i2s_info_ptr, extra_info) (i2s_info_ptr)->extra = (void *)(extra_info)
/** Get extra information pointer of I2S */
#define DEV_I2S_INFO_GET_EXTRA_OBJECT(i2s_info_ptr) ((i2s_info_ptr)->extra)
/**
* @brief Definition for I2S device interface
* @details Define I2S device interface, like I2S information structure,
* fuctions to get I2S info, open/close/control I2S, send/receive data by I2S
* @note All this details are implemented by user in user porting code
*/
typedef struct {
DEV_I2S_INFO i2s_info; /*!< I2S device information */
int32_t (*i2s_open)(uint32_t mode, uint32_t param); /*!< open I2S device in master/slave mode, \
when in master mode, param stands for speed mode, \
when in slave mode, param stands for slave address */
int32_t (*i2s_close)(void); /*!< close I2S device */
int32_t (*i2s_control)(uint32_t ctrl_cmd, void *param); /*!< control i2s device */
int32_t (*i2s_write)(const void *data, uint32_t len); /*!< send data by i2s TX device (blocking method) */
int32_t (*i2s_read)(void *data, uint32_t len); /*!< read data from i2s RX device (blocking method) */
} DEV_I2S, *DEV_I2S_PTR;
/**
* @fn int32_t *DEV_I2S::i2s_open(uint32_t mode, uint32_t param)
* @details Open an I2S device with selected mode (master or slave) with defined param
* @param[in] mode Working mode (@ref DEV_MASTER_MODE "master" or @ref DEV_SLAVE_MODE "slave")
* @param[in] param Device type (@ref I2S_DEVICE_TRANSMITTER "transmitter" OR @ref I2S_DEVICE_RECEIVER "receiver")
* @retval E_OK Open successfully without any issues
* @retval E_OPNED Device was opened before
* @retval E_OBJ Device object is not valid
* @retval E_SYS Device initialized parameters are different with parameters in IP
* @retval E_PAR Parameter is not valid
* @retval E_NOSPT Open settings are not supported
*/
/**
* @fn int32_t *DEV_I2S::i2s_close(void)
* @details close an I2S device, just decrease the @ref DEV_I2S_INFO::opn_cnt "opn_cnt",
* if @ref DEV_I2S_INFO::opn_cnt "opn_cnt" equals 0, then close the device
* @retval E_OK Close successfully without any issues(including scenario that device is already closed)
* @retval E_OPNED Device is still opened, the device @ref DEV_I2S_INFO::opn_cnt "opn_cnt" decreased by 1
* @retval E_OBJ Device object is not valid
*/
/**
* @fn int32_t *DEV_I2S::i2s_control(uint32_t ctrl_cmd, void *param)
* @details Control an I2S device by ctrl_cmd, with passed param.
* you can control I2S device using predefined I2S control commands defined using @ref DEV_SET_SYSCMD
* (which must be implemented by bsp developer), @ref DEVICE_HAL_I2S_CTRLCMD "command details".
* And you can also control I2S device using your own specified commands defined using @ref DEV_SET_USRCMD,
* but these specified commands should be defined in your own I2S device driver implementation.
* @param[in] ctrl_cmd @ref DEVICE_HAL_I2S_CTRLCMD "control command", to change or get some thing related to I2S
* @param[in,out] param Parameters that maybe argument of the command,
* or return values of the command, must not be NULL
* @retval E_OK Control device successfully
* @retval E_CLSED Device is not opened
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid for current control command
* @retval E_SYS Control device failed, due to hardware issues, such as device is disabled
* @retval E_CTX Control device failed, due to different reasons like in transfer state
* @retval E_NOSPT Control command is not supported or not valid
*/
/**
* @fn int32_t *DEV_I2S::i2s_write(const void *data, uint32_t len)
* @details Send data through I2S with defined len to RX device.
* @param[in] data Pointer to data need to send by I2S
* @param[in] len Length of data to be sent
* @retval > 0 Byte count that was successfully sent for poll method,
* it might can't send that much due to @ref DEV_I2S_INFO::err_state "different error state".
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid
* @retval E_CTX Device is still in transfer state
* @retval E_SYS Can't write data to hardware due to hardware issues, such as device is disabled
*/
/**
* @fn int32_t *DEV_I2S::i2s_read(void *data, uint32_t len)
* @details Receive data of defined len through I2S from TX device.
* @param[out] data Pointer to data need to received by I2S
* @param[in] len Length of data to be received
* @retval > 0 Byte count that was successfully received for poll method,
* it might can't send that much due to @ref DEV_I2S_INFO::err_state "different error state".
* @retval E_OBJ Device object is not valid or not exists
* @retval E_CTX Device is still in transfer state
* @retval E_PAR Parameter is not valid
* @retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled
*/
/** @} */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get an @ref DEV_I2S "i2s device" by i2s device id.
* For how to use i2s device hal refer to @ref DEVICE_HAL_I2S_DEVSTRUCT "Functions in i2s device structure"
* @param[in] i2s_id ID of i2s, defined by user
* @retval !NULL Pointer to an @ref DEV_I2S "i2s device structure"
* @retval NULL Failed to find the i2s device by i2s_id
* @note Need to implemented by user in user code
*/
extern DEV_I2S_PTR i2s_get_dev(int32_t i2s_id);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* H_DEV_I2S */

View File

@@ -1,515 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @defgroup DEVICE_HAL_IIC IIC Device HAL Interface
* @ingroup DEVICE_HAL_DEF
* @brief Definitions for iic device hardware layer (@ref dev_iic.h)
* @details Provide interfaces for iic driver to implement
*
* @{
*
* @file
* @brief Definitions for iic device hardware layer
* @details Provide common definitions for iic device,
* then software developer can develop iic driver
* following this definitions, and the applications
* can directly call this definition to realize functions
*/
#ifndef H_DEV_IIC
#define H_DEV_IIC
#include "device/dev_common.h"
/**
* @defgroup DEVICE_HAL_IIC_CFG IIC Related Configurations
* @ingroup DEVICE_HAL_IIC
* @brief Macros definitions for for IIC device
* During IIC device during implementation, it is recommended that
* when user set iic speed to a speed maybe not supported in your
* iic device, device driver will set to a supported slower speed.
* @{
*/
/** IIC Bus possible speed modes */
typedef enum {
IIC_SPEED_STANDARD = 0, /*!< Bidirectional, Standard-mode (Sm), with a bit rate up to 100 kbit/s */
IIC_SPEED_FAST = 1, /*!< Bidirectional, Fast-mode (Fm), with a bit rate up to 400 kbit/s */
IIC_SPEED_FASTPLUS = 2, /*!< Bidirectional, Fast-mode Plus (Fm+), with a bit rate up to 1 Mbit/s */
IIC_SPEED_HIGH = 3, /*!< Bidirectional, High-speed mode (Hs-mode), with a bit rate up to 3.4 Mbit/s */
IIC_SPEED_ULTRA = 4 /*!< Unidirectional(Write only), Ultra Fast-mode (UFm), with a bit rate up to 5 Mbit/s */
} IIC_SPEED_MODE;
/** IIC next Condition */
typedef enum iic_next_condtion {
IIC_MODE_STOP = 0, /*!< Send a STOP condition after write/read operation */
IIC_MODE_RESTART = 1 /*!< Send a RESTART condition after write/read operation */
} IIC_NEXT_CONDTION;
/** IIC Error State */
typedef enum {
IIC_ERR_NONE = 0, /*!< Currently in iic device free state */
IIC_ERR_LOST_BUS = 1, /*!< Master or slave lost bus during operation */
IIC_ERR_ADDR_NOACK = 2, /*!< Slave address is sent but not addressed by any slave devices */
IIC_ERR_DATA_NOACK = 3, /*!< Data in transfer is not acked when it should be acked */
IIC_ERR_TIMEOUT = 4, /*!< Transfer timeout, no more data is received or sent */
IIC_ERR_MSTSTOP = 5, /*!< Slave received a STOP condition from master device */
IIC_ERR_UNDEF = 6 /*!< Undefined error cases */
} IIC_ERROR_STATE;
/** IIC Working State */
typedef enum {
IIC_FREE = 0, /*!< Currently in iic device free state */
IIC_IN_TX = 1, /*!< Currently in iic master transmit state */
IIC_IN_RX = 2 /*!< Currently in iic master receive state */
} IIC_WORKING_STATE;
/** IIC Addressing Mode */
typedef enum {
IIC_7BIT_ADDRESS = 0, /*!< Use 7bit address mode */
IIC_10BIT_ADDRESS = 1 /*!< Use 10bit address mode */
} IIC_ADDRESS_MODE;
/** IIC Slave State */
typedef enum {
IIC_SLAVE_STATE_FREE = 0, /*!< None state, in free */
IIC_SLAVE_STATE_START = (1 << 1), /*!< Start or Restart condition, clear it when read */
IIC_SLAVE_STATE_STOP = (1 << 2), /*!< Stop condition, clear it when read */
IIC_SLAVE_STATE_RD_REQ = (1 << 3), /*!< Read request from master, this will trigger the slave transmit callback */
IIC_SLAVE_STATE_RD_DONE = (1 << 4), /*!< Read request done from master, clear it when read */
IIC_SLAVE_STATE_WR_REQ = (1 << 5), /*!< Write request from master, this will trigger the slave receive callback */
IIC_SLAVE_STATE_GC_REQ = (1 << 6), /*!< General call request from master */
IIC_SLAVE_STATE_ERROR = (1 << 7) /*!< Error, clear it when read */
} IIC_SLAVE_STATE;
/** 7bit IIC address mask */
#define IIC_7BIT_ADDRESS_MASK (0x7F)
/** 10bit IIC address mask */
#define IIC_10BIT_ADDRESS_MASK (0x3FF)
/** @} */
/**
* @defgroup DEVICE_HAL_IIC_CTRLCMD IIC Device Control Commands
* @ingroup DEVICE_HAL_IIC
* @brief Definitions for iic control command, used in @ref DEV_IIC::iic_control "IIC IO Control"
* @details These commands defined here can be used in user code directly.
* - Parameters Usage
* - For passing parameters like integer, just use uint32_t/int32_t to directly pass values
* - For passing parameters for a structure, please use pointer to pass values
* - For getting some data, please use pointer to store the return data
* - Common Return Values
* - @ref E_OK, Control device successfully
* - @ref E_CLSED, Device is not opened
* - @ref E_OBJ, Device object is not valid or not exists
* - @ref E_PAR, Parameter is not valid for current control command
* - @ref E_SYS, Control device failed, due to hardware issues such as device is disabled
* - @ref E_CTX, Control device failed, due to different reasons like in transfer state
* - @ref E_NOSPT, Control command is not supported or not valid
* @{
*/
/** Define IIC control commands for common usage */
#define DEV_SET_IIC_SYSCMD(cmd) DEV_SET_SYSCMD((cmd))
/** Define IIC control commands for master usage */
#define DEV_SET_IIC_MST_SYSCMD(cmd) DEV_SET_SYSCMD(0x00004000 | (cmd))
/** Define IIC control commands for slave usage */
#define DEV_SET_IIC_SLV_SYSCMD(cmd) DEV_SET_SYSCMD(0x00008000 | (cmd))
/* ++++ Common commands for IIC Device ++++ */
/**
* Get @ref DEV_IIC_INFO::status "current device status"
* - Param type : uint32_t *
* - Param usage : store result of current status
* - Return value explanation :
*/
#define IIC_CMD_GET_STATUS DEV_SET_IIC_SYSCMD(0)
/**
* Set @ref DEV_IIC_INFO::addr_mode "iic addressing mode".
* - Param type : uint32_t
* - Param usage : iic addressing mode, possible values can be found @ref IIC_ADDRESS_MODE "here"
* - Return value explanation :
*/
#define IIC_CMD_SET_ADDR_MODE DEV_SET_IIC_SYSCMD(1)
/**
* Set @ref DEV_IIC_CBS::tx_cb "iic transmit success callback" function
* when all required bytes are transmitted for interrupt method
* - Param type : @ref DEV_CALLBACK * or NULL
* - Param usage : transmit success callback function for iic
* - Return value explanation :
*/
#define IIC_CMD_SET_TXCB DEV_SET_IIC_SYSCMD(2)
/**
* Set @ref DEV_IIC_CBS::rx_cb "iic receive success callback" function
* when all required bytes are received for interrupt method
* - Param type : @ref DEV_CALLBACK * or NULL
* - Param usage : receive success callback function for iic
* - Return value explanation :
*/
#define IIC_CMD_SET_RXCB DEV_SET_IIC_SYSCMD(3)
/**
* Set @ref DEV_IIC_CBS::err_cb "iic transfer error callback" function
* when something error happened for interrupt method
* - Param type : @ref DEV_CALLBACK * or NULL
* - Param usage : transfer error callback function for iic
* - Return value explanation :
*/
#define IIC_CMD_SET_ERRCB DEV_SET_IIC_SYSCMD(4)
/**
* Set buffer for interrupt transmit, and it will set @ref DEV_IIC_INFO::tx_buf "tx_buf".
* - IIC master mode use case @n
* For master mode, if you set tx buffer to NULL, when tx interrupt is enabled and entered into tx interrupt,
* it will automatically disable the tx interrupt, so when you want to transfer something, you need to set the
* tx buffer to Non-NULL and enable tx interrupt, when the tx buffer is sent, it will disable the tx interrupt
* and call tx callback function if available.
* - IIC slave mode use case @n
* For slave mode, the tx buffer is not used, only tx callback function is used, and if tx callback is not set,
* then it will automatically disable the tx interrupt, if tx callback is set, it will call the tx callback function
* and you need to write or read in the tx callback function, to avoid meaningless waiting, you can use control command
* @ref IIC_CMD_GET_TXAVAIL to get how many bytes space existing in transmit fifo, and use iic_write to send the available
* bytes.
* - Param type : DEV_BUFFER * or NULL
* - Param usage : buffer structure pointer, if param is NULL, then it will set tx_buf to NULL
* - Return value explanation :
*/
#define IIC_CMD_SET_TXINT_BUF DEV_SET_IIC_SYSCMD(5)
/**
* Set buffer for interrupt receive, and it will set @ref DEV_IIC_INFO::rx_buf "rx_buf"
* - IIC master mode use case @n
* Similar to @ref IIC_CMD_SET_TXINT_BUF
* - IIC slave mode use case @n
* Similiar to @ref IIC_CMD_SET_TXINT_BUF
* - Param type : DEV_BUFFER * or NULL
* - Param usage : buffer structure pointer, if param is NULL, then it will set rx_buf to NULL
* - Return value explanation :
*/
#define IIC_CMD_SET_RXINT_BUF DEV_SET_IIC_SYSCMD(6)
/**
* Enable or disable transmit interrupt,
* for master mode, only one of tx and rx interrupt can be enabled,
* if tx interrupt is enabled, then rx interrupt can't be changed.
* - Param type : uint32_t
* - Param usage : enable(none-zero) or disable(zero) flag
* - Return value explanation :
*/
#define IIC_CMD_SET_TXINT DEV_SET_IIC_SYSCMD(7)
/**
* Enable or disable receive interrupt,
* for master mode, only one of tx and rx interrupt can be enabled,
* if rx interrupt is enabled, then tx interrupt can't be changed.
* - Param type : uint32_t
* - Param usage : enable(none-zero) or disable(zero) flag
* - Return value explanation :
*/
#define IIC_CMD_SET_RXINT DEV_SET_IIC_SYSCMD(8)
/**
* Abort current interrupt transmit operation if tx interrupt enabled,
* it will disable transmit interrupt, and set @ref DEV_IN_TX_ABRT
* in @ref DEV_IIC_INFO::status "status" variable,
* and call the transmit callback function, when tx callback is finished,
* it will clear @ref DEV_IN_TX_ABRT and return
* - Param type : NULL
* - Param usage :
* - Return value explanation :
*/
#define IIC_CMD_ABORT_TX DEV_SET_IIC_SYSCMD(9)
/**
* Abort current interrupt receive operation if rx interrupt enabled,
* it will disable receive interrupt, and set @ref DEV_IN_TX_ABRT
* in @ref DEV_IIC_INFO::status "status" variable,
* and call the receive callback function, when rx callback is finished,
* it will clear @ref DEV_IN_TX_ABRT and return
* - Param type : NULL
* - Param usage :
* - Return value explanation :
*/
#define IIC_CMD_ABORT_RX DEV_SET_IIC_SYSCMD(10)
/**
* Do a software reset for IIC device, it will stop current transfer,
* and clear error state and bring device to normal state, set next condition to STOP
* - Param type : NULL
* - Param usage :
* - Return value explanation :
*/
#define IIC_CMD_RESET DEV_SET_IIC_SYSCMD(11)
/**
* Flush iic device transmit buffer or fifo
* - Param type : NULL
* - Param usage :
* - Return value explanation :
*/
#define IIC_CMD_FLUSH_TX DEV_SET_IIC_SYSCMD(12)
/**
* Flush iic device receive buffer or fifo
* - Param type : NULL
* - Param usage :
* - Return value explanation :
*/
#define IIC_CMD_FLUSH_RX DEV_SET_IIC_SYSCMD(13)
/**
* Enable iic device
* - Param type : NULL
* - Param usage : param is not required
* - Return value explanation :
*/
#define IIC_CMD_ENA_DEV DEV_SET_IIC_SYSCMD(14)
/**
* Disable iic device, when device is disabled,
* only @ref IIC_CMD_ENA_DEV, @ref IIC_CMD_DIS_DEV,
* @ref IIC_CMD_GET_STATUS and @ref IIC_CMD_RESET
* commands can be executed, other commands will return @ref E_SYS
* - Param type : NULL
* - Param usage : param is not required
* - Return value explanation :
*/
#define IIC_CMD_DIS_DEV DEV_SET_IIC_SYSCMD(15)
/**
* Get how many bytes space in iic are available to transmit,
* this can be used in interrupt callback functions,
* cooperate with @ref DEV_IIC::iic_write "iic_write" API to realize non-blocked write
* - Param type : int32_t *
* - Param usage : store the write available bytes, > 0 for available bytes, 0 for not available
* - Return value explaination :
*/
#define IIC_CMD_GET_TXAVAIL DEV_SET_IIC_SYSCMD(16)
/**
* Get how many bytes in iic are available to receive,
* this can be used in interrupt callback functions,
* cooperate with @ref DEV_IIC::iic_read "iic_read" API to realize non-blocked read
* - Param type : int32_t *
* - Param usage : store the read available bytes, > 0 for available bytes, 0 for not available
* - Return value explanation :
*/
#define IIC_CMD_GET_RXAVAIL DEV_SET_IIC_SYSCMD(17)
/* ++++ Master only commands for IIC Device ++++ */
/**
* Set @ref DEV_IIC_INFO::speed_mode "iic speed mode".
* - Param type : uint32_t
* - Param usage : iic speed mode, possible values can be found @ref IIC_SPEED_MODE "here",
* and if passing mode is not supported, it will choose a lower supported speed mode
* - Return value explanation :
*/
#define IIC_CMD_MST_SET_SPEED_MODE DEV_SET_IIC_MST_SYSCMD(0)
/**
* Set next condition for following transmit or receive operation.
* For example, you can change next condition before iic_read or iic_write,
* then in iic_read/iic_write operation, it will send a STOP/RESTART condition
* after the last byte of this operation. For interrupt, this is similar.
* - Param type : uint32_t
* - Param usage : next condition can be @ref IIC_NEXT_CONDTION
* - Return value explanation :
*/
#define IIC_CMD_MST_SET_NEXT_COND DEV_SET_IIC_MST_SYSCMD(1)
/**
* Set target slave device address for selecting slave device
* - Param type : uint32_t
* - Param usage : target slave address value
* - Return value explanation :
*/
#define IIC_CMD_MST_SET_TAR_ADDR DEV_SET_IIC_MST_SYSCMD(2)
/* ++++ Slave only commands for IIC Device ++++ */
/**
* Set slave address when working as slave iic device
* - Param type : uint32_t
* - Param usage : slave address value
* - Return value explanation :
*/
#define IIC_CMD_SLV_SET_SLV_ADDR DEV_SET_IIC_SLV_SYSCMD(0)
/**
* Get @ref IIC_SLAVE_STATE "slave state" when working as slave iic device
* - Param type : uint32_t *
* - Param usage : slave state
* - Return value explanation :
*/
#define IIC_CMD_SLV_GET_SLV_STATE DEV_SET_IIC_SLV_SYSCMD(1)
/** @} */
/**
* @defgroup DEVICE_HAL_IIC_CALLBACK IIC Interrupt callback functions
* @ingroup DEVICE_HAL_IIC
* @brief Structure definition for IIC device callback
* @{
*/
typedef struct {
DEV_CALLBACK tx_cb; /*!< iic data transmit success required bytes callback */
DEV_CALLBACK rx_cb; /*!< iic data receive success required bytes callback */
DEV_CALLBACK err_cb; /*!< iic error callback */
} DEV_IIC_CBS, *DEV_IIC_CBS_PTR;
/** @} */
/**
* @defgroup DEVICE_HAL_IIC_DEVSTRUCT IIC Device Structure
* @ingroup DEVICE_HAL_IIC
* @brief Definitions for IIC device structure.
* @details This structure will be used in user implemented code, which was called
* Device Driver Implement Layer for iic to realize in user code.
* @{
*/
/**
* @brief IIC information struct definition
* @details Informations about iic open state, working state,
* baurate, iic registers, working method, interrupt number
*/
typedef struct {
void *iic_ctrl; /*!< iic control related pointer, implemented by bsp developer, and this should be set during iic object implementation */
uint32_t opn_cnt; /*!< iic open count, open it will increase 1, close it will decrease 1, 0 for close, >0 for open */
uint32_t status; /*!< current working status, refer to @ref DEVICE_HAL_COMMON_DEVSTATUS, this should be @ref DEV_ENABLED for first open */
uint32_t mode; /*!< current working mode, which can be @ref DEV_MASTER_MODE "master mode" or @ref DEV_SLAVE_MODE "slave mode" */
uint32_t speed_mode; /*!< current working @ref IIC_SPEED_MODE "iic speed mode" */
uint32_t cur_state; /*!< @ref IIC_WORKING_STATE "current working state for iic device", this should be @ref IIC_FREE for first open */
uint32_t err_state; /*!< @ref IIC_ERROR_STATE "current error state for iic device", this should be @ref IIC_ERR_NONE for first open */
uint32_t addr_mode; /*!< @ref IIC_ADDRESS_MODE "current addressing mode", this should be @ref IIC_7BIT_ADDRESS for first open */
uint32_t slv_addr; /*!< slave address when working as slave iic device, this should be 0 for first open */
uint32_t tar_addr; /*!< target slave device address when addressing that slave device, this should be 0 for first open */
uint32_t next_cond; /*!< @ref IIC_NEXT_CONDTION "next condition for master transmit or receive", \
possible values are STOP or RESTART, it should be STOP for first open */
DEV_BUFFER tx_buf; /*!< transmit buffer via interrupt, this should be all zero for first open */
DEV_BUFFER rx_buf; /*!< receive buffer via interrupt, this should be all zero for first open */
DEV_IIC_CBS iic_cbs; /*!< iic callbacks, for both master and slave mode, this should be all NULL for first open */
void *extra; /*!< a extra pointer to get hook to applications which should not used by bsp developer,
this should be NULL for first open and you can @ref DEV_IIC_INFO_SET_EXTRA_OBJECT "set"
or @ref DEV_IIC_INFO_GET_EXTRA_OBJECT "get" the extra information pointer */
} DEV_IIC_INFO, *DEV_IIC_INFO_PTR;
/** Set extra information pointer of iic info */
#define DEV_IIC_INFO_SET_EXTRA_OBJECT(iic_info_ptr, extra_info) (iic_info_ptr)->extra = (void *)(extra_info)
/** Get extra information pointer of iic info */
#define DEV_IIC_INFO_GET_EXTRA_OBJECT(iic_info_ptr) ((iic_info_ptr)->extra)
/**
* @brief Definition for IIC device interface
* @details Define iic device interface, like iic information structure,
* fuctions to get iic info, open/close/control iic, send/receive data by iic
* @note All this details are implemented by user in user porting code
*/
typedef struct {
DEV_IIC_INFO iic_info; /*!< iic device information */
int32_t (*iic_open)(uint32_t mode, uint32_t param); /*!< open iic device in master/slave mode, \
when in master mode, param stands for speed mode, \
when in slave mode, param stands for slave address */
int32_t (*iic_close)(void); /*!< close iic device */
int32_t (*iic_control)(uint32_t ctrl_cmd, void *param); /*!< control iic device */
int32_t (*iic_write)(const void *data, uint32_t len); /*!< send data by iic device (blocking method) */
int32_t (*iic_read)(void *data, uint32_t len); /*!< read data from iic device (blocking method) */
} DEV_IIC, *DEV_IIC_PTR;
/**
* @fn int32_t *DEV_IIC::iic_open(uint32_t mode, uint32_t param)
* @details Open an iic device with selected mode (master or slave) with defined param
* @param[in] mode Working mode (@ref DEV_MASTER_MODE "master" or @ref DEV_SLAVE_MODE "slave")
* @param[in] param When mode is @ref DEV_MASTER_MODE, param stands for @ref DEV_IIC_INFO::speed_mode "speed mode",
* when mode is @ref DEV_SLAVE_MODE, param stands for @ref DEV_IIC_INFO::slv_addr "slave device 7bit address"
* @retval E_OK Open successfully without any issues
* @retval E_OPNED If device was opened before with different parameters,
* then just increase the @ref DEV_IIC_INFO::opn_cnt "opn_cnt" and return @ref E_OPNED
* @retval E_OBJ Device object is not valid
* @retval E_SYS Device is opened for different mode before, if you want to open it with different mode, you need to fully close it first.
* @retval E_PAR Parameter is not valid
* @retval E_NOSPT Open settings are not supported
*/
/**
* @fn int32_t *DEV_IIC::iic_close(void)
* @details Close an iic device, just decrease the @ref DEV_IIC_INFO::opn_cnt "opn_cnt",
* if @ref DEV_IIC_INFO::opn_cnt "opn_cnt" equals 0, then close the device
* @retval E_OK Close successfully without any issues(including scenario that device is already closed)
* @retval E_OPNED Device is still opened, the device @ref DEV_IIC_INFO::opn_cnt "opn_cnt" decreased by 1
* @retval E_OBJ Device object is not valid
*/
/**
* @fn int32_t *DEV_IIC::iic_control(uint32_t ctrl_cmd, void *param)
* @details Control an iic device by ctrl_cmd, with passed param.
* you can control iic device using predefined iic control commands defined using @ref DEV_SET_SYSCMD
* (which must be implemented by bsp developer), such as @ref IIC_CMD_MST_SET_SPEED_MODE "set iic speed mode",
* @ref IIC_CMD_FLUSH_TX "flush tx" and @ref DEVICE_HAL_IIC_CTRLCMD "more".
* And you can also control iic device using your own specified commands defined using @ref DEV_SET_USRCMD,
* but these specified commands should be defined in your own iic device driver implementation.
* @param[in] ctrl_cmd @ref DEVICE_HAL_IIC_CTRLCMD "control command", to change or get some thing related to iic
* @param[in,out] param Parameters that maybe argument of the command,
* or return values of the command, must not be NULL
* @retval E_OK Control device successfully
* @retval E_CLSED Device is not opened
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid for current control command
* @retval E_SYS Control device failed, due to hardware issues, such as device is disabled
* @retval E_CTX Control device failed, due to different reasons like in transfer state
* @retval E_NOSPT Control command is not supported or not valid
*/
/**
* @fn int32_t *DEV_IIC::iic_write(const void *data, uint32_t len)
* @details Send data through iic with defined len to slave device which slave address is slv_addr.
* @param[in] data Pointer to data need to send by iic
* @param[in] len Length of data to be sent
* @retval >0 Byte count that was successfully sent for poll method,
* it might can't send that much due to @ref DEV_IIC_INFO::err_state "different error state".
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid
* @retval E_CTX Device is still in transfer state
* @retval E_SYS Can't write data to hardware due to hardware issues, such as device is disabled
*/
/**
* @fn int32_t *DEV_IIC::iic_read(void *data, uint32_t len)
* @details Receive data of defined len through iic from slave device which slave address is slv_addr.
* @param[out] data Pointer to data need to received by iic
* @param[in] len Length of data to be received
* @retval >0 Byte count that was successfully received for poll method,
* it might can't send that much due to @ref DEV_IIC_INFO::err_state "different error state".
* @retval E_OBJ Device object is not valid or not exists
* @retval E_CTX Device is still in transfer state
* @retval E_PAR Parameter is not valid
* @retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled
*/
/** @} */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get an @ref DEV_IIC "iic device" by iic device id.
* For how to use iic device hal refer to @ref DEVICE_HAL_IIC_DEVSTRUCT "Functions in iic device structure"
* @param[in] iic_id ID of iic, defined by user
* @retval !NULL Pointer to an @ref DEV_IIC "iic device structure"
* @retval NULL Failed to find the iic device by iic_id
* @note Need to implemented by user in user code
*/
extern DEV_IIC_PTR iic_get_dev(int32_t iic_id);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* H_DEV_IIC */

View File

@@ -1,235 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
/**
* @defgroup DEVICE_HAL_PWM_TIMER PWM_TIMER Device HAL Interface
* @ingroup DEVICE_HAL_DEF
* @brief Definitions for pwm_timer device hardware layer (@ref dev_pwm_timer.h)
* @details Provide unified APIs for pwm_timer driver to implement.
*
* @{
*
* @file
* @brief Definitions for pwm_timer device hardware layer
* @details Provide common definitions for pwm_timer device,
* then software developer can develop pwm_timer driver
* following this definitions, and the applications
* can directly call this definition to realize functions
*
*/
#ifndef H_DEV_PWM_TIMER
#define H_DEV_PWM_TIMER
#include "device/dev_common.h"
/**
* @defgroup DEVICE_HAL_PWM_TIMER_CTRLCMD PWM_TIMER Device Control Commands
* @ingroup DEVICE_HAL_PWM_TIMER
* @brief Definitions for pwm_timer control command, used in @ref DEV_PWM_TIMER::pwm_timer_control "PWM_TIMER IO Control"
* @details These commands defined here can be used in user code directly.
* - Parameters Usage
* - For passing parameters like integer, just use uint32_t/int32_t to directly pass values
* - For passing parameters for a structure, please use pointer to pass values
* - For getting some data, please use pointer to store the return data
* - Common Return Values
* - @ref E_OK, Control device successfully
* - @ref E_CLSED, Device is not opened
* - @ref E_OBJ, Device object is not valid or not exists
* - @ref E_PAR, Parameter is not valid for current control command
* - @ref E_SYS, Control device failed, due to hardware issues such as device is disabled
* - @ref E_CTX, Control device failed, due to different reasons like in transfer state
* - @ref E_NOSPT, Control command is not supported or not valid
* @{
*/
#define PWM_TIMER_CMD_SET_CFG DEV_SET_SYSCMD(0)
#define PWM_TIMER_CMD_GET_CFG DEV_SET_SYSCMD(1)
#define PWM_TIMER_CMD_ENA_CH DEV_SET_SYSCMD(2)
#define PWM_TIMER_CMD_DIS_CH DEV_SET_SYSCMD(3)
#define PWM_TIMER_CMD_SET_ISR DEV_SET_SYSCMD(4)
#define PWM_TIMER_CMD_GET_ISR DEV_SET_SYSCMD(5)
#define PWM_TIMER_CMD_DIS_ISR DEV_SET_SYSCMD(6)
#define PWM_TIMER_CMD_ENA_ISR DEV_SET_SYSCMD(7)
/** @} */
/** PWM_TIMER interrupt handler or Interrupt Service Routine(ISR) */
typedef void (*DEV_PWM_TIMER_HANDLER) (void *ptr);
/** interrupt handler for each pwm_timer channel */
typedef struct {
uint32_t int_ch_num; /*!< pwm_timer channel num*/
DEV_PWM_TIMER_HANDLER int_ch_handler; /*!< interrupt handler */
} DEV_PWM_TIMER_CH_ISR, *DEV_PWM_TIMER_CH_ISR_PTR;
/**
* PWM_TIMER Device Work Mode Types Enum
*/
typedef enum {
DEV_PWM_TIMER_MODE_CLOSE = 0, /*!< mode close */
DEV_PWM_TIMER_MODE_TIMER = 1, /*!< mode timer */
DEV_PWM_TIMER_MODE_PWM = 2 /*!< mode pwm */
} DEV_PWM_TIMER_MODE, *DEV_PWM_TIMER_MODE_PTR;
/**
* PWM_TIMER Device Config Struct
*/
typedef struct {
DEV_PWM_TIMER_MODE mode; /*!< work mode*/
uint16_t count_low; /*!< count for timer or pwm period low*/
uint16_t count_high; /*!< count for pwm period high*/
DEV_PWM_TIMER_HANDLER isr_hander; /*!< channel ch isr hander*/
} DEV_PWM_TIMER_CFG, *DEV_PWM_TIMER_CFG_PTR;
/**
* @defgroup DEVICE_HAL_PWM_TIMER_DEVSTRUCT PWM_TIMER Device Interface Definition
* @ingroup DEVICE_HAL_PWM_TIMER
* @brief Structure definition for pwm_timer device
* @details This structure will be used in user implemented code, which was called
* @ref DEVICE_IMPL "Device Driver Implement Layer" for pwm_timer to use in implementation code.
* Application developer should use the PWM_TIMER API provided here to access to PWM_TIMER devices.
* BSP developer should follow the API definition to implement PWM_TIMER device drivers.
* @{
*/
/**
* @brief PWM_TIMER information struct definition
* @details Informations about pwm_timer open count, working status,
* pwm_timer registers and ctrl structure
*/
typedef struct {
void *pwm_timer_ctrl;
uint32_t opn_cnt;
// uint32_t status;
// uint32_t mode;
} DEV_PWM_TIMER_INFO, *DEV_PWM_TIMER_INFO_PTR;
/**
* @brief PWM_TIMER device interface definition
* @details Define pwm_timer device interface, like pwm_timer information structure,
* provide functions to open/close/control pwm_timer, send/receive data by pwm_timer
* @note All this details are implemented by user in user porting code
*/
typedef struct {
DEV_PWM_TIMER_INFO pwm_timer_info; /*!< PWM_TIMER device information */
int32_t (*pwm_timer_open)(void); /*!< Open pwm_timer device */
int32_t (*pwm_timer_close)(void); /*!< Close pwm_timer device */
int32_t (*pwm_timer_control)(uint32_t ch, uint32_t cmd, void *param2); /*!< Control pwm_timer device */
int32_t (*pwm_timer_write)(uint32_t ch, uint32_t mode, uint32_t freq, uint32_t dc); /*!< Set the configuration of pwm_timer*/
int32_t (*pwm_timer_read)(uint32_t ch, uint32_t *mode, uint32_t *freq, uint32_t *dc); /*!< Read the configuration of pwm_timer*/
} DEV_PWM_TIMER, *DEV_PWM_TIMER_PTR;
/**
* @fn int32_t *DEV_PWM_TIMER::pwm_timer_open(void)
* @details Open pwm_timer device
* @retval E_OK Open successfully without any issues
* @retval E_OPNED If device was opened before with different parameters,
* then just increase the @ref DEV_PWM_TIMER_INFO::opn_cnt "opn_cnt" and return @ref E_OPNED
* @retval E_OBJ Device object is not valid
* @retval E_PAR Parameter is not valid
* @retval E_NOSPT Open settings are not supported
*/
/**
* @fn int32_t *DEV_PWM_TIMER::pwm_timer_close(void)
* @details Close an pwm_timer device, just decrease the @ref DEV_PWM_TIMER_INFO::opn_cnt "opn_cnt",
* if @ref DEV_PWM_TIMER_INFO::opn_cnt "opn_cnt" equals 0, then close the device
* @retval E_OK Close successfully without any issues(including scenario that device is already closed)
* @retval E_OPNED Device is still opened, the device @ref DEV_PWM_TIMER_INFO::opn_cnt "opn_cnt" decreased by 1
* @retval E_OBJ Device object is not valid
*/
/**
* @fn int32_t *DEV_PWM_TIMER::pwm_timer_control(uint32_t ch, uint32_t cmd, void *param2)
* @details Control a pwm_timer device [channel number: ch] by ctrl_cmd, with passed param.
* @param[in] ch Channel number of pwm_timer to control, must >= 0
* @param[in] ctrl_cmd Control command, to change or get some thing related to pwm_timer
* @param[in,out] param Parameters that maybe argument of the command, or return values of the command
* @retval E_OK Control device successfully
* @retval E_CLSED Device is not opened
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid for current control command
* @retval E_SYS Control device failed, due to hardware issues, such as device is disabled
* @retval E_CTX Control device failed, due to different reasons like in transfer state
* @retval E_NOSPT Control command is not supported or not valid
*/
/**
* @fn int32_t *DEV_PWM_TIMER::pwm_timer_write(uint32_t ch, uint32_t mode, uint32_t freq, uint32_t dc)
* @details Set the configuration of pwm_timer.
* @param[in] ch Channel number of pwm_timer to write, must >= 0
* @param[in] mode Set the mode of pwm_timer, must not be NULL
* @param[in] freq Set the frequency of pwm_timer, must not be NULL
* @param[in] dc Set the duty cycle of pwm_timer, must not be NULL
* @retval E_OK Set device successfully
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid
* @retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled
*/
/**
* @fn int32_t *DEV_PWM_TIMER::pwm_timer_read(uint32_t ch, uint32_t *mode, uint32_t *freq, uint32_t *dc)
* @details Read the configuration of pwm_timer.
* @param[in] ch Channel number of pwm_timer to read, must >= 0
* @param[out] mode Pointer to data mode of pwm_timer, must not be NULL
* @param[out] freq Pointer to data frequency of pwm_timer, must not be NULL
* @param[out] dc Pointer to data duty cycle of pwm_timer, must not be NULL
* @retval E_OK Read device successfully
* @retval E_OBJ Device object is not valid or not exists
* @retval E_PAR Parameter is not valid
* @retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled
*/
/** @} */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get an @ref DEV_PWM_TIMER "pwm_timer device" by pwm_timer device id.
* For how to use pwm_timer device hal refer to @ref DEV_PWM_TIMER "Functions in pwm_timer device structure"
* @param[in] pwm_timer_id ID of pwm_timer, defined by user
* @retval !NULL Pointer to an @ref DEV_PWM_TIMER "pwm_timer device structure"
* @retval NULL Failed to find the pwm_timer device by pwm_timer_id
* @note Need to implemented by user in user code
*/
extern DEV_PWM_TIMER_PTR pwm_timer_get_dev(int32_t pwm_timer_id);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* H_DEV_PWM_TIMER */

Some files were not shown because too many files have changed in this diff Show More