blob: 150537f32c825d79b3631b5dde0fc59e0f8fa0e7 [file] [log] [blame]
/* ------------------------------------------
* 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.
*
* \version 2017.03
* \date 2016-07-18
* \author Qiang Gu(Qiang.Gu@synopsys.com)
--------------------------------------------- */
/**
* \defgroup BOARD_EMSK_DRV_PMODRF EMSK PMOD RF Driver
* \ingroup BOARD_EMSK_DRIVER
* \brief EMSK Pmod RF Driver
* \details
* Realize the EMSK board PMOD RF driver
*/
/**
* \file
* \ingroup BOARD_EMSK_DRV_PMODRF
* \brief Pmod RF driver for emsk board
*/
/**
* \addtogroup BOARD_EMSK_DRV_PMODRF
* @{
*/
#include <stddef.h>
#include <string.h>
#include "inc/arc/arc.h"
#include "inc/arc/arc_builtin.h"
#include "inc/embARC_toolchain.h"
#include "inc/embARC_error.h"
#include "inc/arc/arc_exception.h"
#include "board/board.h"
#include "device/device_hal/inc/dev_gpio.h"
#include "device/device_hal/inc/dev_spi.h"
#include "board/emsk/pmrf/pmrf.h"
#define EMSK_PMRF_0_SPI_CPULOCK_ENABLE
static DEV_SPI_PTR pmrf_spi_ptr;
static DEV_GPIO_PTR pmrf_gpio_ptr;
static uint32_t cs_line = EMSK_PMRF_0_SPI_LINE;
void pmrf_wake_pin(uint32_t flag)
{
if (flag == 1)
{
pmrf_gpio_ptr->gpio_write(MRF24J40_WAKE_ON, MRF24J40_WAKE_PIN);
}
else
{
pmrf_gpio_ptr->gpio_write(MRF24J40_WAKE_OFF, MRF24J40_WAKE_PIN);
}
}
void pmrf_cs_pin(uint32_t flag)
{
uint32_t cpu_status;
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
if (flag == 1)
{
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
}
else
{
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
}
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
}
void pmrf_reset_pin(uint32_t flag)
{
if (flag == 1)
{
pmrf_gpio_ptr->gpio_write(MRF24J40_RST_HIGH, MRF24J40_RST_PIN);
}
else
{
pmrf_gpio_ptr->gpio_write(MRF24J40_RST_LOW, MRF24J40_RST_PIN);
}
}
uint8_t pmrf_read_long_ctrl_reg(uint16_t addr)
{
uint8_t msg[2];
uint8_t ret_val;
DEV_SPI_TRANSFER pmrf_xfer;
uint32_t cpu_status;
msg[0] = (uint8_t)(((addr >> 3) & 0x7F) | 0x80);
msg[1] = (uint8_t)((addr << 5) & 0xE0);
DEV_SPI_XFER_SET_TXBUF(&pmrf_xfer, msg, 0, 2);
DEV_SPI_XFER_SET_RXBUF(&pmrf_xfer, &ret_val, 2, 1);
DEV_SPI_XFER_SET_NEXT(&pmrf_xfer, NULL);
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
pmrf_spi_ptr->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&pmrf_xfer));
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
return ret_val;
}
uint8_t pmrf_read_short_ctrl_reg(uint8_t addr)
{
uint8_t msg;
uint8_t ret_val;
DEV_SPI_TRANSFER pmrf_xfer;
uint32_t cpu_status;
msg = (((addr << 1) & 0x7E) | 0);
DEV_SPI_XFER_SET_TXBUF(&pmrf_xfer, &msg, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&pmrf_xfer, &ret_val, 1, 1);
DEV_SPI_XFER_SET_NEXT(&pmrf_xfer, NULL);
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
pmrf_spi_ptr->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&pmrf_xfer));
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
return ret_val;
}
void pmrf_write_long_ctrl_reg(uint16_t addr, uint8_t value)
{
uint8_t msg[4];
DEV_SPI_TRANSFER pmrf_xfer;
uint32_t cpu_status;
msg[0] = (uint8_t)(((addr >> 3) & 0x7F) | 0x80);
msg[1] = (uint8_t)(((addr << 5) & 0xE0) | (1 << 4));
msg[2] = value;
msg[3] = 0x0; /* have to write 1 more byte, why ?*/
DEV_SPI_XFER_SET_TXBUF(&pmrf_xfer, msg, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&pmrf_xfer, NULL, 4, 0);
DEV_SPI_XFER_SET_NEXT(&pmrf_xfer, NULL);
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
pmrf_spi_ptr->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&pmrf_xfer));
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
}
void pmrf_write_short_ctrl_reg(uint8_t addr, uint8_t value)
{
DEV_SPI_TRANSFER pmrf_xfer;
uint8_t msg[3];
uint32_t cpu_status;
msg[0] = (((addr << 1) & 0x7E) | 1);
msg[1] = value;
msg[2] = 0x0; /* have to write 1 more byte, why ?*/
DEV_SPI_XFER_SET_TXBUF(&pmrf_xfer, msg, 0, 3);
DEV_SPI_XFER_SET_RXBUF(&pmrf_xfer, NULL, 3, 0);
DEV_SPI_XFER_SET_NEXT(&pmrf_xfer, NULL);
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
pmrf_spi_ptr->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&pmrf_xfer));
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
}
void pmrf_delay_us(uint32_t us)
{
uint64_t start_us, us_delayed;
us_delayed = (uint64_t)us;
start_us = board_get_cur_us();
while ((board_get_cur_us() - start_us) < us_delayed);
}
void pmrf_delay_ms(uint32_t ms)
{
board_delay_ms(ms, OSP_DELAY_OS_COMPAT_DISABLE);
}
/* need test */
void pmrf_set_key(uint16_t addr, uint8_t *key)
{
uint8_t msg[16 + 2];
DEV_SPI_TRANSFER pmrf_xfer;
uint32_t cpu_status;
uint8_t i;
msg[0] = (uint8_t)(((addr >> 3) & 0x7F) | 0x80);
msg[1] = (uint8_t)(((addr << 5) & 0xE0) | (1 << 4));
for (i = 0; i < 16; i++)
{
msg[i + 2] = key[0];
}
DEV_SPI_XFER_SET_TXBUF(&pmrf_xfer, msg, 0, 18);
DEV_SPI_XFER_SET_RXBUF(&pmrf_xfer, NULL, 18, 0);
DEV_SPI_XFER_SET_NEXT(&pmrf_xfer, NULL);
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
pmrf_spi_ptr->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&pmrf_xfer));
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
}
/* need test */
void pmrf_txpkt_frame_write(uint8_t *frame, int16_t hdr_len, int16_t frame_len)
{
uint8_t msg[frame_len + 2 + 2];
DEV_SPI_TRANSFER pmrf_xfer;
uint32_t cpu_status;
uint8_t i = 0;
msg[0] = (uint8_t)(((MRF24J40_TXNFIFO >> 3) & 0x7F) | 0x80);
msg[1] = (uint8_t)(((MRF24J40_TXNFIFO << 5) & 0xE0) | (1 << 4));
msg[2] = (uint8_t)hdr_len;
msg[3] = (uint8_t)frame_len;
for (i = 0; i < frame_len; i++)
{
msg[i + 4] = *frame;
frame++;
}
DEV_SPI_XFER_SET_TXBUF(&pmrf_xfer, msg, 0, frame_len + 2 + 2);
DEV_SPI_XFER_SET_RXBUF(&pmrf_xfer, NULL, frame_len + 2 + 2, 0);
DEV_SPI_XFER_SET_NEXT(&pmrf_xfer, NULL);
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
pmrf_spi_ptr->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&pmrf_xfer));
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
}
/* need test */
void pmrf_rxpkt_intcb_frame_read(uint8_t *buf, uint8_t length)
{
uint8_t msg[length];
DEV_SPI_TRANSFER pmrf_xfer;
uint32_t cpu_status;
msg[0] = (uint8_t)((((MRF24J40_RXFIFO + 1) >> 3) & 0x7F) | 0x80);
msg[1] = (uint8_t)(((MRF24J40_RXFIFO + 1) << 5) & 0xE0);
DEV_SPI_XFER_SET_TXBUF(&pmrf_xfer, msg, 0, 2);
DEV_SPI_XFER_SET_RXBUF(&pmrf_xfer, buf, 2, length);
DEV_SPI_XFER_SET_NEXT(&pmrf_xfer, NULL);
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
pmrf_spi_ptr->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&pmrf_xfer));
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
}
void pmrf_all_install(void)
{
pmrf_spi_ptr = spi_get_dev(EMSK_PMRF_0_SPI_ID);
pmrf_gpio_ptr = gpio_get_dev(EMSK_PMRF_0_GPIO_ID);
}
void pmrf_txfifo_write(uint16_t address, uint8_t *data, uint8_t hdr_len, uint8_t len)
{
uint8_t msg[len + 4];
DEV_SPI_TRANSFER pmrf_xfer;
uint32_t cpu_status;
uint8_t i = 0;
msg[0] = (uint8_t)(((address >> 3) & 0x7F) | 0x80);
msg[1] = (uint8_t)(((address << 5) & 0xE0) | (1 << 4));
msg[2] = hdr_len;
msg[3] = len;
for (i = 0; i < len; i++)
{
msg[i + 4] = *(data + i);
}
DEV_SPI_XFER_SET_TXBUF(&pmrf_xfer, msg, 0, len + 4);
DEV_SPI_XFER_SET_RXBUF(&pmrf_xfer, NULL, len + 4, 0);
DEV_SPI_XFER_SET_NEXT(&pmrf_xfer, NULL);
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_status = cpu_lock_save();
#endif
pmrf_spi_ptr->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(cs_line));
pmrf_spi_ptr->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&pmrf_xfer));
pmrf_spi_ptr->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(cs_line));
#ifdef EMSK_PMRF_0_SPI_CPULOCK_ENABLE
cpu_unlock_restore(cpu_status);
#endif
}
/** @} end of group BOARD_EMSK_DRV_PMODRF */