drivers/ieee802154: Switch CC2520 to new SPI API

Finally switching to new SPI API. It makes code simpler and performs
better.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2017-09-29 09:33:25 +02:00 committed by Carles Cufí
parent f44ba8e7d4
commit d4065ae73e
4 changed files with 275 additions and 329 deletions

View file

@ -23,40 +23,39 @@ if IEEE802154_CC2520
config SPI
def_bool y
config SPI_QMSI
def_bool n
config SPI_DW
def_bool y
config GPIO
def_bool y
config IEEE802154_CC2520_SPI_DRV_NAME
default SPI_1_NAME
config IEEE802154_CC2520_SPI_FREQ
default 4
default 8000000
config IEEE802154_CC2520_SPI_SLAVE
default 1
if GPIO_QMSI
config IEEE802154_CC2520_GPIO_0_NAME
default GPIO_QMSI_0_NAME
config IEEE802154_CC2520_GPIO_1_NAME
default GPIO_QMSI_1_NAME
endif # GPIO_QMSI
if SPI_QMSI
config SPI_CS_GPIO
config IEEE802154_CC2520_GPIO_SPI_CS
def_bool y
config SPI_1_CS_GPIO_PORT
config IEEE802154_CC2520_GPIO_SPI_CS_DRV_NAME
default GPIO_QMSI_0_NAME
config SPI_1_CS_GPIO_PIN
config IEEE802154_CC2520_GPIO_SPI_CS_PIN
default 11
config IEEE802154_CC2520_GPIO_0_NAME
string
default GPIO_QMSI_0_NAME
config IEEE802154_CC2520_GPIO_1_NAME
string
default GPIO_QMSI_1_NAME
endif
endif # IEEE802154_CC2520

View file

@ -9,7 +9,6 @@
menuconfig IEEE802154_CC2520
bool "TI CC2520 Driver support"
depends on NETWORKING
select SPI_LEGACY_API
default n
if IEEE802154_CC2520
@ -42,6 +41,29 @@ config IEEE802154_CC2520_SPI_SLAVE
This option sets the SPI slave number SPI controller has to switch
to when dealing with CC2520 chip.
config IEEE802154_CC2520_GPIO_SPI_CS
bool "Manage SPI CS through a GPIO pin"
default n
help
This option is useful if one needs to manage SPI CS through a GPIO
pin to by-pass the SPI controller's CS logic.
config IEEE802154_CC2520_GPIO_SPI_CS_DRV_NAME
string "GPIO driver's name to use to drive SPI CS through"
default ""
depends on IEEE802154_CC2520_GPIO_SPI_CS
help
This option is mandatory to set which GPIO controller to use in order
to actually emulate the SPI CS.
config IEEE802154_CC2520_GPIO_SPI_CS_PIN
int "GPIO PIN to use to drive SPI CS through"
default 0
depends on IEEE802154_CC2520_GPIO_SPI_CS
help
This option is mandatory to set which GPIO pin to use in order
to actually emulate the SPI CS.
config IEEE802154_CC2520_RX_STACK_SIZE
int "Driver's internal RX thread stack size"
default 800

View file

