blob: 6e8b6b7f6f7f44f1b5062c542b09dae4f23bc190 [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2016-2017 Cadence Design Systems, Inc.
* All rights reserved worldwide.
*
* 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 copyright holder 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 SOFTWARE IS PROVIDED "AS IS",
* WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Copyright 2017 NXP
*
******************************************************************************
*
* util.h
*
******************************************************************************
*/
#ifndef UTIL_H_
#define UTIL_H_
#include "API_General.h"
#ifndef __UBOOT__
#include <stdarg.h>
#include <stdint.h>
#else
#include <common.h>
#endif
/**
* \addtogroup UTILS
* \{
*/
#define INTERNAL_CMD_HEAD_SIZE 4
/**
* \brief expands to blocking function body
* \param x - function call
*/
#define internal_block_function(x) \
do { \
CDN_API_STATUS ret; \
do { \
ret = x; \
} while (ret == CDN_BSY || ret == CDN_STARTED); \
return ret; \
} while (0)
/**
* \brief write message and write response (if any), non-blocking way. Also sets state.running = 0
*/
#define INTERNAL_PROCESS_MESSAGES \
do { \
if (state.txenable && !internal_mbox_tx_process().txend) \
return CDN_BSY; \
if (state.rxenable && !internal_mbox_rx_process().rxend) \
return CDN_BSY; \
state.running = 0; \
} while (0)
#define internal_opcode_ok_or_return(module, opcode) \
do { \
CDN_API_STATUS ret = internal_test_rx_head(module, opcode); \
if (ret != CDN_OK) \
return ret; \
} while (0)
#define internal_opcode_match_or_return() \
do { \
CDN_API_STATUS ret = internal_test_rx_head_match(); \
if (ret != CDN_OK) \
return ret; \
} while (0)
/* macro for simple tx only command, command format as in mkfullmsg
(with count) */
#define internal_macro_command_tx(module, opcode, bustype, command...) \
do { \
if (!state.running) { \
internal_tx_mkfullmsg(module, opcode, command); \
state.bus_type = bustype; \
return CDN_STARTED; \
} \
INTERNAL_PROCESS_MESSAGES; \
} while (0)
/* macro for command with response with matching opcode, command format as in
mkfullmsg (with count) */
#define internal_macro_command_txrx(module, opcode, bustype, command...) \
do { \
if (!state.running) { \
internal_tx_mkfullmsg(module, opcode, command); \
state.bus_type = bustype; \
state.rxenable = 1; \
return CDN_STARTED; \
} \
INTERNAL_PROCESS_MESSAGES; \
internal_opcode_match_or_return(); \
} while (0)
typedef struct {
/** apb write status */
enum tx_status_enum {
/** one or more bytes written */
CDN_TX_WRITE = 0,
/** nothing to write */
CDN_TX_NOTHING = 1,
/** mailbox full, 0 bytes written */
CDN_TX_FULL = 2,
/** APB error while writing */
CDN_TX_APB_ERROR = 3
} tx_status:3;
/** apb read status */
enum rx_status_enum {
/** 1 or more bytes read */
CDN_RX_READ = 0,
/** mailbox empty, 0 bytes read */
CDN_RX_EMPTY = 1,
/** apb error while reading */
CDN_RX_APB_ERROR = 2
} rx_status:2;
/** indicates end of currenly recived message */
unsigned char rxend:1;
/** end of tx message reached */
unsigned char txend:1;
} INTERNAL_MBOX_STATUS;
/**
* \brief put val into dest in big endian format
* \param val - value to put
* \param dest - place to put value
* \param bytes - true size of val in bytes. for example if
* bytes = 2 val is treated as short int
*/
void internal_itobe(int val, volatile unsigned char *dest, int bytes);
/**
* \brief read big endian value from src and return it
* \param src - source to read from
* \param bytes - size of read value
* \return result
*/
uint32_t internal_betoi(volatile uint8_t const *src, uint8_t bytes);
/**
* \brief create message from size and value pairs; also sets
* state.running and state.txEnable
* \param dest - pointer to write message to
* \param valNo - number of values to write
* \param ... - pairs of size and value, each value is written
* after another. if size is positive value, value is
* written with #internal_itobe, if size is negative,
* value is treated as src pointer for memcpy
*
* example:
*
* unsigned short x = 0xAABB;
*
* internal_mkmsg(dest, 3, 1, 1, 2, 3, -2, &x);
*
* will write 01 00 03 AA BB to dest
*/
unsigned int internal_mkmsg(volatile unsigned char *dest, int valno, ...);
unsigned int internal_vmkmsg(volatile unsigned char *dest, int valno,
va_list vl);
/**
* \brief setup message header in txBuffer, set txEnable = 1
*/
void internal_mbox_tx_enable(unsigned char module, unsigned char opcode,
unsigned short length);
/**
* \brief write from txBuffer to mailbox untill full or end of message.
*
* when txEnable == 0 writes nothing
* when write reaches end of message set txEnable = 0
*/
/**
* \brief combination of #internal_mkmsg and #internal_mbox_tx_enable
*
* #internal_mkmsg dest and #internal_mbox_tx_enable length are determined
* automaticly this function also sets state.txEnable = 1 and
* state.running
*/
void internal_tx_mkfullmsg(unsigned char module, unsigned char opcode,
int valno, ...);
void internal_vtx_mkfullmsg(unsigned char module, unsigned char opcode,
int valno, va_list vl);
/**
* \brief read from state.txBuffer and store results in specified pointers
* \param valNo - numbero of values to read
* \param ... - pairs of size and ptr
*
* this function is similar to #internal_mkmsg -
*
* when size is positive read value using #internal_betoi
* when size is negative mempcy from txBuffer to ptr -size bytes
* when size is 0 write to ptr addres of current position in rxbuffer
* when ptr is NULL ignore size bytes (if size is negative this
* will rewind buffer)
*/
void internal_readmsg(int valno, ...);
void internal_vreadmsg(int valno, va_list vl);
INTERNAL_MBOX_STATUS internal_mbox_tx_process(void);
/**
* \brief read to rxBuffer from mailbox untill empty or end of message
*
* when rxEnable == 0 reads nothing
* when end of message reached sets rxEnable = 0
*/
INTERNAL_MBOX_STATUS internal_mbox_rx_process(void);
/**
* \brief check if apb is available
* \return !(rxEnable && txEable)
*/
unsigned int internal_apb_available(void);
/**
* \brief test if parameters match module and opcode in rxBuffer
* \return CDN_OK or CDN_BAD_OPCODE or CDN_BAD_MODULE
*/
CDN_API_STATUS internal_test_rx_head(unsigned char module,
unsigned char opcode);
CDN_API_STATUS internal_test_rx_head_match(void);
/**
* \brief print current fw and lib version
*/
void print_fw_ver(void);
typedef struct {
unsigned char txbuffer[1024];
unsigned char rxbuffer[1024];
unsigned int txi; /* iterators */
unsigned int rxi;
unsigned char txenable; /*data readt to send*/
unsigned char rxenable;
unsigned char running;
CDN_BUS_TYPE bus_type;
unsigned int tmp;
} state_struct;
extern state_struct state;
extern int cdn_bus_read(unsigned int addr, unsigned int* value);
extern int cdn_bus_write(unsigned int addr, unsigned int value);
unsigned short internal_get_msg_len(void);
#endif