arm: spi: spi master support for nrf52 family
* SPIMx support for nrf52 spi interface with easy dma Change-Id: I3221b14867924b91a9d809faf689090574f5dc1c Signed-off-by: Roger Lendenmann <roger.lendenmann@intel.com>
This commit is contained in:
parent
8e85600a30
commit
5bcc8fa832
5 changed files with 643 additions and 4 deletions
|
@ -328,7 +328,10 @@ static const struct i2c_driver_api i2c_nrf5_driver_api = {
|
|||
.transfer = i2c_nrf5_transfer,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_I2C_0
|
||||
/* i2c & spi instance with the same id (e.g. I2C_0 and SPI_0) can NOT be used
|
||||
* at the same time on nRF5x chip family.
|
||||
*/
|
||||
#if defined(CONFIG_I2C_0) && !defined(CONFIG_SPI_0)
|
||||
static void i2c_nrf5_config_func_0(struct device *dev);
|
||||
|
||||
static const struct i2c_nrf5_config i2c_nrf5_config_0 = {
|
||||
|
@ -351,9 +354,9 @@ static void i2c_nrf5_config_func_0(struct device *dev)
|
|||
|
||||
irq_enable(NRF5_IRQ_SPI0_TWI0_IRQn);
|
||||
}
|
||||
#endif /* CONFIG_I2C_0 */
|
||||
#endif /* CONFIG_I2C_0 && !CONFIG_SPI_0 */
|
||||
|
||||
#ifdef CONFIG_I2C_1
|
||||
#if defined(CONFIG_I2C_1) && !defined(CONFIG_SPI_1)
|
||||
static void i2c_nrf5_config_func_1(struct device *dev);
|
||||
|
||||
static const struct i2c_nrf5_config i2c_nrf5_config_1 = {
|
||||
|
@ -376,4 +379,4 @@ static void i2c_nrf5_config_func_1(struct device *dev)
|
|||
|
||||
irq_enable(NRF5_IRQ_SPI1_TWI1_IRQn);
|
||||
}
|
||||
#endif /* CONFIG_I2C_1 */
|
||||
#endif /* CONFIG_I2C_1 && !CONFIG_SPI_1 */
|
||||
|
|
|
@ -265,4 +265,6 @@ source "drivers/spi/Kconfig.dw"
|
|||
|
||||
source "drivers/spi/Kconfig.mcux_dspi"
|
||||
|
||||
source "drivers/spi/Kconfig.nrf5"
|
||||
|
||||
endif # SPI
|
||||
|
|
185
drivers/spi/Kconfig.nrf5
Normal file
185
drivers/spi/Kconfig.nrf5
Normal file
|
@ -0,0 +1,185 @@
|
|||
# Kconfig - nrf5 series MDK SPI support
|
||||
#
|
||||
# Copyright (c) 2017, Intel Corp.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# TODO add nrf51 and nrf5 slave spi (spis)
|
||||
|
||||
menuconfig SPI_NRF5
|
||||
bool "nRF5 SPI drivers"
|
||||
depends on SPI && SOC_FAMILY_NRF5 && GPIO_NRF5_P0
|
||||
default n
|
||||
help
|
||||
Enable support for nRF52 MCU series EasyDMA SPI driver. Peripherals
|
||||
with the same instance id can not be used together. eg SPIM0 and I2C_0
|
||||
(TWIM0) and SPIS0. You may need to disable I2C_0 or I2C_1.
|
||||
|
||||
if SPI_NRF5
|
||||
|
||||
# nordic twiX0, spiX0, spi0 instances can not be used at the same time
|
||||
if SPI_0 && !I2C_0
|
||||
|
||||
choice
|
||||
prompt "SPI Port 0 Driver type"
|
||||
optional
|
||||
|
||||
config SPIM0_NRF52
|
||||
bool "nRF52 SPIM0"
|
||||
depends on SOC_SERIES_NRF52X
|
||||
help
|
||||
nRF52 SPI Master with EasyDMA on port 0
|
||||
|
||||
endchoice
|
||||
|
||||
if SPIM0_NRF52
|
||||
|
||||
config SPIM0_NRF52_GPIO_SCK_PIN
|
||||
int "SCK pin number"
|
||||
range 0 31
|
||||
help
|
||||
GPIO pin number for SCK
|
||||
|
||||
config SPIM0_NRF52_GPIO_MOSI_PIN
|
||||
int "MOSI pin number"
|
||||
range 0 31
|
||||
help
|
||||
GPIO pin number to use for MOSI
|
||||
|
||||
config SPIM0_NRF52_GPIO_MISO_PIN
|
||||
int "MISO pin number"
|
||||
range 0 31
|
||||
help
|
||||
GPIO pin number for MISO
|
||||
|
||||
config SPIM0_NRF52_GPIO_SS_PIN_0
|
||||
int "CS0 pin number"
|
||||
range 0 255
|
||||
default 255
|
||||
help
|
||||
Slave Select (Chip Select) gpio pin number for line n. Not used value
|
||||
is 255 (0xff).
|
||||
|
||||
config SPIM0_NRF52_GPIO_SS_PIN_1
|
||||
int "CS1 pin number"
|
||||
range 0 255
|
||||
default 255
|
||||
help
|
||||
Slave Select (Chip Select) gpio pin number for line n. Not used value
|
||||
is 255 (0xff).
|
||||
|
||||
config SPIM0_NRF52_GPIO_SS_PIN_2
|
||||
int "CS2 pin number"
|
||||
range 0 255
|
||||
default 255
|
||||
help
|
||||
Slave Select (Chip Select) gpio pin number for line n. Not used value
|
||||
is 255 (0xff).
|
||||
|
||||
config SPIM0_NRF52_GPIO_SS_PIN_3
|
||||
int "CS3 pin number"
|
||||
range 0 255
|
||||
default 255
|
||||
help
|
||||
Slave Select (Chip Select) gpio pin number for line n. Not used value
|
||||
is 255 (0xff).
|
||||
|
||||
config SPIM0_NRF52_ORC
|
||||
hex "Over Read Character"
|
||||
default 0x00
|
||||
range 0x00 0xff
|
||||
help
|
||||
This option configures what value to send when the tx char count is
|
||||
less than the rx count.
|
||||
|
||||
endif # SPIM0_NRF52
|
||||
|
||||
endif # SPI_0 && !I2C_0
|
||||
|
||||
# nordic twiX1, spiX1, spi1 instances can not be use at the same time
|
||||
if SPI_1 && !I2C_1
|
||||
|
||||
choice
|
||||
prompt "SPI Port 1 Driver type"
|
||||
optional
|
||||
|
||||
config SPIM1_NRF52
|
||||
bool "nRF52 SPIM1"
|
||||
depends on SOC_SERIES_NRF52X
|
||||
help
|
||||
nRF52 SPI Master with EasyDMA on port 0
|
||||
|
||||
endchoice
|
||||
|
||||
if SPIM1_NRF52
|
||||
|
||||
config SPIM1_NRF52_GPIO_SCK_PIN
|
||||
int "SCK pin number"
|
||||
range 0 31
|
||||
help
|
||||
GPIO pin number for SCK
|
||||
|
||||
config SPIM1_NRF52_GPIO_MOSI_PIN
|
||||
int "MOSI pin number"
|
||||
range 0 31
|
||||
help
|
||||
GPIO pin number to use for MOSI
|
||||
|
||||
config SPIM1_NRF52_GPIO_MISO_PIN
|
||||
int "MISO pin number"
|
||||
range 0 31
|
||||
help
|
||||
GPIO pin number for MISO
|
||||
|
||||
config SPIM1_NRF52_GPIO_SS_PIN_0
|
||||
int "CS0 pin number"
|
||||
range 0 255
|
||||
default 255
|
||||
help
|
||||
Slave Select (Chip Select) gpio pin number for line n. Not used value
|
||||
is 255 (0xff).
|
||||
|
||||
config SPIM1_NRF52_GPIO_SS_PIN_1
|
||||
int "CS1 pin number"
|
||||
range 0 255
|
||||
default 255
|
||||
help
|
||||
Slave Select (Chip Select) gpio pin number for line n. Not used value
|
||||
is 255 (0xff).
|
||||
|
||||
config SPIM1_NRF52_GPIO_SS_PIN_2
|
||||
int "CS2 pin number"
|
||||
range 0 255
|
||||
default 255
|
||||
help
|
||||
Slave Select (Chip Select) gpio pin number for line n. Not used value
|
||||
is 255 (0xff).
|
||||
|
||||
config SPIM1_NRF52_GPIO_SS_PIN_3
|
||||
int "CS3 pin number"
|
||||
range 0 255
|
||||
default 255
|
||||
help
|
||||
Slave Select (Chip Select) gpio pin number for line n. Not used value
|
||||
is 255 (0xff).
|
||||
|
||||
config SPIM1_NRF52_ORC
|
||||
hex "Over Read Character"
|
||||
default 0x00
|
||||
range 0x00 0xff
|
||||
help
|
||||
This option configures what value to send when the tx char count is
|
||||
less than the rx count.
|
||||
|
||||
endif # SPIM1_NRF52
|
||||
|
||||
endif # SPI_1 && !I2C_1
|
||||
|
||||
# hidden compile option
|
||||
config SPIM_NRF52
|
||||
bool
|
||||
depends on !I2C_0 || !I2C_1
|
||||
default y if (SPIM0_NRF52 || SPIM1_NRF52)
|
||||
|
||||
endif # SPI_NRF5
|
|
@ -1,5 +1,6 @@
|
|||
obj-$(CONFIG_SPI_INTEL) += spi_intel.o
|
||||
obj-$(CONFIG_SPI_DW) += spi_dw.o
|
||||
obj-$(CONFIG_SPI_MCUX_DSPI) += spi_mcux_dspi.o
|
||||
obj-$(CONFIG_SPIM_NRF52) += spim_nrf52.o
|
||||
obj-$(CONFIG_SPI_QMSI) += spi_qmsi.o
|
||||
obj-$(CONFIG_SPI_QMSI_SS) += spi_qmsi_ss.o
|
||||
|
|
448
drivers/spi/spim_nrf52.c
Normal file
448
drivers/spi/spim_nrf52.c
Normal file
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corp.
|
||||
*
|
||||
* SPDX-License-Identifier:0xApache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* #define CONFIG_ASSERT
|
||||
* #define __ASSERT_ON 1
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <spi.h>
|
||||
#include <soc.h>
|
||||
#include <nrf.h>
|
||||
#include <misc/util.h>
|
||||
#include <gpio.h>
|
||||
|
||||
#define SYS_LOG_DOMAIN "spim"
|
||||
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL
|
||||
#include <logging/sys_log.h>
|
||||
|
||||
/* @todo
|
||||
*
|
||||
* Add support for 52840 spim2.
|
||||
*/
|
||||
|
||||
struct spim_nrf52_config {
|
||||
volatile NRF_SPIM_Type *base;
|
||||
void (*irq_config_func)(struct device *dev);
|
||||
struct spi_config default_cfg;
|
||||
struct {
|
||||
uint8_t sck;
|
||||
uint8_t mosi;
|
||||
uint8_t miso;
|
||||
#define SS_UNUSED 255
|
||||
/* Pin number of up to 4 slave devices */
|
||||
uint8_t ss[4];
|
||||
} psel;
|
||||
uint8_t orc;
|
||||
};
|
||||
|
||||
struct spim_nrf52_data {
|
||||
struct k_sem sem;
|
||||
struct device *gpio_port;
|
||||
uint8_t slave;
|
||||
uint8_t stopped:1;
|
||||
uint8_t txd:1;
|
||||
uint8_t rxd:1;
|
||||
#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_INFO)
|
||||
uint32_t tx_cnt;
|
||||
uint32_t rx_cnt;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define NRF52_SPIM_INT_END SPIM_INTENSET_END_Msk
|
||||
#define NRF52_SPIM_INT_ENDRX SPIM_INTENSET_ENDRX_Msk
|
||||
#define NRF52_SPIM_INT_ENDTX SPIM_INTENSET_ENDTX_Msk
|
||||
#define NRF52_SPIM_ENABLE SPIM_ENABLE_ENABLE_Enabled
|
||||
#define NRF52_SPIM_DISABLE SPIM_ENABLE_ENABLE_Disabled
|
||||
|
||||
static void spim_nrf52_print_cfg_registers(struct device *dev)
|
||||
{
|
||||
const struct spim_nrf52_config *config = dev->config->config_info;
|
||||
volatile NRF_SPIM_Type *spim = config->base;
|
||||
|
||||
SYS_LOG_DBG("\n"
|
||||
"SHORTS=0x%x INT=0x%x FREQUENCY=0x%x CONFIG=0x%x\n"
|
||||
"ENABLE=0x%x SCKPIN=%d MISOPIN=%d MOSIPIN=%d\n"
|
||||
"RXD.(PTR=0x%x MAXCNT=0x%x AMOUNT=0x%x)\n"
|
||||
"TXD.(PTR=0x%x MAXCNT=0x%x AMOUNT=0x%x)\n",
|
||||
spim->SHORTS, spim->INTENSET, spim->FREQUENCY, spim->CONFIG,
|
||||
spim->ENABLE, spim->PSEL.SCK, spim->PSEL.MISO, spim->PSEL.MOSI,
|
||||
spim->RXD.PTR, spim->RXD.MAXCNT, spim->RXD.AMOUNT,
|
||||
spim->TXD.PTR, spim->TXD.MAXCNT, spim->TXD.AMOUNT);
|
||||
|
||||
/* maybe unused */
|
||||
(void)spim;
|
||||
}
|
||||
|
||||
static int spim_nrf52_configure(struct device *dev,
|
||||
struct spi_config *spi_config)
|
||||
{
|
||||
const struct spim_nrf52_config *config = dev->config->config_info;
|
||||
struct spim_nrf52_data *data = dev->driver_data;
|
||||
volatile NRF_SPIM_Type *spim = config->base;
|
||||
uint32_t flags;
|
||||
|
||||
SYS_LOG_DBG("config=0x%x max_sys_freq=%d", spi_config->config,
|
||||
spi_config->max_sys_freq);
|
||||
|
||||
/* make sure SPIM block is off */
|
||||
spim->ENABLE = NRF52_SPIM_DISABLE;
|
||||
|
||||
spim->INTENCLR = 0xffffffffUL;
|
||||
|
||||
spim->SHORTS = 0;
|
||||
|
||||
spim->ORC = config->orc;
|
||||
|
||||
spim->TXD.LIST = 0;
|
||||
spim->RXD.LIST = 0;
|
||||
|
||||
spim->TXD.MAXCNT = 0;
|
||||
spim->RXD.MAXCNT = 0;
|
||||
|
||||
spim->EVENTS_END = 0;
|
||||
spim->EVENTS_ENDTX = 0;
|
||||
spim->EVENTS_ENDRX = 0;
|
||||
spim->EVENTS_STOPPED = 0;
|
||||
spim->EVENTS_STARTED = 0;
|
||||
|
||||
data->stopped = 1;
|
||||
data->txd = 0;
|
||||
data->rxd = 0;
|
||||
#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_INFO)
|
||||
data->tx_cnt = 0;
|
||||
data->rx_cnt = 0;
|
||||
#endif
|
||||
|
||||
switch (spi_config->max_sys_freq) {
|
||||
case 125000:
|
||||
spim->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_K125;
|
||||
break;
|
||||
case 250000:
|
||||
spim->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_K250;
|
||||
break;
|
||||
case 500000:
|
||||
spim->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_K500;
|
||||
break;
|
||||
case 1000000:
|
||||
spim->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_M1;
|
||||
break;
|
||||
case 2000000:
|
||||
spim->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_M2;
|
||||
break;
|
||||
case 4000000:
|
||||
spim->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_M4;
|
||||
break;
|
||||
case 8000000:
|
||||
spim->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_M8;
|
||||
default:
|
||||
SYS_LOG_ERR("unsupported frequency sck=%d\n",
|
||||
spi_config->max_sys_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flags = spi_config->config;
|
||||
|
||||
/* nrf5 supports only 8 bit word size */
|
||||
if (SPI_WORD_SIZE_GET(flags) != 8) {
|
||||
SYS_LOG_ERR("unsupported word size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (flags & SPI_MODE_LOOP) {
|
||||
SYS_LOG_ERR("loopback unsupported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spim->CONFIG = (flags & SPI_TRANSFER_LSB) ? SPIM_CONFIG_ORDER_LsbFirst
|
||||
: SPIM_CONFIG_ORDER_MsbFirst;
|
||||
spim->CONFIG |= (flags & SPI_MODE_CPOL) ? SPIM_CONFIG_CPOL_ActiveLow
|
||||
: SPIM_CONFIG_CPOL_ActiveHigh;
|
||||
spim->CONFIG |= (flags & SPI_MODE_CPHA) ? SPIM_CONFIG_CPHA_Trailing
|
||||
: SPIM_CONFIG_CPHA_Leading;
|
||||
|
||||
spim->INTENSET = NRF52_SPIM_INT_END;
|
||||
|
||||
spim_nrf52_print_cfg_registers(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spim_nrf52_slave_select(struct device *dev, uint32_t slave)
|
||||
{
|
||||
struct spim_nrf52_data *data = dev->driver_data;
|
||||
const struct spim_nrf52_config *config = dev->config->config_info;
|
||||
|
||||
__ASSERT((slave > 0) && (slave <= 4), "slave=%d", slave);
|
||||
|
||||
slave--;
|
||||
|
||||
if (config->psel.ss[slave] == SS_UNUSED) {
|
||||
SYS_LOG_ERR("Slave %d is not configured\n", slave);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data->slave = slave;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void spim_nrf52_csn(struct device *gpio_port, uint32_t pin,
|
||||
bool select)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = gpio_pin_write(gpio_port, pin, select ? 0x0 : 0x1);
|
||||
__ASSERT_NO_MSG(status == 0);
|
||||
}
|
||||
|
||||
static int spim_nrf52_transceive(struct device *dev, const void *tx_buf,
|
||||
uint32_t tx_buf_len, void *rx_buf,
|
||||
uint32_t rx_buf_len)
|
||||
{
|
||||
const struct spim_nrf52_config *config = dev->config->config_info;
|
||||
struct spim_nrf52_data *data = dev->driver_data;
|
||||
volatile NRF_SPIM_Type *spim = config->base;
|
||||
|
||||
SYS_LOG_DBG("transceive tx_buf=0x%p rx_buf=0x%p tx_len=0x%x "
|
||||
"rx_len=0x%x\n", tx_buf, rx_buf, tx_buf_len, rx_buf_len);
|
||||
|
||||
if (spim->ENABLE) {
|
||||
return -EALREADY;
|
||||
}
|
||||
spim->ENABLE = NRF52_SPIM_ENABLE;
|
||||
|
||||
__ASSERT_NO_MSG(data->stopped);
|
||||
data->stopped = 0;
|
||||
|
||||
if (tx_buf_len) {
|
||||
__ASSERT_NO_MSG(tx_buf);
|
||||
spim->TXD.MAXCNT = tx_buf_len;
|
||||
spim->TXD.PTR = (uint32_t)tx_buf;
|
||||
data->txd = 0;
|
||||
#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_INFO)
|
||||
data->tx_cnt = 0;
|
||||
#endif
|
||||
} else {
|
||||
spim->TXD.MAXCNT = 0;
|
||||
}
|
||||
|
||||
if (rx_buf_len) {
|
||||
__ASSERT_NO_MSG(rx_buf);
|
||||
spim->RXD.MAXCNT = rx_buf_len;
|
||||
spim->RXD.PTR = (uint32_t)rx_buf;
|
||||
data->rxd = 0;
|
||||
#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_INFO)
|
||||
data->rx_cnt = 0;
|
||||
#endif
|
||||
} else {
|
||||
spim->RXD.MAXCNT = 0;
|
||||
}
|
||||
|
||||
if (data->slave != SS_UNUSED) {
|
||||
spim_nrf52_csn(data->gpio_port, config->psel.ss[data->slave],
|
||||
true);
|
||||
}
|
||||
|
||||
spim->INTENSET = NRF52_SPIM_INT_END;
|
||||
|
||||
SYS_LOG_DBG("spi_xfer %s/%s CS%d\n", rx_buf_len ? "R" : "-",
|
||||
tx_buf_len ? "W" : "-", data->slave);
|
||||
|
||||
/* start SPI transfer transaction */
|
||||
spim->TASKS_START = 1;
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
k_sem_take(&data->sem, K_FOREVER);
|
||||
|
||||
if (data->slave != SS_UNUSED) {
|
||||
spim_nrf52_csn(data->gpio_port, config->psel.ss[data->slave],
|
||||
false);
|
||||
}
|
||||
|
||||
/* Disable SPIM block for power saving */
|
||||
spim->INTENCLR = 0xffffffffUL;
|
||||
spim->ENABLE = NRF52_SPIM_DISABLE;
|
||||
|
||||
#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_INFO)
|
||||
SYS_LOG_DBG("xfer complete rx_cnt=0x%x tx_cnt=0x%x rxd=%d txd=%d "
|
||||
"stopped=%d\n", data->rx_cnt, data->tx_cnt, data->rxd,
|
||||
data->txd, data->stopped);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spim_nrf52_isr(void *arg)
|
||||
{
|
||||
struct device *dev = arg;
|
||||
const struct spim_nrf52_config *config = dev->config->config_info;
|
||||
struct spim_nrf52_data *data = dev->driver_data;
|
||||
volatile NRF_SPIM_Type *spim = config->base;
|
||||
|
||||
if (spim->EVENTS_END) {
|
||||
data->rxd = 1;
|
||||
data->txd = 1;
|
||||
|
||||
/* assume spi transaction has stopped */
|
||||
data->stopped = 1;
|
||||
|
||||
/* Cortex M4 specific EVENTS register clearing requires 4 cycles
|
||||
* delayto avoid re-triggering of interrupt. Call to
|
||||
* k_sem_give() will ensure this limit.
|
||||
*/
|
||||
spim->EVENTS_END = 0;
|
||||
|
||||
#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_INFO)
|
||||
data->rx_cnt = spim->RXD.AMOUNT;
|
||||
data->tx_cnt = spim->TXD.AMOUNT;
|
||||
SYS_LOG_DBG("endrxtx rx_cnt=%d tx_cnt=%d", data->rx_cnt,
|
||||
data->tx_cnt);
|
||||
#endif
|
||||
k_sem_give(&data->sem);
|
||||
}
|
||||
}
|
||||
|
||||
static int spim_nrf52_init(struct device *dev)
|
||||
{
|
||||
const struct spim_nrf52_config *config = dev->config->config_info;
|
||||
struct spim_nrf52_data *data = dev->driver_data;
|
||||
volatile NRF_SPIM_Type *spim = config->base;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
SYS_LOG_DBG("%s", dev->config->name);
|
||||
|
||||
data->gpio_port = device_get_binding(CONFIG_GPIO_NRF5_P0_DEV_NAME);
|
||||
|
||||
k_sem_init(&data->sem, 0, UINT_MAX);
|
||||
|
||||
for (i = 0; i < sizeof(config->psel.ss); i++) {
|
||||
if (config->psel.ss[i] != SS_UNUSED) {
|
||||
status = gpio_pin_configure(data->gpio_port,
|
||||
config->psel.ss[i],
|
||||
GPIO_DIR_OUT);
|
||||
__ASSERT_NO_MSG(status == 0);
|
||||
|
||||
spim_nrf52_csn(data->gpio_port, config->psel.ss[i],
|
||||
false);
|
||||
SYS_LOG_DBG("CS%d=%d\n", i, config->psel.ss[i]);
|
||||
}
|
||||
}
|
||||
|
||||
data->slave = SS_UNUSED;
|
||||
|
||||
status = gpio_pin_configure(data->gpio_port, config->psel.sck,
|
||||
GPIO_DIR_OUT);
|
||||
__ASSERT_NO_MSG(status == 0);
|
||||
|
||||
status = gpio_pin_configure(data->gpio_port, config->psel.mosi,
|
||||
GPIO_DIR_OUT);
|
||||
__ASSERT_NO_MSG(status == 0);
|
||||
|
||||
status = gpio_pin_configure(data->gpio_port, config->psel.miso,
|
||||
GPIO_DIR_IN);
|
||||
__ASSERT_NO_MSG(status == 0);
|
||||
|
||||
spim->PSEL.SCK = config->psel.sck;
|
||||
spim->PSEL.MOSI = config->psel.mosi;
|
||||
spim->PSEL.MISO = config->psel.miso;
|
||||
|
||||
status = spim_nrf52_configure(dev, (void *)&config->default_cfg);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
config->irq_config_func(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_driver_api spim_nrf52_driver_api = {
|
||||
.configure = spim_nrf52_configure,
|
||||
.slave_select = spim_nrf52_slave_select,
|
||||
.transceive = spim_nrf52_transceive,
|
||||
};
|
||||
|
||||
/* i2c & spi (SPIM, SPIS, SPI) instance with the same id (e.g. I2C_0 and SPI_0)
|
||||
* can NOT be used at the same time on nRF5x chip family.
|
||||
*/
|
||||
#if defined(CONFIG_SPIM0_NRF52) && !defined(CONFIG_I2C_0)
|
||||
static void spim_nrf52_config_func_0(struct device *dev);
|
||||
|
||||
static const struct spim_nrf52_config spim_nrf52_config_0 = {
|
||||
.base = NRF_SPIM0,
|
||||
.irq_config_func = spim_nrf52_config_func_0,
|
||||
.default_cfg = {
|
||||
.config = CONFIG_SPI_0_DEFAULT_CFG,
|
||||
.max_sys_freq = CONFIG_SPI_0_DEFAULT_BAUD_RATE,
|
||||
},
|
||||
.psel = {
|
||||
.sck = CONFIG_SPIM0_NRF52_GPIO_SCK_PIN,
|
||||
.mosi = CONFIG_SPIM0_NRF52_GPIO_MOSI_PIN,
|
||||
.miso = CONFIG_SPIM0_NRF52_GPIO_MISO_PIN,
|
||||
.ss = { CONFIG_SPIM0_NRF52_GPIO_SS_PIN_0,
|
||||
CONFIG_SPIM0_NRF52_GPIO_SS_PIN_1,
|
||||
CONFIG_SPIM0_NRF52_GPIO_SS_PIN_2,
|
||||
CONFIG_SPIM0_NRF52_GPIO_SS_PIN_3 },
|
||||
},
|
||||
.orc = CONFIG_SPIM0_NRF52_ORC,
|
||||
};
|
||||
|
||||
static struct spim_nrf52_data spim_nrf52_data_0;
|
||||
|
||||
DEVICE_AND_API_INIT(spim_nrf52_0, CONFIG_SPI_0_NAME, spim_nrf52_init,
|
||||
&spim_nrf52_data_0, &spim_nrf52_config_0,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
&spim_nrf52_driver_api);
|
||||
|
||||
static void spim_nrf52_config_func_0(struct device *dev)
|
||||
{
|
||||
IRQ_CONNECT(NRF5_IRQ_SPI0_TWI0_IRQn, CONFIG_SPI_0_IRQ_PRI,
|
||||
spim_nrf52_isr, DEVICE_GET(spim_nrf52_0), 0);
|
||||
|
||||
irq_enable(NRF5_IRQ_SPI0_TWI0_IRQn);
|
||||
}
|
||||
#endif /* CONFIG_SPIM0_NRF52 && !CONFIG_I2C_0 */
|
||||
|
||||
#if defined(CONFIG_SPIM1_NRF52) && !defined(CONFIG_I2C_1)
|
||||
static void spim_nrf52_config_func_1(struct device *dev);
|
||||
|
||||
static const struct spim_nrf52_config spim_nrf52_config_1 = {
|
||||
.base = NRF_SPIM1,
|
||||
.irq_config_func = spim_nrf52_config_func_1,
|
||||
.default_cfg = {
|
||||
.config = CONFIG_SPI_1_DEFAULT_CFG,
|
||||
.max_sys_freq = CONFIG_SPI_1_DEFAULT_BAUD_RATE,
|
||||
},
|
||||
.psel = {
|
||||
.sck = CONFIG_SPIM1_NRF52_GPIO_SCK_PIN,
|
||||
.mosi = CONFIG_SPIM1_NRF52_GPIO_MOSI_PIN,
|
||||
.miso = CONFIG_SPIM1_NRF52_GPIO_MISO_PIN,
|
||||
.ss = { CONFIG_SPIM1_NRF52_GPIO_SS_PIN_0,
|
||||
CONFIG_SPIM1_NRF52_GPIO_SS_PIN_1,
|
||||
CONFIG_SPIM1_NRF52_GPIO_SS_PIN_2,
|
||||
CONFIG_SPIM1_NRF52_GPIO_SS_PIN_3 },
|
||||
},
|
||||
.orc = CONFIG_SPIM0_NRF52_ORC,
|
||||
};
|
||||
|
||||
static struct spim_nrf52_data spim_nrf52_data_1;
|
||||
|
||||
DEVICE_AND_API_INIT(spim_nrf52_1, CONFIG_SPI_1_NAME, spim_nrf52_init,
|
||||
&spim_nrf52_data_1, &spim_nrf52_config_1,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
&spim_nrf52_driver_api);
|
||||
|
||||
static void spim_nrf52_config_func_1(struct device *dev)
|
||||
{
|
||||
IRQ_CONNECT(NRF5_IRQ_SPI1_TWI1_IRQn, CONFIG_SPI_1_IRQ_PRI,
|
||||
spim_nrf52_isr, DEVICE_GET(spim_nrf52_1), 0);
|
||||
|
||||
irq_enable(NRF5_IRQ_SPI1_TWI1_IRQn);
|
||||
}
|
||||
#endif /* CONFIG_SPIM1_NRF52 && !CONFIG_I2C_1 */
|
Loading…
Add table
Add a link
Reference in a new issue