@ -55,6 +55,10 @@
#define CC2520_TX_THRESHOLD (0x7F)
#define CC2520_FCS_LENGTH (2)
#if defined(CONFIG_IEEE802154_CC2520_GPIO_SPI_CS)
static struct spi_cs_control cs_ctrl;
#endif
/*********
* DEBUG *
********/
@ -64,21 +68,21 @@ static inline void _cc2520_print_gpio_config(struct device *dev)
struct cc2520_context *cc2520 = dev->driver_data;
SYS_LOG_DBG("GPIOCTRL0/1/2/3/4/5 = 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x",
read_reg_gpioctrl0(&cc2520->spi),
read_reg_gpioctrl1(&cc2520->spi),
read_reg_gpioctrl2(&cc2520->spi),
read_reg_gpioctrl3(&cc2520->spi),
read_reg_gpioctrl4(&cc2520->spi),
read_reg_gpioctrl5(&cc2520->spi));
read_reg_gpioctrl0(cc2520),
read_reg_gpioctrl1(cc2520),
read_reg_gpioctrl2(cc2520),
read_reg_gpioctrl3(cc2520),
read_reg_gpioctrl4(cc2520),
read_reg_gpioctrl5(cc2520));
SYS_LOG_DBG("GPIOPOLARITY: 0x%x",
read_reg_gpiopolarity(&cc2520->spi));
read_reg_gpiopolarity(cc2520));
SYS_LOG_DBG("GPIOCTRL: 0x%x",
read_reg_gpioctrl(&cc2520->spi));
read_reg_gpioctrl(cc2520));
}
static inline void _cc2520_print_exceptions(struct cc2520_context *cc2520)
{
u8_t flag = read_reg_excflag0(&cc2520->spi);
u8_t flag = read_reg_excflag0(cc2520);
SYS_LOG_DBG("EXCFLAG0:");
@ -116,7 +120,7 @@ static inline void _cc2520_print_exceptions(struct cc2520_context *cc2520)
SYS_LOG_BACKEND_FN("\n");
flag = read_reg_excflag1(&cc2520->spi);
flag = read_reg_excflag1(cc2520);
SYS_LOG_DBG("EXCFLAG1:");
@ -157,7 +161,7 @@ static inline void _cc2520_print_exceptions(struct cc2520_context *cc2520)
static inline void _cc2520_print_errors(struct cc2520_context *cc2520)
{
u8_t flag = read_reg_excflag2(&cc2520->spi);
u8_t flag = read_reg_excflag2(cc2520);
SYS_LOG_DBG("EXCFLAG2:");
@ -203,67 +207,58 @@ static inline void _cc2520_print_errors(struct cc2520_context *cc2520)
********************/
#define _usleep(usec) k_busy_wait(usec)
u8_t _cc2520_read_reg(struct cc2520_spi *spi,
bool freg, u8_t addr)
bool _cc2520_access(struct cc2520_context *ctx, bool read, u8_t ins,
u16_t addr, void *data, size_t length)
{
u8_t len = freg ? 2 : 3;
u8_t cmd_buf[2];
struct spi_buf buf[2] = {
{
.buf = cmd_buf,
.len = 1,
},
{
.buf = data,
.len = length,
spi->cmd_buf[0] = freg ? CC2520_INS_REGRD | addr : CC2520_INS_MEMRD;
spi->cmd_buf[1] = freg ? 0 : addr;
spi->cmd_buf[2] = 0;
}
};
struct spi_buf_set tx = {
.buffers = buf,
};
spi_slave_select(spi->dev, spi->slave);
if (spi_transceive(spi->dev, spi->cmd_buf, len,
spi->cmd_buf, len) == 0) {
return spi->cmd_buf[len - 1];
cmd_buf[0] = ins;
if (ins == CC2520_INS_MEMRD || ins == CC2520_INS_MEMWR) {
buf[0].len = 2;
cmd_buf[0] |= (u8_t)(addr >> 8);
cmd_buf[1] = (u8_t)(addr & 0xff);
} else if (ins == CC2520_INS_REGRD || ins == CC2520_INS_REGWR) {
cmd_buf[0] |= (u8_t)(addr & 0xff);
}
return 0;
if (read) {
const struct spi_buf_set rx = {
.buffers = buf,
.count = 2
};
tx.count = 1;
return (spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx) == 0);
}
tx.count = data ? 2 : 1;
return (spi_write(ctx->spi, &ctx->spi_cfg, &tx) == 0);
}
bool _cc2520_write_reg(struct cc2520_spi *spi, bool freg,
u8_t addr, u8_t value)
static inline u8_t _cc2520_status(struct cc2520_context *ctx)
{
u8_t len = freg ? 2 : 3;
u8_t status;
spi->cmd_buf[0] = freg ? CC2520_INS_REGWR | addr : CC2520_INS_MEMWR;
spi->cmd_buf[1] = freg ? value : addr;
spi->cmd_buf[2] = freg ? 0 : value;
spi_slave_select(spi->dev, spi->slave);
return (spi_write(spi->dev, spi->cmd_buf, len) == 0);
}
bool _cc2520_write_ram(struct cc2520_spi *spi, u16_t addr,
u8_t *data_buf, u8_t len)
{
#ifndef CONFIG_IEEE802154_CC2520_CRYPTO
u8_t *cmd_data = spi->cmd_buf;
#else
u8_t cmd_data[128];
#endif
cmd_data[0] = CC2520_INS_MEMWR | (addr >> 8);
cmd_data[1] = addr;
memcpy(&cmd_data[2], data_buf, len);
spi_slave_select(spi->dev, spi->slave);
return (spi_write(spi->dev, cmd_data, len + 2) == 0);
}
static u8_t _cc2520_status(struct cc2520_spi *spi)
{
spi->cmd_buf[0] = CC2520_INS_SNOP;
spi_slave_select(spi->dev, spi->slave);
if (spi_transceive(spi->dev, spi->cmd_buf, 1,
spi->cmd_buf, 1) == 0) {
return spi->cmd_buf[0];
if (_cc2520_access(ctx, true, CC2520_INS_SNOP, 0, &status, 1)) {
return status;
}
return 0;
@ -275,7 +270,7 @@ static bool verify_osc_stabilization(struct cc2520_context *cc2520)
u8_t status;
do {
status = _cc2520_status(&cc2520->spi);
status = _cc2520_status(cc2520);
_usleep(1);
timeout--;
} while (!(status & CC2520_STATUS_XOSC_STABLE_N_RUNNING) && timeout);
@ -317,7 +312,7 @@ static int _cc2520_set_pan_id(struct device *dev, u16_t pan_id)
pan_id = sys_le16_to_cpu(pan_id);
if (!write_mem_pan_id(&cc2520->spi, (u8_t *) &pan_id)) {
if (!write_mem_pan_id(cc2520, (u8_t *) &pan_id)) {
SYS_LOG_ERR("Failed");
return -EIO;
}
@ -333,7 +328,7 @@ static int _cc2520_set_short_addr(struct device *dev, u16_t short_addr)
short_addr = sys_le16_to_cpu(short_addr);
if (!write_mem_short_addr(&cc2520->spi, (u8_t *) &short_addr)) {
if (!write_mem_short_addr(cc2520, (u8_t *) &short_addr)) {
SYS_LOG_ERR("Failed");
return -EIO;
}
@ -345,7 +340,7 @@ static int _cc2520_set_ieee_addr(struct device *dev, const u8_t *ieee_addr)
{
struct cc2520_context *cc2520 = dev->driver_data;
if (!write_mem_ext_addr(&cc2520->spi, (void *)ieee_addr)) {
if (!write_mem_ext_addr(cc2520, (void *)ieee_addr)) {
SYS_LOG_ERR("Failed");
return -EIO;
}
@ -483,35 +478,24 @@ static inline void setup_gpio_callbacks(struct device *dev)
/****************
* TX functions *
***************/
static inline bool write_txfifo_length(struct cc2520_spi *spi,
u8_t len)
static inline bool write_txfifo_length(struct cc2520_context *ctx, u8_t len)
{
spi->cmd_buf[0] = CC2520_INS_TXBUF;
spi->cmd_buf[1] = len + CC2520_FCS_LENGTH;
u8_t length = len + CC2520_FCS_LENGTH;
spi_slave_select(spi->dev, spi->slave);
return (spi_write(spi->dev, spi->cmd_buf, 2) == 0);
return _cc2520_access(ctx, false, CC2520_INS_TXBUF, 0, &length, 1);
}
static inline bool write_txfifo_content(struct cc2520_spi *spi,
static inline bool write_txfifo_content(struct cc2520_context *ctx,
u8_t *frame, u8_t len)
{
u8_t cmd[128];
cmd[0] = CC2520_INS_TXBUF;
memcpy(&cmd[1], frame, len);
spi_slave_select(spi->dev, spi->slave);
return (spi_write(spi->dev, cmd, len + 1) == 0);
return _cc2520_access(ctx, false, CC2520_INS_TXBUF, 0, frame, len);
}
static inline bool verify_txfifo_status(struct cc2520_context *cc2520,
u8_t len)
{
if (read_reg_txfifocnt(&cc2520->spi) < len ||
(read_reg_excflag0(&cc2520->spi) & EXCFLAG0_TX_UNDERFLOW)) {
if (read_reg_txfifocnt(cc2520) < len ||
(read_reg_excflag0(cc2520) & EXCFLAG0_TX_UNDERFLOW)) {
return false;
}
@ -526,7 +510,7 @@ static inline bool verify_tx_done(struct cc2520_context *cc2520)
do {
_usleep(1);
timeout--;
status = read_reg_excflag0(&cc2520->spi);
status = read_reg_excflag0(cc2520);
} while (!(status & EXCFLAG0_TX_FRM_DONE) && timeout);
return !!(status & EXCFLAG0_TX_FRM_DONE);
@ -541,49 +525,38 @@ static inline void flush_rxfifo(struct cc2520_context *cc2520)
/* Note: Errata document - 1.1 */
enable_fifop_interrupt(cc2520, false);
instruct_sflushrx(&cc2520->spi);
instruct_sflushrx(&cc2520->spi);
instruct_sflushrx(cc2520);
instruct_sflushrx(cc2520);
enable_fifop_interrupt(cc2520, true);
write_reg_excflag0(&cc2520->spi, EXCFLAG0_RESET_RX_FLAGS);
write_reg_excflag0(cc2520, EXCFLAG0_RESET_RX_FLAGS);
}
static inline u8_t read_rxfifo_length(struct cc2520_spi *spi)
static inline u8_t read_rxfifo_length(struct cc2520_context *ctx)
{
spi->cmd_buf[0] = CC2520_INS_RXBUF;
spi->cmd_buf[1] = 0;
u8_t len;
spi_slave_select(spi->dev, spi->slave);
if (spi_transceive(spi->dev, spi->cmd_buf, 2,
spi->cmd_buf, 2) == 0) {
return spi->cmd_buf[1];
if (_cc2520_access(ctx, true, CC2520_INS_RXBUF, 0, &len, 1)) {
return len;
}
return 0;
}
static inline bool read_rxfifo_content(struct cc2520_spi *spi,
static inline bool read_rxfifo_content(struct cc2520_context *ctx,
struct net_buf *frag, u8_t len)
{
u8_t data[128+1];
data[0] = CC2520_INS_RXBUF;
memset(&data[1], 0, len);
spi_slave_select(spi->dev, spi->slave);
if (spi_transceive(spi->dev, data, len+1, data, len+1) != 0) {
if (!_cc2520_access(ctx, true, CC2520_INS_RXBUF, 0, frag->data, len)) {
return false;
}
if (read_reg_excflag0(spi) & EXCFLAG0_RX_UNDERFLOW) {
if (read_reg_excflag0(ctx) & EXCFLAG0_RX_UNDERFLOW) {
SYS_LOG_ERR("RX underflow!");
return false;
}
memcpy(frag->data, &data[1], len);
net_buf_add(frag, len);
return true;
@ -617,46 +590,27 @@ static inline void insert_radio_noise_details(struct net_pkt *pkt, u8_t *buf)
net_pkt_set_ieee802154_lqi(pkt, lqi);
}
static inline bool verify_crc(struct cc2520_context *cc2520,
struct net_pkt *pkt)
static inline bool verify_crc(struct cc2520_context *ctx, struct net_pkt *pkt)
{
u8_t *noise_buf;
u8_t fcs[2];
if (!IS_ENABLED(CONFIG_IEEE802154_RAW_MODE)) {
cc2520->spi.cmd_buf[0] = CC2520_INS_RXBUF;
cc2520->spi.cmd_buf[1] = 0;
cc2520->spi.cmd_buf[2] = 0;
spi_slave_select(cc2520->spi.dev, cc2520->spi.slave);
if (spi_transceive(cc2520->spi.dev, cc2520->spi.cmd_buf, 3,
cc2520->spi.cmd_buf, 3) != 0) {
return false;
}
if (!(cc2520->spi.cmd_buf[2] & CC2520_FCS_CRC_OK)) {
return false;
}
noise_buf = &cc2520->spi.cmd_buf[1];
} else {
if (!(pkt->frags->data[pkt->frags->len - 1] &
CC2520_FCS_CRC_OK)) {
return false;
}
noise_buf = &pkt->frags->data[pkt->frags->len - 2];
if (!_cc2520_access(ctx, true, CC2520_INS_RXBUF, 0, &fcs, 2)) {
return false;
}
insert_radio_noise_details(pkt, noise_buf);
if (!(fcs[1] & CC2520_FCS_CRC_OK)) {
return false;
}
insert_radio_noise_details(pkt, fcs);
return true;
}
static inline bool verify_rxfifo_validity(struct cc2520_spi *spi,
static inline bool verify_rxfifo_validity(struct cc2520_context *ctx,
u8_t pkt_len)
{
if (pkt_len < 2 || read_reg_rxfifocnt(spi) != pkt_len) {
if (pkt_len < 2 || read_reg_rxfifocnt(ctx) != pkt_len) {
return false;
}
@ -683,8 +637,8 @@ static void cc2520_rx(int arg)
goto flush;
}
pkt_len = read_rxfifo_length(&cc2520->spi) & 0x7f;
if (!verify_rxfifo_validity(&cc2520->spi, pkt_len)) {
pkt_len = read_rxfifo_length(cc2520) & 0x7f;
if (!verify_rxfifo_validity(cc2520, pkt_len)) {
SYS_LOG_ERR("Invalid content");
goto flush;
}
@ -707,7 +661,7 @@ static void cc2520_rx(int arg)
pkt_len -= 2;
}
if (!read_rxfifo_content(&cc2520->spi, pkt_frag, pkt_len)) {
if (!read_rxfifo_content(cc2520, pkt_frag, pkt_len)) {
SYS_LOG_ERR("No content read");
goto flush;
}
@ -780,7 +734,7 @@ static int cc2520_set_channel(struct device *dev, u16_t channel)
/* See chapter 16 */
channel = 11 + 5 * (channel - 11);
if (!write_reg_freqctrl(&cc2520->spi, FREQCTRL_FREQ(channel))) {
if (!write_reg_freqctrl(cc2520, FREQCTRL_FREQ(channel))) {
SYS_LOG_ERR("Failed");
return -EIO;
}
@ -845,7 +799,7 @@ static int cc2520_set_txpower(struct device *dev, s16_t dbm)
goto error;
}
if (!write_reg_txpower(&cc2520->spi, pwr)) {
if (!write_reg_txpower(cc2520, pwr)) {
goto error;
}
@ -867,9 +821,9 @@ static int cc2520_tx(struct device *dev,
SYS_LOG_DBG("%p (%u)", frag, len);
if (!write_reg_excflag0(&cc2520->spi, EXCFLAG0_RESET_TX_FLAGS) ||
!write_txfifo_length(&cc2520->spi, len) ||
!write_txfifo_content(&cc2520->spi, frame, len)) {
if (!write_reg_excflag0(cc2520, EXCFLAG0_RESET_TX_FLAGS) ||
!write_txfifo_length(cc2520, len) ||
!write_txfifo_content(cc2520, frame, len)) {
SYS_LOG_ERR("Cannot feed in TX fifo");
goto error;
}
@ -888,7 +842,7 @@ static int cc2520_tx(struct device *dev,
atomic_set(&cc2520->tx, 1);
k_sem_init(&cc2520->tx_sync, 0, UINT_MAX);
if (!instruct_stxoncca(&cc2520->spi)) {
if (!instruct_stxoncca(cc2520)) {
SYS_LOG_ERR("Cannot start transmission");
goto error;
}
@ -916,7 +870,7 @@ error:
_cc2520_print_errors(cc2520);
atomic_set(&cc2520->tx, 0);
instruct_sflushtx(&cc2520->spi);
instruct_sflushtx(cc2520);
return -EIO;
}
@ -927,8 +881,8 @@ static int cc2520_start(struct device *dev)
SYS_LOG_DBG("");
if (!instruct_sxoscon(&cc2520->spi) ||
!instruct_srxon(&cc2520->spi) ||
if (!instruct_sxoscon(cc2520) ||
!instruct_srxon(cc2520) ||
!verify_osc_stabilization(cc2520)) {
SYS_LOG_ERR("Error starting CC2520");
return -EIO;
@ -953,8 +907,8 @@ static int cc2520_stop(struct device *dev)
enable_fifop_interrupt(cc2520, false);
enable_sfd_interrupt(cc2520, false);
if (!instruct_srfoff(&cc2520->spi) ||
!instruct_sxoscoff(&cc2520->spi)) {
if (!instruct_srfoff(cc2520) ||
!instruct_sxoscoff(cc2520)) {
SYS_LOG_ERR("Error stopping CC2520");
return -EIO;
}
@ -988,17 +942,17 @@ static int power_on_and_setup(struct device *dev)
}
/* Default settings to always write (see chapter 28 part 1) */
if (!write_reg_txpower(&cc2520->spi, CC2520_TXPOWER_DEFAULT) ||
!write_reg_ccactrl0(&cc2520->spi, CC2520_CCACTRL0_DEFAULT) ||
!write_reg_mdmctrl0(&cc2520->spi, CC2520_MDMCTRL0_DEFAULT) ||
!write_reg_mdmctrl1(&cc2520->spi, CC2520_MDMCTRL1_DEFAULT) ||
!write_reg_rxctrl(&cc2520->spi, CC2520_RXCTRL_DEFAULT) ||
!write_reg_fsctrl(&cc2520->spi, CC2520_FSCTRL_DEFAULT) ||
!write_reg_fscal1(&cc2520->spi, CC2520_FSCAL1_DEFAULT) ||
!write_reg_agcctrl1(&cc2520->spi, CC2520_AGCCTRL1_DEFAULT) ||
!write_reg_adctest0(&cc2520->spi, CC2520_ADCTEST0_DEFAULT) ||
!write_reg_adctest1(&cc2520->spi, CC2520_ADCTEST1_DEFAULT) ||
!write_reg_adctest2(&cc2520->spi, CC2520_ADCTEST2_DEFAULT)) {
if (!write_reg_txpower(cc2520, CC2520_TXPOWER_DEFAULT) ||
!write_reg_ccactrl0(cc2520, CC2520_CCACTRL0_DEFAULT) ||
!write_reg_mdmctrl0(cc2520, CC2520_MDMCTRL0_DEFAULT) ||
!write_reg_mdmctrl1(cc2520, CC2520_MDMCTRL1_DEFAULT) ||
!write_reg_rxctrl(cc2520, CC2520_RXCTRL_DEFAULT) ||
!write_reg_fsctrl(cc2520, CC2520_FSCTRL_DEFAULT) ||
!write_reg_fscal1(cc2520, CC2520_FSCAL1_DEFAULT) ||
!write_reg_agcctrl1(cc2520, CC2520_AGCCTRL1_DEFAULT) ||
!write_reg_adctest0(cc2520, CC2520_ADCTEST0_DEFAULT) ||
!write_reg_adctest1(cc2520, CC2520_ADCTEST1_DEFAULT) ||
!write_reg_adctest2(cc2520, CC2520_ADCTEST2_DEFAULT)) {
return -EIO;
}
@ -1008,21 +962,21 @@ static int power_on_and_setup(struct device *dev)
* FRMFILT0: Frame filtering (setting CC2520_FRAME_FILTERING)
* FIFOPCTRL: Set TX threshold (setting CC2520_TX_THRESHOLD)
*/
if (!write_reg_extclock(&cc2520->spi, 0) ||
!write_reg_frmctrl0(&cc2520->spi, CC2520_AUTOMATISM) ||
!write_reg_frmctrl1(&cc2520->spi, FRMCTRL1_IGNORE_TX_UNDERF |
if (!write_reg_extclock(cc2520, 0) ||
!write_reg_frmctrl0(cc2520, CC2520_AUTOMATISM) ||
!write_reg_frmctrl1(cc2520, FRMCTRL1_IGNORE_TX_UNDERF |
FRMCTRL1_SET_RXENMASK_ON_TX) ||
!write_reg_frmfilt0(&cc2520->spi, FRMFILT0_FRAME_FILTER_EN |
!write_reg_frmfilt0(cc2520, FRMFILT0_FRAME_FILTER_EN |
FRMFILT0_MAX_FRAME_VERSION(3)) ||
!write_reg_frmfilt1(&cc2520->spi, FRMFILT1_ACCEPT_ALL) ||
!write_reg_srcmatch(&cc2520->spi, SRCMATCH_DEFAULTS) ||
!write_reg_fifopctrl(&cc2520->spi,
!write_reg_frmfilt1(cc2520, FRMFILT1_ACCEPT_ALL) ||
!write_reg_srcmatch(cc2520, SRCMATCH_DEFAULTS) ||
!write_reg_fifopctrl(cc2520,
FIFOPCTRL_FIFOP_THR(CC2520_TX_THRESHOLD))) {
return -EIO;
}
/* Cleaning up TX fifo */
instruct_sflushtx(&cc2520->spi);
instruct_sflushtx(cc2520);
setup_gpio_callbacks(dev);
@ -1034,27 +988,36 @@ static int power_on_and_setup(struct device *dev)
static inline int configure_spi(struct device *dev)
{
struct cc2520_context *cc2520 = dev->driver_data;
struct spi_config spi_conf = {
.config = SPI_WORD(8),
.max_sys_freq = CONFIG_IEEE802154_CC2520_SPI_FREQ,
};
cc2520->spi.dev = device_get_binding(
cc2520->spi = device_get_binding(
CONFIG_IEEE802154_CC2520_SPI_DRV_NAME);
if (!cc2520->spi.dev) {
if (!cc2520->spi) {
SYS_LOG_ERR("Unable to get SPI device");
return -ENODEV;
}
cc2520->spi.slave = CONFIG_IEEE802154_CC2520_SPI_SLAVE;
if (spi_configure(cc2520->spi.dev, &spi_conf) != 0 ||
spi_slave_select(cc2520->spi.dev,
cc2520->spi.slave) != 0) {
cc2520->spi.dev = NULL;
return -EIO;
#if defined(CONFIG_IEEE802154_CC2520_GPIO_SPI_CS)
cs_ctrl.gpio_dev = device_get_binding(
CONFIG_IEEE802154_CC2520_GPIO_SPI_CS_DRV_NAME);
if (!cs_ctrl.gpio_dev) {
SYS_LOG_ERR("Unable to get GPIO SPI CS device");
return -ENODEV;
}
cs_ctrl.gpio_pin = CONFIG_IEEE802154_CC2520_GPIO_SPI_CS_PIN;
cs_ctrl.delay = 0;
cc2520->spi_cfg.cs = &cs_ctrl;
SYS_LOG_DBG("SPI GPIO CS configured on %s:%u",
CONFIG_IEEE802154_CC2520_GPIO_SPI_CS_DRV_NAME,
CONFIG_IEEE802154_CC2520_GPIO_SPI_CS_PIN);
#endif /* CONFIG_IEEE802154_CC2520_GPIO_SPI_CS */
cc2520->spi_cfg.frequency = CONFIG_IEEE802154_CC2520_SPI_FREQ;
cc2520->spi_cfg.operation = SPI_WORD_SET(8);
cc2520->spi_cfg.slave = CONFIG_IEEE802154_CC2520_SPI_SLAVE;
return 0;
}
@ -1150,44 +1113,50 @@ NET_STACK_INFO_ADDR(RX, cc2520,
#ifdef CONFIG_IEEE802154_CC2520_CRYPTO
static bool _cc2520_read_ram(struct cc2520_spi *spi, u16_t addr,
u8_t *data_buf, u8_t len)
static inline bool _cc2520_read_ram(struct cc2520_context *ctx, u16_t addr,
u8_t *data_buf, u8_t len)
{
u8_t cmd_buf[128];
cmd_buf[0] = CC2520_INS_MEMRD | (addr >> 8);
cmd_buf[1] = addr;
spi_slave_select(spi->dev, spi->slave);
if (spi_transceive(spi->dev, cmd_buf, len + 2,
cmd_buf, len + 2) != 0) {
return false;
}
memcpy(data_buf, &cmd_buf[2], len);
return true;
return _cc2520_access(ctx, true, CC2520_INS_MEMRD,
addr, data_buf, len);
}
static inline bool instruct_ccm(struct cc2520_context *cc2520,
u8_t key_addr,
u8_t auth_crypt,
u8_t nonce_addr,
u16_t input_addr,
u16_t output_addr,
u8_t in_len,
u8_t m)
static inline bool _cc2520_write_ram(struct cc2520_context *ctx, u16_t addr,
u8_t *data_buf, u8_t len)
{
return _cc2520_access(ctx, false, CC2520_INS_MEMWR,
addr, data_buf, len);
}
static inline bool instruct_uccm_ccm(struct cc2520_context *cc2520,
bool uccm,
u8_t key_addr,
u8_t auth_crypt,
u8_t nonce_addr,
u16_t input_addr,
u16_t output_addr,
u8_t in_len,
u8_t m)
{
u8_t cmd[9];
const struct spi_buf buf[1] = {
{
.buf = cmd,
.len = 9,
},
};
const struct spi_buf_set tx = {
.buffers = buf,
.count = 1
};
int ret;
SYS_LOG_DBG("CCM(P={01} K={%02x} C={%02x} N={%02x}"
SYS_LOG_DBG("%sCCM(P={01} K={%02x} C={%02x} N={%02x}"
" A={%03x} E={%03x} F{%02x} M={%02x})",
key_addr, auth_crypt, nonce_addr,
uccm ? "U" : "", key_addr, auth_crypt, nonce_addr,
input_addr, output_addr, in_len, m);
cmd[0] = CC2520_INS_CCM | 1;
cmd[0] = uccm ? CC2520_INS_UCCM | 1 : CC2520_INS_CCM | 1;
cmd[1] = key_addr;
cmd[2] = (auth_crypt & 0x7f);
cmd[3] = nonce_addr;
@ -1200,54 +1169,12 @@ static inline bool instruct_ccm(struct cc2520_context *cc2520,
k_sem_take(&cc2520->access_lock, K_FOREVER);
ret = spi_write(cc2520->spi.dev, cmd, 9);
ret = spi_write(cc2520->spi, &cc2520->spi_cfg, &tx);
k_sem_give(&cc2520->access_lock);
if (ret) {
SYS_LOG_ERR("CCM Failed");
return false;
}
return true;
}
static inline bool instruct_uccm(struct cc2520_context *cc2520,
u8_t key_addr,
u8_t auth_crypt,
u8_t nonce_addr,
u16_t input_addr,
u16_t output_addr,
u8_t in_len,
u8_t m)
{
u8_t cmd[9];
int ret;
SYS_LOG_DBG("UCCM(P={01} K={%02x} C={%02x} N={%02x}"
" A={%03x} E={%03x} F{%02x} M={%02x})",
key_addr, auth_crypt, nonce_addr,
input_addr, output_addr, in_len, m);
cmd[0] = CC2520_INS_UCCM | 1;
cmd[1] = key_addr;
cmd[2] = (auth_crypt & 0x7f);
cmd[3] = nonce_addr;
cmd[4] = (u8_t)(((input_addr & 0x0f00) >> 4) |
((output_addr & 0x0f00) >> 8));
cmd[5] = (u8_t)(input_addr & 0x00ff);
cmd[6] = (u8_t)(output_addr & 0x00ff);
cmd[7] = (in_len & 0x7f);
cmd[8] = (m & 0x03);
k_sem_take(&cc2520->access_lock, K_FOREVER);
ret = spi_write(cc2520->spi.dev, cmd, 9);
k_sem_give(&cc2520->access_lock);
if (ret) {
SYS_LOG_ERR("UCCM Failed");
SYS_LOG_ERR("%sCCM Failed", uccm ? "U" : "");
return false;
}
@ -1334,7 +1261,7 @@ static int insert_crypto_parameters(struct cipher_ctx *ctx,
}
/* Writing the frame in RAM */
if (!_cc2520_write_ram(&cc2520->spi, CC2520_MEM_DATA, in_buf, in_len)) {
if (!_cc2520_write_ram(cc2520, CC2520_MEM_DATA, in_buf, in_len)) {
SYS_LOG_ERR("Cannot write the frame in RAM");
return -EIO;
}
@ -1343,7 +1270,7 @@ static int insert_crypto_parameters(struct cipher_ctx *ctx,
sys_memcpy_swap(data, ctx->key.bit_stream, ctx->keylen);
/* Writing the key in RAM */
if (!_cc2520_write_ram(&cc2520->spi, CC2520_MEM_KEY, data, 16)) {
if (!_cc2520_write_ram(cc2520, CC2520_MEM_KEY, data, 16)) {
SYS_LOG_ERR("Cannot write the key in RAM");
return -EIO;
}
@ -1351,7 +1278,7 @@ static int insert_crypto_parameters(struct cipher_ctx *ctx,
generate_nonce(ccm_nonce, data, apkt, m);
/* Writing the nonce in RAM */
if (!_cc2520_write_ram(&cc2520->spi, CC2520_MEM_NONCE, data, 16)) {
if (!_cc2520_write_ram(cc2520, CC2520_MEM_NONCE, data, 16)) {
SYS_LOG_ERR("Cannot write the nonce in RAM");
return -EIO;
}
@ -1392,10 +1319,10 @@ static int _cc2520_crypto_ccm(struct cipher_ctx *ctx,
return -ENOBUFS;
}
if (!instruct_ccm(cc2520, CC2520_MEM_KEY >> 4, auth_crypt,
CC2520_MEM_NONCE >> 4, CC2520_MEM_DATA,
0x000, apkt->ad_len, m) ||
!_cc2520_read_ram(&cc2520->spi, CC2520_MEM_DATA,
if (!instruct_uccm_ccm(cc2520, false, CC2520_MEM_KEY >> 4, auth_crypt,
CC2520_MEM_NONCE >> 4, CC2520_MEM_DATA,
0x000, apkt->ad_len, m) ||
!_cc2520_read_ram(cc2520, CC2520_MEM_DATA,
apkt->pkt->out_buf, apkt->pkt->out_len)) {
SYS_LOG_ERR("CCM or reading result from RAM failed");
return -EIO;
@ -1431,16 +1358,16 @@ static int _cc2520_crypto_uccm(struct cipher_ctx *ctx,
apkt->pkt->out_len = apkt->pkt->in_len + apkt->ad_len;
if (!instruct_uccm(cc2520, CC2520_MEM_KEY >> 4, auth_crypt,
CC2520_MEM_NONCE >> 4, CC2520_MEM_DATA,
0x000, apkt->ad_len, m) ||
!_cc2520_read_ram(&cc2520->spi, CC2520_MEM_DATA,
if (!instruct_uccm_ccm(cc2520, true, CC2520_MEM_KEY >> 4, auth_crypt,
CC2520_MEM_NONCE >> 4, CC2520_MEM_DATA,
0x000, apkt->ad_len, m) ||
!_cc2520_read_ram(cc2520, CC2520_MEM_DATA,
apkt->pkt->out_buf, apkt->pkt->out_len)) {
SYS_LOG_ERR("UCCM or reading result from RAM failed");
return -EIO;
}
if (m && (!(read_reg_dpustat(&cc2520->spi) & DPUSTAT_AUTHSTAT_H))) {
if (m && (!(read_reg_dpustat(cc2520) & DPUSTAT_AUTHSTAT_H))) {
SYS_LOG_ERR("Authentication of the frame failed");
return -EBADMSG;
}

View file

@ -18,23 +18,14 @@
/* Runtime context structure
***************************
*/
struct cc2520_spi {
struct device *dev;
u32_t slave;
/**
* cmd_buf will use at most 9 bytes:
* dummy bytes + 8 ieee address bytes
*/
u8_t cmd_buf[12];
};
struct cc2520_context {
struct net_if *iface;
/**************************/
struct cc2520_gpio_configuration *gpios;
struct gpio_callback sfd_cb;
struct gpio_callback fifop_cb;
struct cc2520_spi spi;
struct device *spi;
struct spi_config spi_cfg;
u8_t mac_addr[8];
/************TX************/
struct k_sem tx_sync;
@ -57,34 +48,50 @@ struct cc2520_context {
***************************
*/
u8_t _cc2520_read_reg(struct cc2520_spi *spi,
bool freg, u8_t addr);
bool _cc2520_write_reg(struct cc2520_spi *spi, bool freg,
u8_t addr, u8_t value);
bool _cc2520_access(struct cc2520_context *ctx, bool read, u8_t ins,
u16_t addr, void *data, size_t length);
#define DEFINE_REG_READ(__reg_name, __reg_addr, __freg) \
static inline u8_t read_reg_##__reg_name(struct cc2520_spi *spi) \
#define DEFINE_SREG_READ(__reg_name, __reg_addr) \
static inline u8_t read_reg_##__reg_name(struct cc2520_context *ctx) \
{ \
return _cc2520_read_reg(spi, __freg, __reg_addr); \
u8_t val; \
\
if (_cc2520_access(ctx, true, CC2520_INS_MEMRD, \
__reg_addr, &val, 1)) { \
return val; \
} \
\
return 0; \
}
#define DEFINE_REG_WRITE(__reg_name, __reg_addr, __freg) \
static inline bool write_reg_##__reg_name(struct cc2520_spi *spi, \
#define DEFINE_SREG_WRITE(__reg_name, __reg_addr) \
static inline bool write_reg_##__reg_name(struct cc2520_context *ctx, \
u8_t val) \
{ \
return _cc2520_write_reg(spi, __freg, __reg_addr, val); \
return _cc2520_access(ctx, false, CC2520_INS_MEMWR, \
__reg_addr, &val, 1); \
}
#define DEFINE_FREG_READ(__reg_name, __reg_addr) \
DEFINE_REG_READ(__reg_name, __reg_addr, true)
#define DEFINE_FREG_WRITE(__reg_name, __reg_addr) \
DEFINE_REG_WRITE(__reg_name, __reg_addr, true)
#define DEFINE_SREG_READ(__reg_name, __reg_addr) \
DEFINE_REG_READ(__reg_name, __reg_addr, false)
#define DEFINE_SREG_WRITE(__reg_name, __reg_addr) \
DEFINE_REG_WRITE(__reg_name, __reg_addr, false)
#define DEFINE_FREG_READ(__reg_name, __reg_addr) \
static inline u8_t read_reg_##__reg_name(struct cc2520_context *ctx) \
{ \
u8_t val; \
\
if (_cc2520_access(ctx, true, CC2520_INS_REGRD, \
__reg_addr, &val, 1)) { \
return val; \
} \
\
return 0; \
}
#define DEFINE_FREG_WRITE(__reg_name, __reg_addr) \
static inline bool write_reg_##__reg_name(struct cc2520_context *ctx, \
u8_t val) \
{ \
return _cc2520_access(ctx, false, CC2520_INS_REGWR, \
__reg_addr, &val, 1); \
}
DEFINE_FREG_READ(excflag0, CC2520_FREG_EXCFLAG0)
DEFINE_FREG_READ(excflag1, CC2520_FREG_EXCFLAG1)
@ -129,14 +136,12 @@ DEFINE_SREG_WRITE(extclock, CC2520_SREG_EXTCLOCK)
************************
*/
bool _cc2520_write_ram(struct cc2520_spi *spi, u16_t addr,
u8_t *data_buf, u8_t len);
#define DEFINE_MEM_WRITE(__mem_name, __addr, __sz) \
static inline bool write_mem_##__mem_name(struct cc2520_spi *spi, \
static inline bool write_mem_##__mem_name(struct cc2520_context *ctx, \
u8_t *buf) \
{ \
return _cc2520_write_ram(spi, __addr, buf, __sz); \
return _cc2520_access(ctx, false, CC2520_INS_MEMWR, \
__addr, buf, __sz); \
}
DEFINE_MEM_WRITE(short_addr, CC2520_MEM_SHORT_ADDR, 2)
@ -148,37 +153,30 @@ DEFINE_MEM_WRITE(ext_addr, CC2520_MEM_EXT_ADDR, 8)
******************************
*/
static inline bool _cc2520_command_strobe(struct cc2520_spi *spi,
static inline bool _cc2520_command_strobe(struct cc2520_context *ctx,
u8_t instruction)
{
spi_slave_select(spi->dev, spi->slave);
return (spi_write(spi->dev, &instruction, 1) == 0);
return _cc2520_access(ctx, false, instruction, 0, NULL, 0);
}
static inline bool _cc2520_command_strobe_snop(struct cc2520_spi *spi,
static inline bool _cc2520_command_strobe_snop(struct cc2520_context *ctx,
u8_t instruction)
{
u8_t ins[2] = {
instruction,
CC2520_INS_SNOP
};
u8_t snop[1] = { CC2520_INS_SNOP };
spi_slave_select(spi->dev, spi->slave);
return (spi_write(spi->dev, ins, 2) == 0);
return _cc2520_access(ctx, false, instruction, 0, snop, 1);
}
#define DEFINE_STROBE_INSTRUCTION(__ins_name, __ins) \
static inline bool instruct_##__ins_name(struct cc2520_spi *spi) \
static inline bool instruct_##__ins_name(struct cc2520_context *ctx) \
{ \
return _cc2520_command_strobe(spi, __ins); \
return _cc2520_command_strobe(ctx, __ins); \
}
#define DEFINE_STROBE_SNOP_INSTRUCTION(__ins_name, __ins) \
static inline bool instruct_##__ins_name(struct cc2520_spi *spi) \
static inline bool instruct_##__ins_name(struct cc2520_context *ctx) \
{ \
return _cc2520_command_strobe_snop(spi, __ins); \
return _cc2520_command_strobe_snop(ctx, __ins); \
}
DEFINE_STROBE_INSTRUCTION(srxon, CC2520_INS_SRXON)