/* cc2520_arch.h - TI CC2520 arch/driver model specific header */ /* * Copyright (c) 2015 Intel Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* You should not include this file directly and it should only be * included by board.h file. */ #ifndef __CC2520_ARCH_H__ #define __CC2520_ARCH_H__ #include #include #include #include #include #include "cc2520.h" #if CONFIG_TI_CC2520_DEBUG #define DRIVER_STR "TI cc2520 driver" #if defined(CONFIG_STDOUT_CONSOLE) #include #define DBG printf #else #include #define DBG printk #endif #else #define DBG(...) #endif /* CONFIG_TI_CC2520_DEBUG */ #ifndef CLOCK_CYCLE_LT #define CLOCK_CYCLE_LT(a, b) ((signed)((a)-(b)) < 0) #endif #ifndef CLOCK_MSEC_TO_CYCLES #define CLOCK_MSEC_TO_CYCLES(msec) \ ((msec) * sys_clock_hw_cycles_per_tick * \ sys_clock_us_per_tick / 1000) #endif #define CONFIG_CC2520_DRV_NAME "CC2520" #define CC2520_READING_STACK_SIZE CONFIG_TI_CC2520_FIBER_STACK_SIZE struct cc2520_gpio_config { struct device *gpio; }; struct cc2520_config { struct cc2520_gpio_config **gpios; struct device *spi; uint32_t spi_slave; struct nano_sem read_lock; struct nano_sem radio_lock; }; extern struct cc2520_gpio_config cc2520_gpio_config[CC2520_GPIO_IDX_LAST_ENTRY]; extern struct cc2520_config cc2520_config; extern struct device *cc2520_sgl_dev; typedef void (*cc2520_gpio_int_handler_t)(struct device *port, uint32_t pin); struct cc2520_gpio_config **cc2520_gpio_configure(void); #define CC2520_GPIO(p) \ (((struct device *)& \ ((struct cc2520_config *) \ cc2520_sgl_dev-> \ config->config_info)->gpios[CC2520_GPIO_IDX_ ## p]->gpio)) #define CC2520_SPI() \ (((struct cc2520_config *) \ cc2520_sgl_dev->config->config_info)->spi) #define CC2520_SPI_SLAVE() \ (((struct cc2520_config *) \ cc2520_sgl_dev->config->config_info)->spi_slave) static inline bool spi_transfer(struct device *dev, uint8_t *data_out, uint8_t *data_in, int len) { uint32_t out_len, in_len; int ret; out_len = data_out ? len : 0; in_len = data_in ? len : 0; spi_slave_select(dev, CC2520_SPI_SLAVE()); ret = spi_transceive(dev, data_out, out_len, data_in, in_len); return (ret == DEV_OK); } static inline bool cc2520_read_fifo_buf(uint8_t *buffer, uint32_t count) { uint8_t data[128 + 1] = { 0xff }; bool ret; data[0] = CC2520_INS_RXBUF; ret = spi_transfer(CC2520_SPI(), data, data, count + 1); if (ret) { memcpy(buffer, data + 1, count); } return ret; } static inline bool cc2520_write_fifo_buf(uint8_t *buffer, int count) { uint8_t data[128 + 1]; if (count > (sizeof(data) - 1)) { DBG("%s: too long data %d, max is %lu\n", __func__, count, sizeof(data) - 1); return false; } data[0] = CC2520_INS_TXBUF; memcpy(&data[1], buffer, count); return spi_transfer(CC2520_SPI(), data, NULL, count + 1); } static inline bool cc2520_write_reg(uint16_t addr, uint16_t value) { uint8_t data[3]; data[0] = (CC2520_INS_MEMWR | (addr >> 8)) & 0xff; data[1] = addr & 0xff; data[2] = value & 0xff; return spi_transfer(CC2520_SPI(), data, NULL, 3); } static inline bool cc2520_read_reg(uint16_t addr, uint16_t *value) { uint8_t data[3]; bool ret; data[0] = (CC2520_INS_MEMRD | (addr >> 8)) & 0xff; data[1] = addr & 0xff; data[2] = 0; ret = spi_transfer(CC2520_SPI(), data, data, 3); *value = data[2]; return ret; } static inline bool cc2520_write_ram(uint8_t *buffer, int addr, int count) { uint8_t data[128 + 1 + 1]; if (count > (sizeof(data) - 2)) { DBG("%s: too long data %d, max is %lu\n", __func__, count, sizeof(data) - 2); return false; } data[0] = (CC2520_INS_MEMWR | (addr >> 8)) & 0xff; data[1] = addr & 0xff; memcpy(&data[2], buffer, count); return spi_transfer(CC2520_SPI(), data, NULL, count + 2); } static inline bool cc2520_read_ram(uint8_t *buffer, int addr, uint32_t count) { uint8_t data[128 + 1 + 1] = { 0 }; int ret; data[0] = (CC2520_INS_MEMRD | (addr >> 8)) & 0xff; data[1] = addr & 0xff; ret = spi_transfer(CC2520_SPI(), data, data, count + 2); memcpy(buffer, data + 2, count); return (!ret); } static inline bool cc2520_get_status(uint8_t *status) { uint8_t data = CC2520_INS_SNOP; return spi_transfer(CC2520_SPI(), &data, status, 1); } static inline bool cc2520_strobe(uint8_t strobe) { return spi_transfer(CC2520_SPI(), &strobe, NULL, 1); } static inline bool cc2520_strobe_plus_nop(uint8_t strobe) { uint8_t data[2]; data[0] = strobe; data[1] = CC2520_INS_SNOP; return spi_transfer(CC2520_SPI(), data, NULL, 2); } static inline int cc2520_get_fifop(void) { uint32_t value; gpio_pin_read(CC2520_GPIO(FIFOP), CONFIG_CC2520_GPIO_FIFOP, &value); return value; } static inline int cc2520_get_fifo(void) { uint32_t value; gpio_pin_read(CC2520_GPIO(FIFO), CONFIG_CC2520_GPIO_FIFO, &value); return value; } static inline int cc2520_get_sfd(void) { uint32_t value; gpio_pin_read(CC2520_GPIO(SFD), CONFIG_CC2520_GPIO_SFD, &value); return value; } static inline int cc2520_get_cca(void) { uint32_t value; gpio_pin_read(CC2520_GPIO(CCA), CONFIG_CC2520_GPIO_CCA, &value); return value; } static inline void cc2520_set_vreg(int enable) { /* If VREG_EN is connected to VDD, then set the gpio pointer * to NULL and do not configure. */ if (!CC2520_GPIO(VREG)) { return; } gpio_pin_write(CC2520_GPIO(VREG), CONFIG_CC2520_GPIO_VREG, enable); } static inline void cc2520_set_reset(int enable) { gpio_pin_write(CC2520_GPIO(RESET), CONFIG_CC2520_GPIO_RESET, enable); } static inline void cc2520_enable_fifop_int(int enable) { DBG("%s FIFOP\n", enable ? "enable" : "disable"); if (enable) { gpio_pin_enable_callback(CC2520_GPIO(FIFOP), CONFIG_CC2520_GPIO_FIFOP); } else { gpio_pin_disable_callback(CC2520_GPIO(FIFOP), CONFIG_CC2520_GPIO_FIFOP); } } static inline void cc2520_init_fifop_int(cc2520_gpio_int_handler_t handler) { gpio_set_callback(CC2520_GPIO(FIFOP), handler); } #endif /* __CC2520_ARCH_H__ */