diff --git a/arch/arc/soc/quark_se_c1000_ss/Kconfig.defconfig b/arch/arc/soc/quark_se_c1000_ss/Kconfig.defconfig index 22d9acd18884..ba2949591c25 100644 --- a/arch/arc/soc/quark_se_c1000_ss/Kconfig.defconfig +++ b/arch/arc/soc/quark_se_c1000_ss/Kconfig.defconfig @@ -218,54 +218,60 @@ endif # UART_QMSI if SPI -config SPI_QMSI - def_bool n - -if SPI_QMSI -config SPI_0 +config SPI_DW def_bool y -config SPI_0_NAME - default "SPI_2" +if SPI_DW -config SPI_0_IRQ_PRI - default 1 +config SPI_DW_FIFO_DEPTH + default 7 -config SPI_1 +config CLOCK_CONTROL def_bool y -config SPI_1_NAME - default "SPI_3" - -config SPI_1_IRQ_PRI - default 1 +config CLOCK_CONTROL_QUARK_SE + def_bool y -endif +config CLOCK_CONTROL_QUARK_SE_SENSOR + def_bool y -config SPI_QMSI_SS +config SPI_0 def_bool y -if SPI_QMSI_SS -config SPI_SS_0 +config SPI_DW_PORT_0_INTERRUPT_SINGLE_LINE + def_bool n + +config SPI_DW_PORT_0_CLOCK_GATE def_bool y -config SPI_SS_0_NAME - default "SPI_0" +config SPI_DW_PORT_0_CLOCK_GATE_DRV_NAME + default CLOCK_CONTROL_QUARK_SE_SENSOR_DRV_NAME + +config SPI_DW_PORT_0_CLOCK_GATE_SUBSYS + default 3 -config SPI_SS_0_IRQ_PRI +config SPI_0_IRQ_PRI default 1 -config SPI_SS_1 +config SPI_1 def_bool y -config SPI_SS_1_NAME - default "SPI_1" +config SPI_DW_PORT_1_INTERRUPT_SINGLE_LINE + def_bool n -config SPI_SS_1_IRQ_PRI - default 1 +config SPI_DW_PORT_1_CLOCK_GATE + def_bool y -endif +config SPI_DW_PORT_1_CLOCK_GATE_DRV_NAME + default CLOCK_CONTROL_QUARK_SE_SENSOR_DRV_NAME + +config SPI_DW_PORT_1_CLOCK_GATE_SUBSYS + default 4 + +config SPI_1_IRQ_PRI + default 1 +endif # SPI_DW endif # SPI if AIO_COMPARATOR diff --git a/arch/arc/soc/quark_se_c1000_ss/soc.h b/arch/arc/soc/quark_se_c1000_ss/soc.h index c7a56186fa16..3c58ca64b99d 100644 --- a/arch/arc/soc/quark_se_c1000_ss/soc.h +++ b/arch/arc/soc/quark_se_c1000_ss/soc.h @@ -175,18 +175,37 @@ * SPI */ -#define SPI_DW_PORT_0_REGS 0x80010000 -#define SPI_DW_PORT_1_REGS 0x80010100 +#ifdef CONFIG_SPI_DW -#define SPI_DW_PORT_0_ERROR_INT_MASK (SCSS_REGISTER_BASE + 0x430) -#define SPI_DW_PORT_0_RX_INT_MASK (SCSS_REGISTER_BASE + 0x434) -#define SPI_DW_PORT_0_TX_INT_MASK (SCSS_REGISTER_BASE + 0x438) +#define SPI_DW_PORT_0_REGS 0x80010000 +#define SPI_DW_PORT_1_REGS 0x80010100 -#define SPI_DW_PORT_1_ERROR_INT_MASK (SCSS_REGISTER_BASE + 0x43C) -#define SPI_DW_PORT_1_RX_INT_MASK (SCSS_REGISTER_BASE + 0x440) -#define SPI_DW_PORT_1_TX_INT_MASK (SCSS_REGISTER_BASE + 0x444) +#define SPI_DW_PORT_0_ERROR_INT_MASK (SCSS_REGISTER_BASE + 0x430) +#define SPI_DW_PORT_0_RX_INT_MASK (SCSS_REGISTER_BASE + 0x434) +#define SPI_DW_PORT_0_TX_INT_MASK (SCSS_REGISTER_BASE + 0x438) -#define SPI_DW_IRQ_FLAGS 0 +#define SPI_DW_PORT_1_ERROR_INT_MASK (SCSS_REGISTER_BASE + 0x43C) +#define SPI_DW_PORT_1_RX_INT_MASK (SCSS_REGISTER_BASE + 0x440) +#define SPI_DW_PORT_1_TX_INT_MASK (SCSS_REGISTER_BASE + 0x444) + +#define SPI_DW_IRQ_FLAGS 0 + +#define SPI_DW_PORT_2_REGS 0xB0001000 +#define SPI_DW_PORT_2_IRQ IRQ_SPI_MST0_INTR +#define SPI_DW_PORT_2_INT_MASK (SCSS_REGISTER_BASE + 0x454) + +#define SPI_DW_PORT_3_REGS 0xB0001400 +#define SPI_DW_PORT_3_IRQ IRQ_SPI_MST1_INTR +#define SPI_DW_PORT_3_INT_MASK (SCSS_REGISTER_BASE + 0x458) + +#endif /* CONFIG_SPI_DW */ + +/* Clock */ +#define CLOCK_PERIPHERAL_BASE_ADDR (SCSS_REGISTER_BASE + 0x18) +#define CLOCK_EXTERNAL_BASE_ADDR (SCSS_REGISTER_BASE + 0x24) +#define CLOCK_SENSOR_BASE_ADDR (SCSS_REGISTER_BASE + 0x28) +#define CLOCK_SYSTEM_CLOCK_CONTROL (SCSS_REGISTER_BASE + \ + SCSS_CCU_SYS_CLK_CTL) static inline void _quark_se_ss_ready(void) { diff --git a/arch/arm/soc/st_stm32/common/Kconfig.defconfig.series b/arch/arm/soc/st_stm32/common/Kconfig.defconfig.series index 1338b5943f29..cee389f9e2fd 100644 --- a/arch/arm/soc/st_stm32/common/Kconfig.defconfig.series +++ b/arch/arm/soc/st_stm32/common/Kconfig.defconfig.series @@ -56,9 +56,6 @@ if SPI && (SPI_1 || SPI_2 || SPI_3) config SPI_STM32 def_bool y -config SPI_LEGACY_API - def_bool n - endif # SPI if I2C && (I2C_1 || I2C_2 || I2C_3) diff --git a/arch/x86/soc/intel_quark/quark_d2000/Kconfig.defconfig.series b/arch/x86/soc/intel_quark/quark_d2000/Kconfig.defconfig.series index 00142a2cb95c..2b45c7f14d18 100644 --- a/arch/x86/soc/intel_quark/quark_d2000/Kconfig.defconfig.series +++ b/arch/x86/soc/intel_quark/quark_d2000/Kconfig.defconfig.series @@ -141,8 +141,10 @@ config DMA_QMSI endif if SPI -config SPI_QMSI +config SPI_DW def_bool y +config SPI_DW_FIFO_DEPTH + default 7 config SPI_0 def_bool y config SPI_0_IRQ_PRI diff --git a/arch/x86/soc/intel_quark/quark_d2000/soc.h b/arch/x86/soc/intel_quark/quark_d2000/soc.h index a6dea6d5b943..36d3b16bf47f 100644 --- a/arch/x86/soc/intel_quark/quark_d2000/soc.h +++ b/arch/x86/soc/intel_quark/quark_d2000/soc.h @@ -46,4 +46,14 @@ #define UART_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_HIGH) +#ifdef CONFIG_SPI_DW + +#define SPI_DW_PORT_0_REGS 0xB0001000 +#define SPI_DW_PORT_0_IRQ 2 +#define SPI_DW_PORT_0_INT_MASK (SCSS_REGISTER_BASE + 0x454) + +#define SPI_DW_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_HIGH) + +#endif + #endif /* __SOC_H_ */ diff --git a/arch/x86/soc/intel_quark/quark_se/Kconfig.defconfig.series b/arch/x86/soc/intel_quark/quark_se/Kconfig.defconfig.series index f503b2664eb2..198cad8ec70b 100644 --- a/arch/x86/soc/intel_quark/quark_se/Kconfig.defconfig.series +++ b/arch/x86/soc/intel_quark/quark_se/Kconfig.defconfig.series @@ -141,7 +141,7 @@ endif if SPI -config SPI_QMSI +config SPI_DW def_bool y config SPI_0 @@ -156,12 +156,22 @@ config SPI_1 config SPI_1_IRQ_PRI default 2 -config SPI_DW - def_bool n - config SPI_DW_FIFO_DEPTH default 7 +if SPI_SLAVE + +config SPI_2 + def_bool y + +config SPI_2_OP_MODES + default 2 + +config SPI_2_IRQ_PRI + default 2 + +endif # SPI_SLAVE + endif # SPI diff --git a/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto_defconfig b/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto_defconfig index af7608444d2a..1e21d77afb46 100644 --- a/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto_defconfig +++ b/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto_defconfig @@ -17,7 +17,6 @@ CONFIG_SOC_ATMEL_SAMD_XOSC32K=y CONFIG_SOC_ATMEL_SAMD_XOSC32K_AS_MAIN=y CONFIG_SPI=y CONFIG_SPI_SAM0=y -CONFIG_SPI_LEGACY_API=n CONFIG_PINMUX=y CONFIG_PINMUX_SAM0=y CONFIG_USB=y diff --git a/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0_defconfig b/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0_defconfig index d21017ac9998..668e91cc06a1 100644 --- a/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0_defconfig +++ b/boards/arm/adafruit_trinket_m0/adafruit_trinket_m0_defconfig @@ -16,7 +16,6 @@ CONFIG_WATCHDOG=y CONFIG_WDT_SAM0=y CONFIG_SPI=y CONFIG_SPI_SAM0=y -CONFIG_SPI_LEGACY_API=n CONFIG_PINMUX=y CONFIG_PINMUX_SAM0=y CONFIG_USB=y diff --git a/boards/arm/arduino_zero/arduino_zero_defconfig b/boards/arm/arduino_zero/arduino_zero_defconfig index 64a8fad29d7c..6021449d0e48 100644 --- a/boards/arm/arduino_zero/arduino_zero_defconfig +++ b/boards/arm/arduino_zero/arduino_zero_defconfig @@ -17,7 +17,7 @@ CONFIG_SOC_ATMEL_SAMD_XOSC32K=y CONFIG_SOC_ATMEL_SAMD_XOSC32K_AS_MAIN=y CONFIG_SPI=y CONFIG_SPI_SAM0=y -CONFIG_SPI_LEGACY_API=n +CONFIG_SPI_4=y CONFIG_PINMUX=y CONFIG_PINMUX_SAM0=y CONFIG_USB=y diff --git a/boards/x86/galileo/Kconfig.defconfig b/boards/x86/galileo/Kconfig.defconfig index 5b1ddb08a6c0..9324d12bc143 100644 --- a/boards/x86/galileo/Kconfig.defconfig +++ b/boards/x86/galileo/Kconfig.defconfig @@ -19,33 +19,12 @@ config PWM config SPI def_bool y -config ADC - def_bool y - config SHARED_IRQ def_bool y config PCI_ENUMERATION def_bool y -if ADC - -config ADC_TI_ADC108S102 - def_bool y - -if ADC_TI_ADC108S102 - -config ADC_TI_ADC108S102_SPI_PORT_NAME - default "SPI_0" -config ADC_TI_ADC108S102_SPI_CONFIGURATION - default 0x81 -config ADC_TI_ADC108S102_SPI_MAX_FREQ - default 0x20000000 - -endif # ADC_TI_AC108S102 - -endif # ADC - if GPIO && I2C config GPIO_PCAL9535A @@ -131,7 +110,4 @@ config SPI_INIT_PRIORITY config PINMUX_INIT_PRIORITY default 80 if PINMUX -config ADC_INIT_PRIORITY - default 95 - endif # BOARD_GALILEO diff --git a/boards/x86/quark_se_c1000_devboard/Kconfig.defconfig b/boards/x86/quark_se_c1000_devboard/Kconfig.defconfig index 42bcd71047e8..d3bea3357a58 100644 --- a/boards/x86/quark_se_c1000_devboard/Kconfig.defconfig +++ b/boards/x86/quark_se_c1000_devboard/Kconfig.defconfig @@ -23,40 +23,35 @@ if IEEE802154_CC2520 config SPI 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 @@ -64,11 +59,6 @@ if IEEE802154_CC1200 config SPI def_bool y -config SPI_QMSI - def_bool n -config SPI_DW - def_bool y - config GPIO def_bool y diff --git a/boards/x86/quark_se_c1000_devboard/pinmux.c b/boards/x86/quark_se_c1000_devboard/pinmux.c index 462eb5cd5545..80af09c142de 100644 --- a/boards/x86/quark_se_c1000_devboard/pinmux.c +++ b/boards/x86/quark_se_c1000_devboard/pinmux.c @@ -105,10 +105,17 @@ static void _pinmux_defaults(u32_t base) u32_t mux_config[PINMUX_MAX_REGISTERS] = { 0, 0, 0, 0, 0}; int i = 0; +#if defined(CONFIG_SPI_2) + PIN_CONFIG(mux_config, 0, PINMUX_FUNC_C); + PIN_CONFIG(mux_config, 1, PINMUX_FUNC_C); + PIN_CONFIG(mux_config, 2, PINMUX_FUNC_C); + PIN_CONFIG(mux_config, 3, PINMUX_FUNC_C); +#else PIN_CONFIG(mux_config, 0, PINMUX_FUNC_B); PIN_CONFIG(mux_config, 1, PINMUX_FUNC_B); PIN_CONFIG(mux_config, 2, PINMUX_FUNC_B); PIN_CONFIG(mux_config, 3, PINMUX_FUNC_B); +#endif PIN_CONFIG(mux_config, 8, PINMUX_FUNC_C); PIN_CONFIG(mux_config, 9, PINMUX_FUNC_C); PIN_CONFIG(mux_config, 16, PINMUX_FUNC_C); diff --git a/drivers/adc/Kconfig.ti_adc108s102 b/drivers/adc/Kconfig.ti_adc108s102 index ea83c12868ba..eaeeacf88542 100644 --- a/drivers/adc/Kconfig.ti_adc108s102 +++ b/drivers/adc/Kconfig.ti_adc108s102 @@ -22,17 +22,11 @@ config ADC_TI_ADC108S102_SPI_PORT_NAME help Master SPI port name through which adc108s102 chip is accessed. -config ADC_TI_ADC108S102_SPI_CONFIGURATION - hex "Master SPI port configuration" - default 0x0 - help - Master SPI port configuration flags used to access adc108s102 chip. - -config ADC_TI_ADC108S102_SPI_MAX_FREQ - hex "Master SPI port max frequency" - default 0x0 +config ADC_TI_ADC108S102_SPI_FREQ + int "Master SPI port max frequency" + default 0 help - Master SPI port maximum frequency used to access adc108s102 chip. + Master SPI port frequency used to access adc108s102 chip. config ADC_TI_ADC108S102_SPI_SLAVE int "SPI slave slot" diff --git a/drivers/adc/adc_ti_adc108s102.c b/drivers/adc/adc_ti_adc108s102.c index 32038a207aa8..17cbc1eefe2f 100644 --- a/drivers/adc/adc_ti_adc108s102.c +++ b/drivers/adc/adc_ti_adc108s102.c @@ -20,14 +20,26 @@ static inline int _ti_adc108s102_sampling(struct device *dev) { struct ti_adc108s102_data *adc = dev->driver_data; + const struct spi_buf tx_buf = { + .buf = adc->cmd_buffer, + .len = ADC108S102_CMD_BUFFER_SIZE + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1 + }; + const struct spi_buf rx_buf = { + .buf = adc->sampling_buffer, + .len = ADC108S102_SAMPLING_BUFFER_SIZE + }; + const struct spi_buf_set rx = { + .buffers = &rx_buf, + .count = 1 + }; SYS_LOG_DBG("Sampling!"); - /* SPI deals with u8_t buffers so multiplying by 2 the length */ - return spi_transceive(adc->spi, adc->cmd_buffer, - adc->cmd_buf_len * 2, - adc->sampling_buffer, - adc->sampling_buf_len * 2); + return spi_transceive(adc->spi, &adc->spi_cfg, &tx, &rx); } static inline void _ti_adc108s102_handle_result(struct device *dev) @@ -143,23 +155,10 @@ static inline int _verify_entries(struct adc_seq_table *seq_table) static int ti_adc108s102_read(struct device *dev, struct adc_seq_table *seq_table) { - const struct ti_adc108s102_config *config = dev->config->config_info; struct ti_adc108s102_data *adc = dev->driver_data; - struct spi_config spi_conf; int ret = 0; s32_t delay; - spi_conf.config = config->spi_config_flags; - spi_conf.max_sys_freq = config->spi_freq; - - if (spi_configure(adc->spi, &spi_conf)) { - return -EIO; - } - - if (spi_slave_select(adc->spi, config->spi_slave)) { - return -EIO; - } - /* Resetting all internal channel data */ memset(adc->chans, 0, ADC108S102_CHANNELS_SIZE); @@ -201,14 +200,19 @@ static const struct adc_driver_api ti_adc108s102_api = { static int ti_adc108s102_init(struct device *dev) { - const struct ti_adc108s102_config *config = dev->config->config_info; struct ti_adc108s102_data *adc = dev->driver_data; - adc->spi = device_get_binding((char *)config->spi_port); + adc->spi = device_get_binding( + CONFIG_ADC_TI_ADC108S102_SPI_PORT_NAME); if (!adc->spi) { - return -EPERM; + return -EINVAL; } + adc->spi_cfg.operation = SPI_WORD_SET(16); + adc->spi_cfg.frequency = CONFIG_ADC_TI_ADC108S102_SPI_FREQ; + adc->spi_cfg.slave = CONFIG_ADC_TI_ADC108S102_SPI_SLAVE; + + SYS_LOG_DBG("ADC108s102 initialized"); dev->driver_api = &ti_adc108s102_api; @@ -220,16 +224,9 @@ static int ti_adc108s102_init(struct device *dev) static struct ti_adc108s102_data adc108s102_data; -static const struct ti_adc108s102_config adc108s102_config = { - .spi_port = CONFIG_ADC_TI_ADC108S102_SPI_PORT_NAME, - .spi_config_flags = CONFIG_ADC_TI_ADC108S102_SPI_CONFIGURATION, - .spi_freq = CONFIG_ADC_TI_ADC108S102_SPI_MAX_FREQ, - .spi_slave = CONFIG_ADC_TI_ADC108S102_SPI_SLAVE, -}; - DEVICE_INIT(adc108s102, CONFIG_ADC_0_NAME, ti_adc108s102_init, - &adc108s102_data, &adc108s102_config, + &adc108s102_data, NULL, POST_KERNEL, CONFIG_ADC_INIT_PRIORITY); #endif /* CONFIG_ADC_TI_ADC108S102 */ diff --git a/drivers/adc/adc_ti_adc108s102.h b/drivers/adc/adc_ti_adc108s102.h index 9f5ce406cd66..7fb9d64e5df0 100644 --- a/drivers/adc/adc_ti_adc108s102.h +++ b/drivers/adc/adc_ti_adc108s102.h @@ -32,13 +32,6 @@ extern "C" { #define ADC108S102_RESULT(_res_) \ (sys_be16_to_cpu(_res_) & ADC108S102_RESULT_MASK) -struct ti_adc108s102_config { - const char *spi_port; - u32_t spi_config_flags; - u32_t spi_freq; - u32_t spi_slave; -}; - struct ti_adc108s102_chan { u32_t buf_idx; }; @@ -47,6 +40,7 @@ struct ti_adc108s102_data { u16_t cmd_buffer[ADC108S102_CMD_BUFFER_SIZE]; u16_t sampling_buffer[ADC108S102_SAMPLING_BUFFER_SIZE]; struct device *spi; + struct spi_config spi_cfg; struct ti_adc108s102_chan chans[ADC108S102_CHANNELS]; struct adc_seq_table *seq_table; diff --git a/drivers/bluetooth/hci/spi.c b/drivers/bluetooth/hci/spi.c index d2148b9c9a03..0cc1135d9147 100644 --- a/drivers/bluetooth/hci/spi.c +++ b/drivers/bluetooth/hci/spi.c @@ -46,7 +46,7 @@ #define GPIO_IRQ_PIN CONFIG_BT_SPI_IRQ_PIN #define GPIO_RESET_PIN CONFIG_BT_SPI_RESET_PIN #if defined(CONFIG_BT_SPI_BLUENRG) -#define GPIO_CS_PIN CONFIG_BT_SPI_CHIP_SELECT_PIN +#define GPIO_CS_PIN CONFIG_BT_SPI_CHIP_SELECT_PIN #endif /* CONFIG_BT_SPI_BLUENRG */ /* Max SPI buffer length for transceive operations. @@ -61,9 +61,6 @@ static u8_t rxmsg[SPI_MAX_MSG_LEN]; static u8_t txmsg[SPI_MAX_MSG_LEN]; -#if defined(CONFIG_BT_SPI_BLUENRG) -static struct device *cs_dev; -#endif /* CONFIG_BT_SPI_BLUENRG */ static struct device *irq_dev; static struct device *rst_dev; @@ -100,32 +97,12 @@ static inline void spi_dump_message(const u8_t *pre, u8_t *buf, u8_t size) {} #endif -/* - * SPI driver shim. - * - * This can be removed and this driver further improved when the - * legacy SPI API is gone. (For example, the chip select handling done - * under CONFIG_BT_SPI_BLUENRG could be done with a struct - * spi_cs_control instead). - */ -static struct device *spi_dev; -#if defined(CONFIG_SPI_LEGACY_API) -static struct spi_config spi_conf = { - .config = SPI_WORD(8), - .max_sys_freq = CONFIG_BT_SPI_MAX_CLK_FREQ, -}; +#if defined(CONFIG_BT_SPI_BLUENRG) +static struct device *cs_dev; +#endif /* CONFIG_BT_SPI_BLUENRG */ -static inline int bt_spi_dev_configure(void) -{ - return spi_configure(spi_dev, &spi_conf); -} +static struct device *spi_dev; -static inline int bt_spi_transceive(const void *tx, u32_t tx_len, - void *rx, u32_t rx_len) -{ - return spi_transceive(spi_dev, tx, tx_len, rx, rx_len); -} -#else /* !defined(CONFIG_SPI_LEGACY_API) */ static struct spi_config spi_conf = { .frequency = CONFIG_BT_SPI_MAX_CLK_FREQ, .operation = (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | @@ -135,27 +112,24 @@ static struct spi_config spi_conf = { }; static struct spi_buf spi_tx_buf; static struct spi_buf spi_rx_buf; +static const struct spi_buf_set spi_tx = { + .buffers = &spi_tx_buf, + .count = 1 +}; +static const struct spi_buf_set spi_rx = { + .buffers = &spi_rx_buf, + .count = 1 +}; -static inline int bt_spi_dev_configure(void) -{ - spi_conf.dev = spi_dev; - return 0; -} - -static inline int bt_spi_transceive(const void *tx, u32_t tx_len, +static inline int bt_spi_transceive(void *tx, u32_t tx_len, void *rx, u32_t rx_len) { - /* - * It's OK to cast away const here: &spi_tx_buf is treated as - * const by spi_transceive(). - */ - spi_tx_buf.buf = (void *)tx; + spi_tx_buf.buf = tx; spi_tx_buf.len = (size_t)tx_len; spi_rx_buf.buf = rx; spi_rx_buf.len = (size_t)rx_len; - return spi_transceive(&spi_conf, &spi_tx_buf, 1, &spi_rx_buf, 1); + return spi_transceive(spi_dev, &spi_conf, &spi_tx, &spi_rx); } -#endif /* CONFIG_SPI_LEGACY_API */ static inline u16_t bt_spi_get_cmd(u8_t *txmsg) { @@ -168,8 +142,10 @@ static inline u16_t bt_spi_get_evt(u8_t *rxmsg) } static void bt_spi_isr(struct device *unused1, struct gpio_callback *unused2, - unsigned int unused3) + unsigned int unused3) { + BT_DBG(""); + k_sem_give(&sem_request); } @@ -183,13 +159,55 @@ static void bt_spi_handle_vendor_evt(u8_t *rxmsg) } } +#if defined(CONFIG_BT_SPI_BLUENRG) +/* BlueNRG has a particuliar way to wake up from sleep and be ready. + * All is done through its CS line: + * If it is in sleep mode, the first transaction will not return ready + * status. At this point, it's necessary to release the CS and retry + * within 2ms the same transaction. And again when it's required to + * know the amount of byte to read. + * (See section 5.2 of BlueNRG-MS datasheet) + */ +static int bt_spi_configure_cs(void) +{ + cs_dev = device_get_binding(CONFIG_BT_SPI_CHIP_SELECT_DEV_NAME); + if (!cs_dev) { + BT_ERR("Failed to initialize GPIO driver: %s", + CONFIG_BT_SPI_CHIP_SELECT_DEV_NAME); + return -EIO; + } + + gpio_pin_configure(cs_dev, GPIO_CS_PIN, + GPIO_DIR_OUT | GPIO_PUD_PULL_UP); + gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); + + return 0; +} + +static void bt_spi_kick_cs(void) +{ + gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); + gpio_pin_write(cs_dev, GPIO_CS_PIN, 0); +} + +static void bt_spi_release_cs(void) +{ + gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); +} +#else +#define bt_spi_configure_cs(...) 0 +#define bt_spi_kick_cs(...) +#define bt_spi_release_cs(...) +#endif + static void bt_spi_rx_thread(void) { struct net_buf *buf; u8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 }; u8_t header_slave[5]; struct bt_hci_acl_hdr acl_hdr; - u8_t size; + u8_t size = 0; + int ret; memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN); @@ -199,26 +217,33 @@ static void bt_spi_rx_thread(void) gpio_pin_disable_callback(irq_dev, GPIO_IRQ_PIN); k_sem_take(&sem_busy, K_FOREVER); - do { -#if defined(CONFIG_BT_SPI_BLUENRG) - gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); - gpio_pin_write(cs_dev, GPIO_CS_PIN, 0); -#endif /* CONFIG_BT_SPI_BLUENRG */ - bt_spi_transceive(header_master, 5, header_slave, 5); - } while (header_slave[STATUS_HEADER_TOREAD] == 0 || - header_slave[STATUS_HEADER_TOREAD] == 0xFF); + BT_DBG(""); - size = header_slave[STATUS_HEADER_TOREAD]; do { - bt_spi_transceive(&txmsg, size, &rxmsg, size); - } while (rxmsg[0] == 0); + bt_spi_kick_cs(); + ret = bt_spi_transceive(header_master, 5, + header_slave, 5); + } while ((header_slave[STATUS_HEADER_TOREAD] == 0 || + header_slave[STATUS_HEADER_TOREAD] == 0xFF) && !ret); + + if (!ret) { + size = header_slave[STATUS_HEADER_TOREAD]; + + do { + ret = bt_spi_transceive(&txmsg, size, + &rxmsg, size); + } while (rxmsg[0] == 0 && ret == 0); + } + bt_spi_release_cs(); gpio_pin_enable_callback(irq_dev, GPIO_IRQ_PIN); -#if defined(CONFIG_BT_SPI_BLUENRG) - gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); -#endif /* CONFIG_BT_SPI_BLUENRG */ k_sem_give(&sem_busy); + if (ret) { + BT_ERR("Error %d", ret); + continue; + } + spi_dump_message("RX:ed", rxmsg, size); switch (rxmsg[PACKET_TYPE]) { @@ -265,6 +290,9 @@ static int bt_spi_send(struct net_buf *buf) { u8_t header[5] = { SPI_WRITE, 0x00, 0x00, 0x00, 0x00 }; u32_t pending; + int ret; + + BT_DBG(""); /* Buffer needs an additional byte for type */ if (buf->len >= SPI_MAX_MSG_LEN) { @@ -298,31 +326,35 @@ static int bt_spi_send(struct net_buf *buf) /* Poll sanity values until device has woken-up */ do { -#if defined(CONFIG_BT_SPI_BLUENRG) - gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); - gpio_pin_write(cs_dev, GPIO_CS_PIN, 0); -#endif /* CONFIG_BT_SPI_BLUENRG */ - bt_spi_transceive(header, 5, rxmsg, 5); + bt_spi_kick_cs(); + ret = bt_spi_transceive(header, 5, rxmsg, 5); /* * RX Header (rxmsg) must contain a sanity check Byte and size * information. If it does not contain BOTH then it is * sleeping or still in the initialisation stage (waking-up). */ - } while (rxmsg[STATUS_HEADER_READY] != READY_NOW || - (rxmsg[1] | rxmsg[2] | rxmsg[3] | rxmsg[4]) == 0); + } while ((rxmsg[STATUS_HEADER_READY] != READY_NOW || + (rxmsg[1] | rxmsg[2] | rxmsg[3] | rxmsg[4]) == 0) && !ret); - /* Transmit the message */ - do { - bt_spi_transceive(buf->data, buf->len, rxmsg, buf->len); - } while (rxmsg[0] == 0); -#if defined(CONFIG_BT_SPI_BLUENRG) - /* Deselect chip */ - gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); -#endif /* CONFIG_BT_SPI_BLUENRG */ k_sem_give(&sem_busy); + if (!ret) { + /* Transmit the message */ + do { + ret = bt_spi_transceive(buf->data, buf->len, + rxmsg, buf->len); + } while (rxmsg[0] == 0 && !ret); + } + + bt_spi_release_cs(); + + if (ret) { + BT_ERR("Error %d", ret); + goto out; + } + spi_dump_message("TX:ed", buf->data, buf->len); #if defined(CONFIG_BT_SPI_BLUENRG) @@ -337,10 +369,10 @@ static int bt_spi_send(struct net_buf *buf) k_sem_take(&sem_initialised, K_FOREVER); } #endif /* CONFIG_BT_SPI_BLUENRG */ - +out: net_buf_unref(buf); - return 0; + return ret; } static int bt_spi_open(void) @@ -350,15 +382,6 @@ static int bt_spi_open(void) GPIO_DIR_OUT | GPIO_PUD_PULL_UP); gpio_pin_write(rst_dev, GPIO_RESET_PIN, 0); - bt_spi_dev_configure(); - -#if defined(CONFIG_BT_SPI_BLUENRG) - /* Configure the CS (Chip Select) pin */ - gpio_pin_configure(cs_dev, GPIO_CS_PIN, - GPIO_DIR_OUT | GPIO_PUD_PULL_UP); - gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); -#endif /* CONFIG_BT_SPI_BLUENRG */ - /* Configure IRQ pin and the IRQ call-back/handler */ gpio_pin_configure(irq_dev, GPIO_IRQ_PIN, GPIO_DIR_IN | GPIO_INT | @@ -408,14 +431,9 @@ static int _bt_spi_init(struct device *unused) return -EIO; } -#if defined(CONFIG_BT_SPI_BLUENRG) - cs_dev = device_get_binding(CONFIG_BT_SPI_CHIP_SELECT_DEV_NAME); - if (!cs_dev) { - BT_ERR("Failed to initialize GPIO driver: %s", - CONFIG_BT_SPI_CHIP_SELECT_DEV_NAME); + if (bt_spi_configure_cs()) { return -EIO; } -#endif /* CONFIG_BT_SPI_BLUENRG */ irq_dev = device_get_binding(CONFIG_BT_SPI_IRQ_DEV_NAME); if (!irq_dev) { @@ -433,6 +451,9 @@ static int _bt_spi_init(struct device *unused) bt_hci_driver_register(&drv); + + BT_DBG("BT SPI initialized"); + return 0; } diff --git a/drivers/clock_control/Kconfig.quark_se b/drivers/clock_control/Kconfig.quark_se index 042a534d6523..a6b744c9da0d 100644 --- a/drivers/clock_control/Kconfig.quark_se +++ b/drivers/clock_control/Kconfig.quark_se @@ -6,8 +6,6 @@ # SPDX-License-Identifier: Apache-2.0 # -if SOC_QUARK_SE_C1000 - menuconfig CLOCK_CONTROL_QUARK_SE bool prompt "Quark SE Clock controller support" @@ -15,10 +13,11 @@ menuconfig CLOCK_CONTROL_QUARK_SE help Enable support for the Quark SE clock driver. +if CLOCK_CONTROL_QUARK_SE + config CLOCK_CONTROL_QUARK_SE_PERIPHERAL bool prompt "Quark SE peripheral clock support" - depends on CLOCK_CONTROL_QUARK_SE default n help Enable support for Quark SE peripheral clock which controls the @@ -33,7 +32,6 @@ config CLOCK_CONTROL_QUARK_SE_PERIPHERAL_DRV_NAME config CLOCK_CONTROL_QUARK_SE_EXTERNAL bool prompt "Quark SE external clock support" - depends on CLOCK_CONTROL_QUARK_SE default n help Enable support for Quark SE external sub-system clock. @@ -47,7 +45,6 @@ config CLOCK_CONTROL_QUARK_SE_EXTERNAL_DRV_NAME config CLOCK_CONTROL_QUARK_SE_SENSOR bool prompt "Quark SE sensor clock support" - depends on CLOCK_CONTROL_QUARK_SE default n help Enable support for Quark SE sensor sub-system clock. @@ -58,4 +55,4 @@ config CLOCK_CONTROL_QUARK_SE_SENSOR_DRV_NAME depends on CLOCK_CONTROL_QUARK_SE_SENSOR default "clk_sensor" -endif # SOC_QUARK_SE_C1000 +endif # CLOCK_CONTROL_QUARK_SE \ No newline at end of file diff --git a/drivers/clock_control/quark_se_clock_control.c b/drivers/clock_control/quark_se_clock_control.c index ee0975da340e..ff48ea028db9 100644 --- a/drivers/clock_control/quark_se_clock_control.c +++ b/drivers/clock_control/quark_se_clock_control.c @@ -22,6 +22,18 @@ #define SYS_LOG_LEVEL CONFIG_SYS_LOG_CLOCK_CONTROL_LEVEL #include +#ifdef CONFIG_ARC +#define WRITE(__data, __base_address) \ + sys_out32(__data, __base_address) +#define TEST_CLEAR_BIT(__base_address, __bit) \ + sys_io_test_and_clear_bit(__base_address, __bit) +#else +#define WRITE(__data, __base_address) \ + sys_write32(__data, __base_address) +#define TEST_CLEAR_BIT(__base_address, __bit) \ + sys_test_and_clear_bit(__base_address, __bit) +#endif /* CONFIG_ARC */ + struct quark_se_clock_control_config { u32_t base_address; }; @@ -29,37 +41,39 @@ struct quark_se_clock_control_config { static inline int quark_se_clock_control_on(struct device *dev, clock_control_subsys_t sub_system) { - const struct quark_se_clock_control_config *info = dev->config->config_info; + const struct quark_se_clock_control_config *info = + dev->config->config_info; u32_t subsys = POINTER_TO_INT(sub_system); if (sub_system == CLOCK_CONTROL_SUBSYS_ALL) { SYS_LOG_DBG("Enabling all clock gates on dev %p", dev); - sys_write32(0xffffffff, info->base_address); + WRITE(0xffffffff, info->base_address); return 0; } SYS_LOG_DBG("Enabling clock gate on dev %p subsystem %u", dev, subsys); - return sys_test_and_set_bit(info->base_address, subsys); + return TEST_CLEAR_BIT(info->base_address, subsys); } static inline int quark_se_clock_control_off(struct device *dev, clock_control_subsys_t sub_system) { - const struct quark_se_clock_control_config *info = dev->config->config_info; + const struct quark_se_clock_control_config *info = + dev->config->config_info; u32_t subsys = POINTER_TO_INT(sub_system); if (sub_system == CLOCK_CONTROL_SUBSYS_ALL) { SYS_LOG_DBG("Disabling all clock gates on dev %p", dev); - sys_write32(0x00000000, info->base_address); + WRITE(0x00000000, info->base_address); return 0; } SYS_LOG_DBG("clock gate on dev %p subsystem %u", dev, subsys); - return sys_test_and_clear_bit(info->base_address, subsys); + return TEST_CLEAR_BIT(info->base_address, subsys); } static const struct clock_control_driver_api quark_se_clock_control_api = { @@ -70,8 +84,7 @@ static const struct clock_control_driver_api quark_se_clock_control_api = { int quark_se_clock_control_init(struct device *dev) { - SYS_LOG_DBG("Quark Se clock controller driver initialized on device: " - "%p", dev); + SYS_LOG_DBG("Quark_SE clock controller on: %p", dev); return 0; } @@ -82,11 +95,11 @@ static struct quark_se_clock_control_config clock_quark_se_peripheral_config = { }; DEVICE_AND_API_INIT(clock_quark_se_peripheral, - CONFIG_CLOCK_CONTROL_QUARK_SE_PERIPHERAL_DRV_NAME, - &quark_se_clock_control_init, - NULL, &clock_quark_se_peripheral_config, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &quark_se_clock_control_api); + CONFIG_CLOCK_CONTROL_QUARK_SE_PERIPHERAL_DRV_NAME, + &quark_se_clock_control_init, + NULL, &clock_quark_se_peripheral_config, + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &quark_se_clock_control_api); #endif /* CONFIG_CLOCK_CONTROL_QUARK_SE_PERIPHERAL */ #ifdef CONFIG_CLOCK_CONTROL_QUARK_SE_EXTERNAL @@ -96,11 +109,11 @@ static struct quark_se_clock_control_config clock_quark_se_external_config = { }; DEVICE_AND_API_INIT(clock_quark_se_external, - CONFIG_CLOCK_CONTROL_QUARK_SE_EXTERNAL_DRV_NAME, - &quark_se_clock_control_init, - NULL, &clock_quark_se_external_config, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &quark_se_clock_control_api); + CONFIG_CLOCK_CONTROL_QUARK_SE_EXTERNAL_DRV_NAME, + &quark_se_clock_control_init, + NULL, &clock_quark_se_external_config, + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &quark_se_clock_control_api); #endif /* CONFIG_CLOCK_CONTROL_QUARK_SE_EXTERNAL */ #ifdef CONFIG_CLOCK_CONTROL_QUARK_SE_SENSOR @@ -110,10 +123,10 @@ static struct quark_se_clock_control_config clock_quark_se_sensor_config = { }; DEVICE_AND_API_INIT(clock_quark_se_sensor, - CONFIG_CLOCK_CONTROL_QUARK_SE_SENSOR_DRV_NAME, - &quark_se_clock_control_init, - NULL, &clock_quark_se_sensor_config, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &quark_se_clock_control_api); + CONFIG_CLOCK_CONTROL_QUARK_SE_SENSOR_DRV_NAME, + &quark_se_clock_control_init, + NULL, &clock_quark_se_sensor_config, + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &quark_se_clock_control_api); #endif /* CONFIG_CLOCK_CONTROL_QUARK_SE_SENSOR */ diff --git a/drivers/ethernet/Kconfig.enc28j60 b/drivers/ethernet/Kconfig.enc28j60 index 78bdc5799750..cce8373efc3b 100644 --- a/drivers/ethernet/Kconfig.enc28j60 +++ b/drivers/ethernet/Kconfig.enc28j60 @@ -9,7 +9,6 @@ menuconfig ETH_ENC28J60 bool "ENC28J60C Ethernet Controller" depends on NET_L2_ETHERNET - depends on SPI_LEGACY_API depends on SPI default n help @@ -84,11 +83,32 @@ config ETH_ENC28J60_0_SLAVE help ENC28J60C chip select pin. +config ETH_ENC28J60_0_GPIO_SPI_CS + bool "Manage SPI CS throug 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 ETH_ENC28J60_0_SPI_CS_PORT_NAME + string "SPI cs port name" + default "" + depends on ETH_ENC28J60_0_GPIO_SPI_CS + help + Master SPI port name through which ENC28J60C chip is accessed. + +config ETH_ENC28J60_0_SPI_CS_PIN + int "SPI CS pin" + default 0 + depends on ETH_ENC28J60_0_GPIO_SPI_CS + help + CS pin used for the SPI device + config ETH_ENC28J60_0_SPI_BUS_FREQ int "ENC28J60C SPI bus speed in Hz" - default 128 + default 128000 help - This is the maximum supported SPI bus frequency. + This is the SPI bus frequency for accessing the device. config ETH_ENC28J60_0_MAC3 hex "MAC Address Byte 3" diff --git a/drivers/ethernet/eth_enc28j60.c b/drivers/ethernet/eth_enc28j60.c index 5e20ad636a73..6d2b78e8ce96 100644 --- a/drivers/ethernet/eth_enc28j60.c +++ b/drivers/ethernet/eth_enc28j60.c @@ -29,30 +29,56 @@ static int eth_enc28j60_soft_reset(struct device *dev) { struct eth_enc28j60_runtime *context = dev->driver_data; u8_t tx_buf[2] = {ENC28J60_SPI_SC, 0xFF}; - - return spi_write(context->spi, tx_buf, 2); + const struct spi_buf tx_bufs[] = { + { + .buf = tx_buf, + .len = 1, + }, + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + + return spi_write(context->spi, &context->spi_cfg, &tx); } static void eth_enc28j60_set_bank(struct device *dev, u16_t reg_addr) { struct eth_enc28j60_runtime *context = dev->driver_data; + struct spi_buf tx_bufs[1]; + struct spi_buf rx_bufs[1]; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs) + }; u8_t tx_buf[2]; - - k_sem_take(&context->spi_sem, K_FOREVER); + u8_t rx_buf[2]; + int ret; tx_buf[0] = ENC28J60_SPI_RCR | ENC28J60_REG_ECON1; tx_buf[1] = 0x0; - if (!spi_transceive(context->spi, tx_buf, 2, tx_buf, 2)) { + tx_bufs[0].buf = tx_buf; + tx_bufs[0].len = 2; + rx_bufs[0].buf = rx_buf; + rx_bufs[0].len = 2; + + ret = spi_transceive(context->spi, &context->spi_cfg, &tx, &rx); + if (!ret) { tx_buf[0] = ENC28J60_SPI_WCR | ENC28J60_REG_ECON1; - tx_buf[1] = (tx_buf[1] & 0xFC) | ((reg_addr >> 8) & 0x0F); + tx_buf[1] = (rx_buf[1] & 0xFC) | ((reg_addr >> 8) & 0x0F); - spi_write(context->spi, tx_buf, 2); + tx_bufs[0].buf = tx_buf; + tx_bufs[0].len = 2; + spi_write(context->spi, &context->spi_cfg, &tx); } else { SYS_LOG_DBG("Failure while setting bank to %d", reg_addr); } - - k_sem_give(&context->spi_sem); } static void eth_enc28j60_write_reg(struct device *dev, u16_t reg_addr, @@ -60,41 +86,67 @@ static void eth_enc28j60_write_reg(struct device *dev, u16_t reg_addr, { struct eth_enc28j60_runtime *context = dev->driver_data; u8_t tx_buf[2]; - - k_sem_take(&context->spi_sem, K_FOREVER); + const struct spi_buf tx_bufs[] = { + { + .buf = tx_buf, + .len = 2 + } + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; tx_buf[0] = ENC28J60_SPI_WCR | (reg_addr & 0xFF); tx_buf[1] = value; - spi_write(context->spi, tx_buf, 2); - - k_sem_give(&context->spi_sem); + spi_write(context->spi, &context->spi_cfg, &tx); } static void eth_enc28j60_read_reg(struct device *dev, u16_t reg_addr, u8_t *value) { struct eth_enc28j60_runtime *context = dev->driver_data; - u8_t tx_size = 2; - u8_t tx_buf[3]; - - k_sem_take(&context->spi_sem, K_FOREVER); + u8_t tx_buf[2]; + const struct spi_buf tx_bufs[1] = { + { + .buf = tx_buf, + .len = 2 + } + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + u8_t rx_buf[3]; + struct spi_buf rx_bufs[1] = { + { + .buf = rx_buf, + } + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs) + }; + u8_t rx_size = 2; + int ret; if (reg_addr & 0xF000) { - tx_size = 3; + rx_size = 3; } tx_buf[0] = ENC28J60_SPI_RCR | (reg_addr & 0xFF); tx_buf[1] = 0x0; - if (!spi_transceive(context->spi, tx_buf, tx_size, tx_buf, tx_size)) { - *value = tx_buf[tx_size - 1]; + rx_bufs[0].len = rx_size; + + ret = spi_transceive(context->spi, &context->spi_cfg, &tx, &rx); + if (!ret) { + *value = rx_buf[rx_size - 1]; } else { SYS_LOG_DBG("Failure while reading register %d", reg_addr); *value = 0; } - - k_sem_give(&context->spi_sem); } static void eth_enc28j60_set_eth_reg(struct device *dev, u16_t reg_addr, @@ -102,15 +154,21 @@ static void eth_enc28j60_set_eth_reg(struct device *dev, u16_t reg_addr, { struct eth_enc28j60_runtime *context = dev->driver_data; u8_t tx_buf[2]; - - k_sem_take(&context->spi_sem, K_FOREVER); + const struct spi_buf tx_bufs[1] = { + { + .buf = tx_buf, + .len = 2 + } + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; tx_buf[0] = ENC28J60_SPI_BFS | (reg_addr & 0xFF); tx_buf[1] = value; - spi_write(context->spi, tx_buf, 2); - - k_sem_give(&context->spi_sem); + spi_write(context->spi, &context->spi_cfg, &tx); } @@ -119,21 +177,32 @@ static void eth_enc28j60_clear_eth_reg(struct device *dev, u16_t reg_addr, { struct eth_enc28j60_runtime *context = dev->driver_data; u8_t tx_buf[2]; - - k_sem_take(&context->spi_sem, K_FOREVER); + const struct spi_buf tx_bufs[1] = { + { + .buf = tx_buf, + .len = ARRAY_SIZE(tx_bufs) + } + }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; tx_buf[0] = ENC28J60_SPI_BFC | (reg_addr & 0xFF); tx_buf[1] = value; - spi_write(context->spi, tx_buf, 2); - - k_sem_give(&context->spi_sem); + spi_write(context->spi, &context->spi_cfg, &tx); } static void eth_enc28j60_write_mem(struct device *dev, u8_t *data_buffer, u16_t buf_len) { struct eth_enc28j60_runtime *context = dev->driver_data; + struct spi_buf tx_bufs[1]; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; u8_t *index_buf; u16_t num_segments; u16_t num_remaining; @@ -142,44 +211,51 @@ static void eth_enc28j60_write_mem(struct device *dev, u8_t *data_buffer, num_segments = buf_len / MAX_BUFFER_LENGTH; num_remaining = buf_len - MAX_BUFFER_LENGTH * num_segments; - k_sem_take(&context->spi_sem, K_FOREVER); - for (int i = 0; i < num_segments; ++i, index_buf += MAX_BUFFER_LENGTH) { context->mem_buf[0] = ENC28J60_SPI_WBM; memcpy(context->mem_buf + 1, index_buf, MAX_BUFFER_LENGTH); - spi_write(context->spi, - context->mem_buf, MAX_BUFFER_LENGTH + 1); + tx_bufs[0].buf = context->mem_buf; + tx_bufs[0].len = MAX_BUFFER_LENGTH + 1; + + spi_write(context->spi, &context->spi_cfg, &tx); } if (num_remaining > 0) { context->mem_buf[0] = ENC28J60_SPI_WBM; memcpy(context->mem_buf + 1, index_buf, num_remaining); - spi_write(context->spi, context->mem_buf, num_remaining + 1); - } + tx_bufs[0].buf = context->mem_buf; + tx_bufs[0].len = num_remaining + 1; - k_sem_give(&context->spi_sem); + spi_write(context->spi, &context->spi_cfg, &tx); + } } static void eth_enc28j60_read_mem(struct device *dev, u8_t *data_buffer, u16_t buf_len) { struct eth_enc28j60_runtime *context = dev->driver_data; + struct spi_buf tx_bufs[1]; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; u16_t num_segments; u16_t num_remaining; + int ret; num_segments = buf_len / MAX_BUFFER_LENGTH; num_remaining = buf_len - MAX_BUFFER_LENGTH * num_segments; - k_sem_take(&context->spi_sem, K_FOREVER); - for (int i = 0; i < num_segments; ++i, data_buffer += MAX_BUFFER_LENGTH) { context->mem_buf[0] = ENC28J60_SPI_RBM; - if (!spi_transceive(context->spi, - context->mem_buf, MAX_BUFFER_LENGTH + 1, - context->mem_buf, MAX_BUFFER_LENGTH + 1)) { + tx_bufs[0].buf = context->mem_buf; + tx_bufs[0].len = MAX_BUFFER_LENGTH + 1; + + ret = spi_transceive(context->spi, &context->spi_cfg, &tx, &tx); + if (!ret) { if (data_buffer) { memcpy(data_buffer, context->mem_buf + 1, MAX_BUFFER_LENGTH); @@ -192,9 +268,11 @@ static void eth_enc28j60_read_mem(struct device *dev, u8_t *data_buffer, if (num_remaining > 0) { context->mem_buf[0] = ENC28J60_SPI_RBM; - if (!spi_transceive(context->spi, - context->mem_buf, num_remaining + 1, - context->mem_buf, num_remaining + 1)) { + tx_bufs[0].buf = context->mem_buf; + tx_bufs[0].len = num_remaining + 1; + + ret = spi_transceive(context->spi, &context->spi_cfg, &tx, &tx); + if (!ret) { if (data_buffer) { memcpy(data_buffer, context->mem_buf + 1, num_remaining); @@ -203,8 +281,6 @@ static void eth_enc28j60_read_mem(struct device *dev, u8_t *data_buffer, SYS_LOG_DBG("Failed to read memory"); } } - - k_sem_give(&context->spi_sem); } static void eth_enc28j60_write_phy(struct device *dev, u16_t reg_addr, @@ -348,23 +424,38 @@ static int eth_enc28j60_init(struct device *dev) { const struct eth_enc28j60_config *config = dev->config->config_info; struct eth_enc28j60_runtime *context = dev->driver_data; - struct spi_config spi_cfg; - k_sem_init(&context->spi_sem, 1, UINT_MAX); - - context->gpio = device_get_binding((char *)config->gpio_port); - if (!context->gpio) { - SYS_LOG_ERR("GPIO port %s not found", config->gpio_port); - return -EINVAL; - } + /* SPI config */ + context->spi_cfg.operation = SPI_WORD_SET(8); + context->spi_cfg.frequency = config->spi_freq; + context->spi_cfg.slave = config->spi_slave; context->spi = device_get_binding((char *)config->spi_port); if (!context->spi) { + SYS_LOG_ERR("SPI master port %s not found", config->spi_port); return -EINVAL; } +#ifdef CONFIG_ETH_ENC28J60_0_GPIO_SPI_CS + context->spi_cs.gpio_dev = + device_get_binding((char *)config->spi_cs_port); + if (!context->spi_cs.gpio_dev) { + SYS_LOG_ERR("SPI CS port %s not found", config->spi_cs_port); + return -EINVAL; + } + + context->spi_cs.gpio_pin = config->spi_cs_pin; + context->spi_cfg.cs = &context->spi_cs; +#endif /* CONFIG_ETH_ENC28J60_0_GPIO_SPI_CS */ + /* Initialize GPIO */ + context->gpio = device_get_binding((char *)config->gpio_port); + if (!context->gpio) { + SYS_LOG_ERR("GPIO port %s not found", config->gpio_port); + return -EINVAL; + } + if (gpio_pin_configure(context->gpio, config->gpio_pin, (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE))) { @@ -384,27 +475,12 @@ static int eth_enc28j60_init(struct device *dev) return -EINVAL; } - /* Initialize SPI: - * Mode: 0/0; Size: 8 bits; MSB - */ - spi_cfg.config = 8 << 4; - spi_cfg.max_sys_freq = config->spi_freq; - - if (spi_configure(context->spi, &spi_cfg) < 0) { - SYS_LOG_ERR("Failed to configure SPI"); - return -EIO; - } - - if (spi_slave_select(context->spi, config->spi_slave) < 0) { - return -EIO; - } - if (eth_enc28j60_soft_reset(dev)) { SYS_LOG_ERR("Soft-reset failed"); return -EIO; } - /* Errata B7/2 */ + /* Errata B7/1 */ k_busy_wait(D10D24S); eth_enc28j60_init_buffers(dev); @@ -528,6 +604,11 @@ static int eth_enc28j60_rx(struct device *dev) * does not reliably/accurately report the status of pending packet. * Use EPKTCNT register instead. */ + eth_enc28j60_set_bank(dev, ENC28J60_REG_EPKTCNT); + eth_enc28j60_read_reg(dev, ENC28J60_REG_EPKTCNT, &counter); + if (!counter) { + return 0; + } SYS_LOG_DBG(""); @@ -658,7 +739,6 @@ static void enc28j60_thread_main(void *arg1, void *unused1, void *unused2) while (1) { k_sem_take(&context->int_sem, K_FOREVER); eth_enc28j60_read_reg(dev, ENC28J60_REG_EIR, &int_stat); - if (int_stat & ENC28J60_BIT_EIR_PKTIF) { eth_enc28j60_rx(dev); /* Clear rx interruption flag */ @@ -718,6 +798,10 @@ static const struct eth_enc28j60_config eth_enc28j60_0_config = { .spi_port = CONFIG_ETH_ENC28J60_0_SPI_PORT_NAME, .spi_freq = CONFIG_ETH_ENC28J60_0_SPI_BUS_FREQ, .spi_slave = CONFIG_ETH_ENC28J60_0_SLAVE, +#ifdef CONFIG_ETH_ENC28J60_0_GPIO_SPI_CS + .spi_cs_port = CONFIG_ETH_ENC28J60_0_SPI_CS_PORT_NAME, + .spi_cs_pin = CONFIG_ETH_ENC28J60_0_SPI_CS_PIN, +#endif /* CONFIG_ETH_ENC28J60_0_GPIO_SPI_CS */ .full_duplex = CONFIG_ETH_EN28J60_0_FULL_DUPLEX, .timeout = CONFIG_ETH_EN28J60_TIMEOUT, }; diff --git a/drivers/ethernet/eth_enc28j60_priv.h b/drivers/ethernet/eth_enc28j60_priv.h index 6b3bb42d65bc..62cc30635cdb 100644 --- a/drivers/ethernet/eth_enc28j60_priv.h +++ b/drivers/ethernet/eth_enc28j60_priv.h @@ -217,6 +217,8 @@ struct eth_enc28j60_config { const char *gpio_port; u8_t gpio_pin; const char *spi_port; + u8_t spi_cs_pin; + const char *spi_cs_port; u32_t spi_freq; u8_t spi_slave; u8_t full_duplex; @@ -230,13 +232,14 @@ struct eth_enc28j60_runtime { struct k_thread thread; struct device *gpio; struct device *spi; + struct spi_cs_control spi_cs; + struct spi_config spi_cfg; struct gpio_callback gpio_cb; u8_t mem_buf[MAX_BUFFER_LENGTH + 1]; u8_t tx_tsv[TSV_SIZE]; u8_t rx_rsv[RSV_SIZE]; struct k_sem tx_rx_sem; struct k_sem int_sem; - struct k_sem spi_sem; }; #endif /*_ENC28J60_*/ diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index f7a9a6c70038..f920759d36a9 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -66,7 +66,7 @@ config SPI_FLASH_W25QXXDV_INIT_PRIORITY config SPI_FLASH_W25QXXDV_SPI_FREQ_0 int "SPI system frequency" depends on SPI_FLASH_W25QXXDV - default 4 + default 8000000 help This option sets the SPI controller's frequency. Beware this value depends on the SPI controller being used and also on the system diff --git a/drivers/flash/spi_flash_w25qxxdv.c b/drivers/flash/spi_flash_w25qxxdv.c index 218a83b1d3da..f3e4998cbbba 100644 --- a/drivers/flash/spi_flash_w25qxxdv.c +++ b/drivers/flash/spi_flash_w25qxxdv.c @@ -14,88 +14,99 @@ #include "spi_flash_w25qxxdv.h" #include "flash_priv.h" -static inline int spi_flash_wb_id(struct device *dev) +static int spi_flash_wb_access(struct spi_flash_data *ctx, + u8_t cmd, bool addressed, off_t offset, + void *data, size_t length, bool write) { - struct spi_flash_data *const driver_data = dev->driver_data; - u8_t buf[W25QXXDV_LEN_CMD_AND_ID]; - u32_t temp_data; + u8_t access[4]; + struct spi_buf buf[2] = { + { + .buf = access + }, + { + .buf = data, + .len = length + } + }; + struct spi_buf_set tx = { + .buffers = buf, + }; - buf[0] = W25QXXDV_CMD_RDID; + access[0] = cmd; - if (spi_transceive(driver_data->spi, buf, W25QXXDV_LEN_CMD_AND_ID, - buf, W25QXXDV_LEN_CMD_AND_ID) != 0) { - return -EIO; + if (addressed) { + access[1] = (u8_t) (offset >> 16); + access[2] = (u8_t) (offset >> 8); + access[3] = (u8_t) offset; + + buf[0].len = 4; + } else { + buf[0].len = 1; } - temp_data = ((u32_t) buf[1]) << 16; - temp_data |= ((u32_t) buf[2]) << 8; - temp_data |= (u32_t) buf[3]; + tx.count = length ? 2 : 1; - if (temp_data != W25QXXDV_RDID_VALUE) { - return -ENODEV; + if (!write) { + const struct spi_buf_set rx = { + .buffers = buf, + .count = 2 + }; + + return spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx); } - return 0; + return spi_write(ctx->spi, &ctx->spi_cfg, &tx); } -static int spi_flash_wb_config(struct device *dev) +static inline int spi_flash_wb_id(struct device *dev) { struct spi_flash_data *const driver_data = dev->driver_data; - struct spi_config config; - - config.max_sys_freq = CONFIG_SPI_FLASH_W25QXXDV_SPI_FREQ_0; - - config.config = SPI_WORD(8); + u32_t temp_data; + u8_t buf[3]; - if (spi_slave_select(driver_data->spi, - CONFIG_SPI_FLASH_W25QXXDV_SPI_SLAVE) != - 0) { + if (spi_flash_wb_access(driver_data, W25QXXDV_CMD_RDID, + false, 0, buf, 3, false) != 0) { return -EIO; } - if (spi_configure(driver_data->spi, &config) != 0) { - return -EIO; + temp_data = ((u32_t) buf[0]) << 16; + temp_data |= ((u32_t) buf[1]) << 8; + temp_data |= (u32_t) buf[2]; + + if (temp_data != W25QXXDV_RDID_VALUE) { + return -ENODEV; } - return spi_flash_wb_id(dev); + return 0; } -static int spi_flash_wb_reg_read(struct device *dev, u8_t *data) +static u8_t spi_flash_wb_reg_read(struct device *dev, u8_t reg) { struct spi_flash_data *const driver_data = dev->driver_data; - u8_t buf[2]; - if (spi_transceive(driver_data->spi, data, 2, buf, 2) != 0) { - return -EIO; + if (spi_flash_wb_access(driver_data, reg, + false, 0, ®, 1, false)) { + return 0; } - memcpy(data, buf, 2); - - return 0; + return reg; } static inline void wait_for_flash_idle(struct device *dev) { - u8_t buf[2]; - - buf[0] = W25QXXDV_CMD_RDSR; - spi_flash_wb_reg_read(dev, buf); + u8_t reg; - while (buf[1] & W25QXXDV_WIP_BIT) { - buf[0] = W25QXXDV_CMD_RDSR; - spi_flash_wb_reg_read(dev, buf); - } + do { + reg = spi_flash_wb_reg_read(dev, W25QXXDV_CMD_RDSR); + } while (reg & W25QXXDV_WIP_BIT); } -static int spi_flash_wb_reg_write(struct device *dev, u8_t *data) +static int spi_flash_wb_reg_write(struct device *dev, u8_t reg) { struct spi_flash_data *const driver_data = dev->driver_data; - u8_t buf; - - wait_for_flash_idle(dev); - if (spi_transceive(driver_data->spi, data, 1, - &buf /*dummy */, 1) != 0) { + if (spi_flash_wb_access(driver_data, reg, false, 0, + NULL, 0, true) != 0) { return -EIO; } @@ -106,7 +117,7 @@ static int spi_flash_wb_read(struct device *dev, off_t offset, void *data, size_t len) { struct spi_flash_data *const driver_data = dev->driver_data; - u8_t *buf = driver_data->buf; + int ret; if (len > CONFIG_SPI_FLASH_W25QXXDV_MAX_DATA_LEN || offset < 0) { return -ENODEV; @@ -114,38 +125,22 @@ static int spi_flash_wb_read(struct device *dev, off_t offset, void *data, k_sem_take(&driver_data->sem, K_FOREVER); - if (spi_flash_wb_config(dev) != 0) { - k_sem_give(&driver_data->sem); - return -EIO; - } - wait_for_flash_idle(dev); - buf[0] = W25QXXDV_CMD_READ; - buf[1] = (u8_t) (offset >> 16); - buf[2] = (u8_t) (offset >> 8); - buf[3] = (u8_t) offset; - - memset(buf + W25QXXDV_LEN_CMD_ADDRESS, 0, len); - - if (spi_transceive(driver_data->spi, buf, len + W25QXXDV_LEN_CMD_ADDRESS, - buf, len + W25QXXDV_LEN_CMD_ADDRESS) != 0) { - k_sem_give(&driver_data->sem); - return -EIO; - } - - memcpy(data, buf + W25QXXDV_LEN_CMD_ADDRESS, len); + ret = spi_flash_wb_access(driver_data, W25QXXDV_CMD_READ, + true, offset, data, len, false); k_sem_give(&driver_data->sem); - return 0; + return ret; } static int spi_flash_wb_write(struct device *dev, off_t offset, const void *data, size_t len) { struct spi_flash_data *const driver_data = dev->driver_data; - u8_t *buf = driver_data->buf; + u8_t reg; + int ret; if (len > CONFIG_SPI_FLASH_W25QXXDV_MAX_DATA_LEN || offset < 0) { return -ENOTSUP; @@ -153,79 +148,55 @@ static int spi_flash_wb_write(struct device *dev, off_t offset, k_sem_take(&driver_data->sem, K_FOREVER); - if (spi_flash_wb_config(dev) != 0) { - k_sem_give(&driver_data->sem); - return -EIO; - } - wait_for_flash_idle(dev); - buf[0] = W25QXXDV_CMD_RDSR; - spi_flash_wb_reg_read(dev, buf); - - if (!(buf[1] & W25QXXDV_WEL_BIT)) { + reg = spi_flash_wb_reg_read(dev, W25QXXDV_CMD_RDSR); + if (!(reg & W25QXXDV_WEL_BIT)) { k_sem_give(&driver_data->sem); return -EIO; } wait_for_flash_idle(dev); - buf[0] = W25QXXDV_CMD_PP; - buf[1] = (u8_t) (offset >> 16); - buf[2] = (u8_t) (offset >> 8); - buf[3] = (u8_t) offset; - - memcpy(buf + W25QXXDV_LEN_CMD_ADDRESS, data, len); - /* Assume write protection has been disabled. Note that w25qxxdv * flash automatically turns on write protection at the completion * of each write or erase transaction. */ - if (spi_write(driver_data->spi, buf, len + W25QXXDV_LEN_CMD_ADDRESS) != 0) { - k_sem_give(&driver_data->sem); - return -EIO; - } + ret = spi_flash_wb_access(driver_data, W25QXXDV_CMD_PP, + true, offset, (void *)data, len, true); k_sem_give(&driver_data->sem); - return 0; + return ret; } static int spi_flash_wb_write_protection_set(struct device *dev, bool enable) { struct spi_flash_data *const driver_data = dev->driver_data; - u8_t buf = 0; + u8_t reg = 0; + int ret; k_sem_take(&driver_data->sem, K_FOREVER); - if (spi_flash_wb_config(dev) != 0) { - k_sem_give(&driver_data->sem); - return -EIO; - } - wait_for_flash_idle(dev); if (enable) { - buf = W25QXXDV_CMD_WRDI; + reg = W25QXXDV_CMD_WRDI; } else { - buf = W25QXXDV_CMD_WREN; + reg = W25QXXDV_CMD_WREN; } - if (spi_flash_wb_reg_write(dev, &buf) != 0) { - k_sem_give(&driver_data->sem); - return -EIO; - } + ret = spi_flash_wb_reg_write(dev, reg); k_sem_give(&driver_data->sem); - return 0; + return ret; } static inline int spi_flash_wb_erase_internal(struct device *dev, off_t offset, size_t size) { struct spi_flash_data *const driver_data = dev->driver_data; - u8_t buf[W25QXXDV_LEN_CMD_ADDRESS]; u8_t erase_opcode; u32_t len; @@ -236,8 +207,7 @@ static inline int spi_flash_wb_erase_internal(struct device *dev, wait_for_flash_idle(dev); /* write enable */ - buf[0] = W25QXXDV_CMD_WREN; - spi_flash_wb_reg_write(dev, buf); + spi_flash_wb_reg_write(dev, W25QXXDV_CMD_WREN); wait_for_flash_idle(dev); @@ -263,25 +233,21 @@ static inline int spi_flash_wb_erase_internal(struct device *dev, } - buf[0] = erase_opcode; - buf[1] = (u8_t) (offset >> 16); - buf[2] = (u8_t) (offset >> 8); - buf[3] = (u8_t) offset; - /* Assume write protection has been disabled. Note that w25qxxdv * flash automatically turns on write protection at the completion * of each write or erase transaction. */ - return spi_write(driver_data->spi, buf, len); + return spi_flash_wb_access(driver_data, erase_opcode, + true, offset, NULL, len, true); } static int spi_flash_wb_erase(struct device *dev, off_t offset, size_t size) { struct spi_flash_data *const driver_data = dev->driver_data; - u8_t *buf = driver_data->buf; int ret = 0; u32_t new_offset = offset; u32_t size_remaining = size; + u8_t reg; if ((offset < 0) || ((offset & W25QXXDV_SECTOR_MASK) != 0) || ((size + offset) > CONFIG_SPI_FLASH_W25QXXDV_FLASH_SIZE) || @@ -291,15 +257,9 @@ static int spi_flash_wb_erase(struct device *dev, off_t offset, size_t size) k_sem_take(&driver_data->sem, K_FOREVER); - if (spi_flash_wb_config(dev) != 0) { - k_sem_give(&driver_data->sem); - return -EIO; - } + reg = spi_flash_wb_reg_read(dev, W25QXXDV_CMD_RDSR); - buf[0] = W25QXXDV_CMD_RDSR; - spi_flash_wb_reg_read(dev, buf); - - if (!(buf[1] & W25QXXDV_WEL_BIT)) { + if (!(reg & W25QXXDV_WEL_BIT)) { k_sem_give(&driver_data->sem); return -EIO; } @@ -352,23 +312,31 @@ static const struct flash_driver_api spi_flash_api = { .write_block_size = 1, }; -static int spi_flash_init(struct device *dev) +static int spi_flash_wb_configure(struct device *dev) { - struct device *spi_dev; struct spi_flash_data *data = dev->driver_data; - int ret; - spi_dev = device_get_binding(CONFIG_SPI_FLASH_W25QXXDV_SPI_NAME); - if (!spi_dev) { - return -EIO; + data->spi = device_get_binding(CONFIG_SPI_FLASH_W25QXXDV_SPI_NAME); + if (!data->spi) { + return -EINVAL; } - data->spi = spi_dev; + data->spi_cfg.frequency = CONFIG_SPI_FLASH_W25QXXDV_SPI_FREQ_0; + data->spi_cfg.operation = SPI_WORD_SET(8); + data->spi_cfg.slave = CONFIG_SPI_FLASH_W25QXXDV_SPI_SLAVE; + + return spi_flash_wb_id(dev); +} + +static int spi_flash_init(struct device *dev) +{ + struct spi_flash_data *data = dev->driver_data; + int ret; k_sem_init(&data->sem, 1, UINT_MAX); - ret = spi_flash_wb_config(dev); - if (!ret) { + ret = spi_flash_wb_configure(dev); + if (ret) { dev->driver_api = &spi_flash_api; } @@ -377,6 +345,6 @@ static int spi_flash_init(struct device *dev) static struct spi_flash_data spi_flash_memory_data; -DEVICE_INIT(spi_flash_memory, CONFIG_SPI_FLASH_W25QXXDV_DRV_NAME, spi_flash_init, - &spi_flash_memory_data, NULL, POST_KERNEL, +DEVICE_INIT(spi_flash_memory, CONFIG_SPI_FLASH_W25QXXDV_DRV_NAME, + spi_flash_init, &spi_flash_memory_data, NULL, POST_KERNEL, CONFIG_SPI_FLASH_W25QXXDV_INIT_PRIORITY); diff --git a/drivers/flash/spi_flash_w25qxxdv.h b/drivers/flash/spi_flash_w25qxxdv.h index c7589ba05da0..8daab83d954a 100644 --- a/drivers/flash/spi_flash_w25qxxdv.h +++ b/drivers/flash/spi_flash_w25qxxdv.h @@ -16,8 +16,7 @@ struct spi_flash_data { struct device *spi; - u8_t buf[CONFIG_SPI_FLASH_W25QXXDV_MAX_DATA_LEN + - W25QXXDV_LEN_CMD_ADDRESS]; + struct spi_config spi_cfg; struct k_sem sem; }; diff --git a/drivers/ieee802154/Kconfig.cc2520 b/drivers/ieee802154/Kconfig.cc2520 index d0adf328d488..12428116d4ab 100644 --- a/drivers/ieee802154/Kconfig.cc2520 +++ b/drivers/ieee802154/Kconfig.cc2520 @@ -41,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 diff --git a/drivers/ieee802154/Kconfig.mcr20a b/drivers/ieee802154/Kconfig.mcr20a index 193410b2e6f8..6b494ad97f1c 100644 --- a/drivers/ieee802154/Kconfig.mcr20a +++ b/drivers/ieee802154/Kconfig.mcr20a @@ -41,6 +41,29 @@ config IEEE802154_MCR20A_SPI_SLAVE This option sets the SPI slave number SPI controller has to switch to when dealing with MCR20A chip. +config IEEE802154_MCR20A_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_MCR20A_GPIO_SPI_CS_DRV_NAME + string "GPIO driver's name to use to drive SPI CS through" + default "" + depends on IEEE802154_MCR20A_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_MCR20A_GPIO_SPI_CS_PIN + int "GPIO PIN to use to drive SPI CS through" + default 0 + depends on IEEE802154_MCR20A_GPIO_SPI_CS + help + This option is mandatory to set which GPIO pin to use in order + to actually emulate the SPI CS. + config MCR20A_GPIO_IRQ_B_NAME string "GPIO device used for IRQ_B output of MCR20A" default GPIO_MCUX_PORTB_NAME diff --git a/drivers/ieee802154/ieee802154_cc1200.c b/drivers/ieee802154/ieee802154_cc1200.c index cbc991c12c7f..02e8d575f662 100644 --- a/drivers/ieee802154/ieee802154_cc1200.c +++ b/drivers/ieee802154/ieee802154_cc1200.c @@ -78,11 +78,11 @@ static void _cc1200_print_status(u8_t status) * Generic functions * ********************/ -bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr, +bool _cc1200_access_reg(struct cc1200_context *ctx, bool read, u8_t addr, void *data, size_t length, bool extended, bool burst) { u8_t cmd_buf[2]; - struct spi_buf buf[2] = { + const struct spi_buf buf[2] = { { .buf = cmd_buf, .len = extended ? 2 : 1, @@ -93,6 +93,7 @@ bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr, } }; + struct spi_buf_set tx = { .buffers = buf }; /* SYS_LOG_DBG("%s: addr 0x%02x - Data %p Length %u - %s, %s", @@ -115,13 +116,22 @@ bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr, } if (read) { + const struct spi_buf_set rx = { + .buffers = buf, + .count = 2 + }; + cmd_buf[0] |= CC1200_ACCESS_RD; - return (spi_transceive(spi, buf, 1, buf, 2) == 0); + tx.count = 1; + + return (spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx) == 0); } /* CC1200_ACCESS_WR is 0 so no need to play with it */ - return (spi_write(spi, buf, data ? 2 : 1) == 0); + tx.count = data ? 2 : 1; + + return (spi_write(ctx->spi, &ctx->spi_cfg, &tx) == 0); } static inline u8_t *get_mac(struct device *dev) @@ -149,11 +159,11 @@ static inline u8_t *get_mac(struct device *dev) return cc1200->mac_addr; } -static u8_t get_status(struct spi_config *spi) +static u8_t get_status(struct cc1200_context *ctx) { u8_t val; - if (_cc1200_access_reg(spi, true, CC1200_INS_SNOP, + if (_cc1200_access_reg(ctx, true, CC1200_INS_SNOP, &val, 1, false, false)) { /* See Section 3.1.2 */ return val & CC1200_STATUS_MASK; @@ -218,13 +228,13 @@ static void setup_gpio_callback(struct device *dev) * RF functions * ***************/ -static u8_t get_lo_divider(struct spi_config *spi) +static u8_t get_lo_divider(struct cc1200_context *ctx) { /* See Table 34 */ - return FSD_BANDSELECT(read_reg_fs_cfg(spi)) << 1; + return FSD_BANDSELECT(read_reg_fs_cfg(ctx)) << 1; } -static bool write_reg_freq(struct spi_config *spi, u32_t freq) +static bool write_reg_freq(struct cc1200_context *ctx, u32_t freq) { u8_t freq_data[3]; @@ -232,7 +242,7 @@ static bool write_reg_freq(struct spi_config *spi, u32_t freq) freq_data[1] = (u8_t)((freq & 0x0000FF00) >> 8); freq_data[2] = (u8_t)(freq & 0x000000FF); - return _cc1200_access_reg(spi, false, CC1200_REG_FREQ2, + return _cc1200_access_reg(ctx, false, CC1200_REG_FREQ2, freq_data, 3, true, true); } @@ -266,7 +276,7 @@ static bool write_reg_freq(struct spi_config *spi, u32_t freq) * User does not need to pass anything extra besides the nominal settings: no * pre-computed part or else. */ -static u32_t rf_evaluate_freq_setting(struct cc1200_context *cc1200, u32_t chan) +static u32_t rf_evaluate_freq_setting(struct cc1200_context *ctx, u32_t chan) { u32_t xtal = CONFIG_IEEE802154_CC1200_XOSC; u32_t mult_10 = 100000; @@ -276,7 +286,7 @@ static u32_t rf_evaluate_freq_setting(struct cc1200_context *cc1200, u32_t chan) rf = cc1200->rf_settings->chan_center_freq0 + ((chan * (u32_t)cc1200->rf_settings->channel_spacing) / 10); - lo_div = get_lo_divider(&cc1200->spi); + lo_div = get_lo_divider(ctx); SYS_LOG_DBG("Calculating freq for %u KHz RF (%u)", rf, lo_div); @@ -322,14 +332,14 @@ rf_install_settings(struct device *dev, { struct cc1200_context *cc1200 = dev->driver_data; - if (!_cc1200_access_reg(&cc1200->spi, false, CC1200_REG_SYNC3, + if (!_cc1200_access_reg(cc1200, false, CC1200_REG_SYNC3, (void *)rf_settings->registers, CC1200_RF_NON_EXT_SPACE_REGS, false, true) || - !_cc1200_access_reg(&cc1200->spi, false, CC1200_REG_IF_MIX_CFG, + !_cc1200_access_reg(cc1200, false, CC1200_REG_IF_MIX_CFG, (void *)rf_settings->registers + CC1200_RF_NON_EXT_SPACE_REGS, CC1200_RF_EXT_SPACE_REGS, true, true) || - !write_reg_pkt_len(&cc1200->spi, 0xFF)) { + !write_reg_pkt_len(cc1200, 0xFF)) { SYS_LOG_ERR("Could not install RF settings"); return false; } @@ -339,9 +349,9 @@ rf_install_settings(struct device *dev, return true; } -static int rf_calibrate(struct spi_config *spi) +static int rf_calibrate(struct cc1200_context *ctx) { - if (!instruct_scal(spi)) { + if (!instruct_scal(ctx)) { SYS_LOG_ERR("Could not calibrate RF"); return -EIO; } @@ -349,16 +359,16 @@ static int rf_calibrate(struct spi_config *spi) k_busy_wait(5 * USEC_PER_MSEC); /* We need to re-enable RX as SCAL shuts off the freq synth */ - if (!instruct_sidle(spi) || - !instruct_sfrx(spi) || - !instruct_srx(spi)) { + if (!instruct_sidle(ctx) || + !instruct_sfrx(ctx) || + !instruct_srx(ctx)) { SYS_LOG_ERR("Could not switch to RX"); return -EIO; } k_busy_wait(10 * USEC_PER_MSEC); - _cc1200_print_status(get_status(spi)); + _cc1200_print_status(get_status(ctx)); return 0; } @@ -367,10 +377,10 @@ static int rf_calibrate(struct spi_config *spi) * TX functions * ***************/ -static inline bool write_txfifo(struct spi_config *spi, +static inline bool write_txfifo(struct cc1200_context *ctx, void *data, size_t length) { - return _cc1200_access_reg(spi, false, + return _cc1200_access_reg(ctx, false, CC1200_REG_TXFIFO, data, length, false, true); } @@ -379,19 +389,19 @@ static inline bool write_txfifo(struct spi_config *spi, * RX functions * ***************/ -static inline bool read_rxfifo(struct spi_config *spi, +static inline bool read_rxfifo(struct cc1200_context *ctx, void *data, size_t length) { - return _cc1200_access_reg(spi, true, + return _cc1200_access_reg(ctx, true, CC1200_REG_RXFIFO, data, length, false, true); } -static inline u8_t get_packet_length(struct spi_config *spi) +static inline u8_t get_packet_length(struct cc1200_context *ctx) { u8_t len; - if (_cc1200_access_reg(spi, true, CC1200_REG_RXFIFO, + if (_cc1200_access_reg(ctx, true, CC1200_REG_RXFIFO, &len, 1, false, true)) { return len; } @@ -399,23 +409,24 @@ static inline u8_t get_packet_length(struct spi_config *spi) return 0; } -static inline bool verify_rxfifo_validity(struct spi_config *spi, u8_t pkt_len) +static inline bool verify_rxfifo_validity(struct cc1200_context *ctx, + u8_t pkt_len) { /* packet should be at least 3 bytes as a ACK */ if (pkt_len < 3 || - read_reg_num_rxbytes(spi) > (pkt_len + CC1200_FCS_LEN)) { + read_reg_num_rxbytes(ctx) > (pkt_len + CC1200_FCS_LEN)) { return false; } return true; } -static inline bool read_rxfifo_content(struct spi_config *spi, +static inline bool read_rxfifo_content(struct cc1200_context *ctx, struct net_buf *frag, u8_t len) { - if (!read_rxfifo(spi, frag->data, len) || - (get_status(spi) == CC1200_STATUS_RX_FIFO_ERROR)) { + if (!read_rxfifo(ctx, frag->data, len) || + (get_status(ctx) == CC1200_STATUS_RX_FIFO_ERROR)) { return false; } @@ -424,11 +435,11 @@ static inline bool read_rxfifo_content(struct spi_config *spi, return true; } -static inline bool verify_crc(struct spi_config *spi, struct net_pkt *pkt) +static inline bool verify_crc(struct cc1200_context *ctx, struct net_pkt *pkt) { u8_t fcs[2]; - if (!read_rxfifo(spi, fcs, 2)) { + if (!read_rxfifo(ctx, fcs, 2)) { return false; } @@ -454,13 +465,13 @@ static void cc1200_rx(struct device *dev) k_sem_take(&cc1200->rx_lock, K_FOREVER); - if (get_status(&cc1200->spi) == CC1200_STATUS_RX_FIFO_ERROR) { + if (get_status(cc1200) == CC1200_STATUS_RX_FIFO_ERROR) { SYS_LOG_ERR("Fifo error"); goto flush; } - pkt_len = get_packet_length(&cc1200->spi); - if (!verify_rxfifo_validity(&cc1200->spi, pkt_len)) { + pkt_len = get_packet_length(cc1200); + if (!verify_rxfifo_validity(cc1200, pkt_len)) { SYS_LOG_ERR("Invalid frame"); goto flush; } @@ -479,12 +490,12 @@ static void cc1200_rx(struct device *dev) net_pkt_frag_insert(pkt, pkt_frag); - if (!read_rxfifo_content(&cc1200->spi, pkt_frag, pkt_len)) { + if (!read_rxfifo_content(cc1200, pkt_frag, pkt_len)) { SYS_LOG_ERR("No content read"); goto flush; } - if (!verify_crc(&cc1200->spi, pkt)) { + if (!verify_crc(cc1200, pkt)) { SYS_LOG_ERR("Bad packet CRC"); goto out; } @@ -507,9 +518,9 @@ static void cc1200_rx(struct device *dev) continue; flush: SYS_LOG_DBG("Flushing RX"); - instruct_sidle(&cc1200->spi); - instruct_sfrx(&cc1200->spi); - instruct_srx(&cc1200->spi); + instruct_sidle(cc1200); + instruct_sfrx(cc1200); + instruct_srx(cc1200); out: if (pkt) { net_pkt_unref(pkt); @@ -532,7 +543,7 @@ static int cc1200_cca(struct device *dev) struct cc1200_context *cc1200 = dev->driver_data; if (atomic_get(&cc1200->rx) == 0) { - u8_t status = read_reg_rssi0(&cc1200->spi); + u8_t status = read_reg_rssi0(cc1200); if (!(status & CARRIER_SENSE) && (status & CARRIER_SENSE_VALID)) { @@ -560,8 +571,8 @@ static int cc1200_set_channel(struct device *dev, u16_t channel) if (atomic_get(&cc1200->rx) == 0) { u32_t freq = rf_evaluate_freq_setting(cc1200, channel); - if (!write_reg_freq(&cc1200->spi, freq) || - rf_calibrate(&cc1200->spi)) { + if (!write_reg_freq(cc1200, freq) || + rf_calibrate(cc1200)) { SYS_LOG_ERR("Could not set channel %u", channel); return -EIO; } @@ -584,10 +595,10 @@ static int cc1200_set_txpower(struct device *dev, s16_t dbm) return -EINVAL; } - pa_power_ramp = read_reg_pa_cfg1(&cc1200->spi) & ~PA_POWER_RAMP_MASK; + pa_power_ramp = read_reg_pa_cfg1(cc1200) & ~PA_POWER_RAMP_MASK; pa_power_ramp |= ((u8_t) dbm) & PA_POWER_RAMP_MASK; - if (!write_reg_pa_cfg1(&cc1200->spi, pa_power_ramp)) { + if (!write_reg_pa_cfg1(cc1200, pa_power_ramp)) { SYS_LOG_ERR("Could not proceed"); return -EIO; } @@ -611,17 +622,17 @@ static int cc1200_tx(struct device *dev, * depending on len value, this will also take more time. */ - if (!instruct_sidle(&cc1200->spi) || - !instruct_sfrx(&cc1200->spi) || - !instruct_sftx(&cc1200->spi) || - !instruct_sfstxon(&cc1200->spi)) { + if (!instruct_sidle(cc1200) || + !instruct_sfrx(cc1200) || + !instruct_sftx(cc1200) || + !instruct_sfstxon(cc1200)) { SYS_LOG_ERR("Cannot switch to TX mode"); goto out; } - if (!write_txfifo(&cc1200->spi, &len, CC1200_PHY_HDR_LEN) || - !write_txfifo(&cc1200->spi, frame, len) || - read_reg_num_txbytes(&cc1200->spi) != (len + CC1200_PHY_HDR_LEN)) { + if (!write_txfifo(cc1200, &len, CC1200_PHY_HDR_LEN) || + !write_txfifo(cc1200, frame, len) || + read_reg_num_txbytes(cc1200) != (len + CC1200_PHY_HDR_LEN)) { SYS_LOG_ERR("Cannot fill-in TX fifo"); goto out; } @@ -629,7 +640,7 @@ static int cc1200_tx(struct device *dev, atomic_set(&cc1200->tx, 1); atomic_set(&cc1200->tx_start, 0); - if (!instruct_stx(&cc1200->spi)) { + if (!instruct_stx(cc1200)) { SYS_LOG_ERR("Cannot start transmission"); goto out; } @@ -642,14 +653,14 @@ static int cc1200_tx(struct device *dev, } out: - _cc1200_print_status(get_status(&cc1200->spi)); + _cc1200_print_status(get_status(cc1200)); if (atomic_get(&cc1200->tx) == 1 && - read_reg_num_txbytes(&cc1200->spi) != 0) { + read_reg_num_txbytes(cc1200) != 0) { SYS_LOG_ERR("TX Failed"); atomic_set(&cc1200->tx_start, 0); - instruct_sftx(&cc1200->spi); + instruct_sftx(cc1200); status = false; } else { status = true; @@ -658,7 +669,7 @@ static int cc1200_tx(struct device *dev, atomic_set(&cc1200->tx, 0); /* Get back to RX */ - instruct_srx(&cc1200->spi); + instruct_srx(cc1200); return status ? 0 : -EIO; } @@ -667,17 +678,17 @@ static int cc1200_start(struct device *dev) { struct cc1200_context *cc1200 = dev->driver_data; - if (!instruct_sidle(&cc1200->spi) || - !instruct_sftx(&cc1200->spi) || - !instruct_sfrx(&cc1200->spi) || - rf_calibrate(&cc1200->spi)) { + if (!instruct_sidle(cc1200) || + !instruct_sftx(cc1200) || + !instruct_sfrx(cc1200) || + rf_calibrate(cc1200)) { SYS_LOG_ERR("Could not proceed"); return -EIO; } enable_gpio0_interrupt(cc1200, true); - _cc1200_print_status(get_status(&cc1200->spi)); + _cc1200_print_status(get_status(cc1200)); return 0; } @@ -688,7 +699,7 @@ static int cc1200_stop(struct device *dev) enable_gpio0_interrupt(cc1200, false); - if (!instruct_spwd(&cc1200->spi)) { + if (!instruct_spwd(cc1200)) { SYS_LOG_ERR("Could not proceed"); return -EIO; } @@ -711,7 +722,7 @@ static int power_on_and_setup(struct device *dev) { struct cc1200_context *cc1200 = dev->driver_data; - if (!instruct_sres(&cc1200->spi)) { + if (!instruct_sres(cc1200)) { SYS_LOG_ERR("Cannot reset"); return -EIO; } @@ -720,25 +731,25 @@ static int power_on_and_setup(struct device *dev) return -EIO; } - if (!write_reg_iocfg3(&cc1200->spi, CC1200_IOCFG3) || - !write_reg_iocfg2(&cc1200->spi, CC1200_IOCFG2) || - !write_reg_iocfg0(&cc1200->spi, CC1200_IOCFG0)) { + if (!write_reg_iocfg3(cc1200, CC1200_IOCFG3) || + !write_reg_iocfg2(cc1200, CC1200_IOCFG2) || + !write_reg_iocfg0(cc1200, CC1200_IOCFG0)) { SYS_LOG_ERR("Cannot configure GPIOs"); return -EIO; } setup_gpio_callback(dev); - return rf_calibrate(&cc1200->spi); + return rf_calibrate(cc1200); } static int configure_spi(struct device *dev) { struct cc1200_context *cc1200 = dev->driver_data; - cc1200->spi.dev = device_get_binding( + cc1200->spi = device_get_binding( CONFIG_IEEE802154_CC1200_SPI_DRV_NAME); - if (!cc1200->spi.dev) { + if (!cc1200->spi) { SYS_LOG_ERR("Unable to get SPI device"); return -ENODEV; } @@ -754,16 +765,16 @@ static int configure_spi(struct device *dev) cs_ctrl.gpio_pin = CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_PIN; cs_ctrl.delay = 0; - cc1200->spi.cs = &cs_ctrl; + cc1200->spi_cfg.cs = &cs_ctrl; SYS_LOG_DBG("SPI GPIO CS configured on %s:%u", CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_DRV_NAME, CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_PIN); } - cc1200->spi.operation = SPI_WORD_SET(8); - cc1200->spi.frequency = CONFIG_IEEE802154_CC1200_SPI_FREQ; - cc1200->spi.slave = CONFIG_IEEE802154_CC1200_SPI_SLAVE; + cc1200->spi_cfg.operation = SPI_WORD_SET(8); + cc1200->spi_cfg.frequency = CONFIG_IEEE802154_CC1200_SPI_FREQ; + cc1200->spi_cfg.slave = CONFIG_IEEE802154_CC1200_SPI_SLAVE; return 0; } diff --git a/drivers/ieee802154/ieee802154_cc1200.h b/drivers/ieee802154/ieee802154_cc1200.h index 58f6a859fecf..8b799f5d1029 100644 --- a/drivers/ieee802154/ieee802154_cc1200.h +++ b/drivers/ieee802154/ieee802154_cc1200.h @@ -24,7 +24,8 @@ struct cc1200_context { /**************************/ struct cc1200_gpio_configuration *gpios; struct gpio_callback rx_tx_cb; - struct spi_config spi; + struct device *spi; + struct spi_config spi_cfg; u8_t mac_addr[8]; /************RF************/ const struct cc1200_rf_registers_set *rf_settings; @@ -46,45 +47,45 @@ struct cc1200_context { *************************** */ -bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr, +bool _cc1200_access_reg(struct cc1200_context *ctx, bool read, u8_t addr, void *data, size_t length, bool extended, bool burst); -static inline u8_t _cc1200_read_single_reg(struct spi_config *spi, +static inline u8_t _cc1200_read_single_reg(struct cc1200_context *ctx, u8_t addr, bool extended) { u8_t val; - if (_cc1200_access_reg(spi, true, addr, &val, 1, extended, false)) { + if (_cc1200_access_reg(ctx, true, addr, &val, 1, extended, false)) { return val; } return 0; } -static inline bool _cc1200_write_single_reg(struct spi_config *spi, +static inline bool _cc1200_write_single_reg(struct cc1200_context *ctx, u8_t addr, u8_t val, bool extended) { - return _cc1200_access_reg(spi, false, addr, &val, 1, extended, false); + return _cc1200_access_reg(ctx, false, addr, &val, 1, extended, false); } -static inline bool _cc1200_instruct(struct spi_config *spi, u8_t addr) +static inline bool _cc1200_instruct(struct cc1200_context *ctx, u8_t addr) { - return _cc1200_access_reg(spi, false, addr, NULL, 0, false, false); + return _cc1200_access_reg(ctx, false, addr, NULL, 0, false, false); } #define DEFINE_REG_READ(__reg_name, __reg_addr, __ext) \ - static inline u8_t read_reg_##__reg_name(struct spi_config *spi) \ + static inline u8_t read_reg_##__reg_name(struct cc1200_context *ctx) \ { \ /*SYS_LOG_DBG("");*/ \ - return _cc1200_read_single_reg(spi, __reg_addr, __ext); \ + return _cc1200_read_single_reg(ctx, __reg_addr, __ext); \ } #define DEFINE_REG_WRITE(__reg_name, __reg_addr, __ext) \ - static inline bool write_reg_##__reg_name(struct spi_config *spi, \ + static inline bool write_reg_##__reg_name(struct cc1200_context *ctx, \ u8_t val) \ { \ /*SYS_LOG_DBG("");*/ \ - return _cc1200_write_single_reg(spi, __reg_addr, \ + return _cc1200_write_single_reg(ctx, __reg_addr, \ val, __ext); \ } @@ -106,10 +107,10 @@ DEFINE_REG_READ(num_rxbytes, CC1200_REG_NUM_RXBYTES, true) */ #define DEFINE_STROBE_INSTRUCTION(__ins_name, __ins_addr) \ - static inline bool instruct_##__ins_name(struct spi_config *spi) \ + static inline bool instruct_##__ins_name(struct cc1200_context *ctx) \ { \ /*SYS_LOG_DBG("");*/ \ - return _cc1200_instruct(spi, __ins_addr); \ + return _cc1200_instruct(ctx, __ins_addr); \ } DEFINE_STROBE_INSTRUCTION(sres, CC1200_INS_SRES) diff --git a/drivers/ieee802154/ieee802154_cc2520.c b/drivers/ieee802154/ieee802154_cc2520.c index 8fa32a6327b8..9ed75ccbe1fe 100644 --- a/drivers/ieee802154/ieee802154_cc2520.c +++ b/drivers/ieee802154/ieee802154_cc2520.c @@ -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; - - spi->cmd_buf[0] = freg ? CC2520_INS_REGRD | addr : CC2520_INS_MEMRD; - spi->cmd_buf[1] = freg ? 0 : addr; - spi->cmd_buf[2] = 0; - - 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]; - } + u8_t cmd_buf[2]; + struct spi_buf buf[2] = { + { + .buf = cmd_buf, + .len = 1, + }, + { + .buf = data, + .len = length, - return 0; -} - -bool _cc2520_write_reg(struct cc2520_spi *spi, bool freg, - u8_t addr, u8_t value) -{ - u8_t len = freg ? 2 : 3; + } + }; + struct spi_buf_set tx = { + .buffers = buf, + }; - 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); + cmd_buf[0] = ins; - return (spi_write(spi->dev, spi->cmd_buf, len) == 0); -} + 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); + } -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 + if (read) { + const struct spi_buf_set rx = { + .buffers = buf, + .count = 2 + }; - cmd_data[0] = CC2520_INS_MEMWR | (addr >> 8); - cmd_data[1] = addr; + tx.count = 1; - memcpy(&cmd_data[2], data_buf, len); + return (spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx) == 0); + } - spi_slave_select(spi->dev, spi->slave); + tx.count = data ? 2 : 1; - return (spi_write(spi->dev, cmd_data, len + 2) == 0); + return (spi_write(ctx->spi, &ctx->spi_cfg, &tx) == 0); } -static u8_t _cc2520_status(struct cc2520_spi *spi) +static inline u8_t _cc2520_status(struct cc2520_context *ctx) { - spi->cmd_buf[0] = CC2520_INS_SNOP; - - spi_slave_select(spi->dev, spi->slave); + u8_t status; - 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; - - 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; - } + u8_t fcs[2]; - 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; - } + if (!_cc2520_access(ctx, true, CC2520_INS_RXBUF, 0, &fcs, 2)) { + return false; + } - noise_buf = &pkt->frags->data[pkt->frags->len - 2]; + if (!(fcs[1] & CC2520_FCS_CRC_OK)) { + return false; } - insert_radio_noise_details(pkt, noise_buf); + 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 @@ static int cc2520_tx(struct device *dev, _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,86 +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) { - u8_t cmd[9]; - int ret; - - SYS_LOG_DBG("CCM(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_CCM | 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("CCM Failed"); - return false; - } - - return true; + return _cc2520_access(ctx, false, CC2520_INS_MEMWR, + addr, data_buf, len); } -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) +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("UCCM(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_UCCM | 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; @@ -1242,12 +1169,12 @@ static inline bool instruct_uccm(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("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; } diff --git a/drivers/ieee802154/ieee802154_cc2520.h b/drivers/ieee802154/ieee802154_cc2520.h index 07c3eddcbd0b..69ab871b202c 100644 --- a/drivers/ieee802154/ieee802154_cc2520.h +++ b/drivers/ieee802154/ieee802154_cc2520.h @@ -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 - }; - - spi_slave_select(spi->dev, spi->slave); + u8_t snop[1] = { CC2520_INS_SNOP }; - 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) diff --git a/drivers/ieee802154/ieee802154_mcr20a.c b/drivers/ieee802154/ieee802154_mcr20a.c index 3d1e3ef5f92d..e5ec6daa5574 100644 --- a/drivers/ieee802154/ieee802154_mcr20a.c +++ b/drivers/ieee802154/ieee802154_mcr20a.c @@ -147,128 +147,121 @@ static const u16_t pll_frac_lt[16] = { #define _usleep(usec) k_busy_wait(usec) /* Read direct (dreg is true) or indirect register (dreg is false) */ -u8_t _mcr20a_read_reg(struct mcr20a_spi *spi, bool dreg, u8_t addr) +u8_t _mcr20a_read_reg(struct mcr20a_context *dev, bool dreg, u8_t addr) { + u8_t cmd_buf[3] = { + dreg ? (MCR20A_REG_READ | addr) : + (MCR20A_IAR_INDEX | MCR20A_REG_WRITE), + dreg ? 0 : (addr | MCR20A_REG_READ), + 0 + }; u8_t len = dreg ? 2 : 3; + const struct spi_buf buf = { + .buf = cmd_buf, + .len = len + }; + const struct spi_buf_set tx = { + .buffers = &buf, + .count = 1 + }; + const struct spi_buf_set rx = { + .buffers = &buf, + .count = 1 + }; - k_sem_take(&spi->spi_sem, K_FOREVER); - - spi->cmd_buf[0] = dreg ? (MCR20A_REG_READ | addr) : - (MCR20A_IAR_INDEX | MCR20A_REG_WRITE); - spi->cmd_buf[1] = dreg ? 0 : (addr | MCR20A_REG_READ); - spi->cmd_buf[2] = 0; - - spi_slave_select(spi->dev, spi->slave); - - if (spi_transceive(spi->dev, spi->cmd_buf, len, - spi->cmd_buf, len) == 0) { - k_sem_give(&spi->spi_sem); - return spi->cmd_buf[len - 1]; + if (spi_transceive(dev->spi, &dev->spi_cfg, &tx, &rx) == 0) { + return cmd_buf[len - 1]; } SYS_LOG_ERR("Failed"); - k_sem_give(&spi->spi_sem); return 0; } /* Write direct (dreg is true) or indirect register (dreg is false) */ -bool _mcr20a_write_reg(struct mcr20a_spi *spi, bool dreg, u8_t addr, +bool _mcr20a_write_reg(struct mcr20a_context *dev, bool dreg, u8_t addr, u8_t value) { - u8_t len = dreg ? 2 : 3; - bool retval; - - k_sem_take(&spi->spi_sem, K_FOREVER); - - spi->cmd_buf[0] = dreg ? (MCR20A_REG_WRITE | addr) : - (MCR20A_IAR_INDEX | MCR20A_REG_WRITE); - spi->cmd_buf[1] = dreg ? value : (addr | MCR20A_REG_WRITE); - spi->cmd_buf[2] = dreg ? 0 : value; - - spi_slave_select(spi->dev, spi->slave); - retval = (spi_write(spi->dev, spi->cmd_buf, len) == 0); - - k_sem_give(&spi->spi_sem); + u8_t cmd_buf[3] = { + dreg ? (MCR20A_REG_WRITE | addr) : + (MCR20A_IAR_INDEX | MCR20A_REG_WRITE), + dreg ? value : (addr | MCR20A_REG_WRITE), + dreg ? 0 : value + }; + const struct spi_buf buf = { + .buf = cmd_buf, + .len = dreg ? 2 : 3 + }; + const struct spi_buf_set tx = { + .buffers = &buf, + .count = 1 + }; - return retval; + return (spi_write(dev->spi, &dev->spi_cfg, &tx) == 0); } /* Write multiple bytes to direct or indirect register */ -bool _mcr20a_write_burst(struct mcr20a_spi *spi, bool dreg, u16_t addr, +bool _mcr20a_write_burst(struct mcr20a_context *dev, bool dreg, u16_t addr, u8_t *data_buf, u8_t len) { - bool retval; - - if ((len + 2) > sizeof(spi->cmd_buf)) { - SYS_LOG_ERR("cmd buffer too small"); - return false; - } - - k_sem_take(&spi->spi_sem, K_FOREVER); - - if (dreg) { - spi->cmd_buf[0] = MCR20A_REG_WRITE | addr; - memcpy(&spi->cmd_buf[1], data_buf, len); - len += 1; - } else { - spi->cmd_buf[0] = MCR20A_IAR_INDEX | MCR20A_REG_WRITE; - spi->cmd_buf[1] = addr | MCR20A_REG_WRITE; - memcpy(&spi->cmd_buf[2], data_buf, len); - len += 2; - } - - spi_slave_select(spi->dev, spi->slave); - retval = (spi_write(spi->dev, spi->cmd_buf, len) == 0); - - k_sem_give(&spi->spi_sem); + u8_t cmd_buf[2] = { + dreg ? MCR20A_REG_WRITE | addr : + MCR20A_IAR_INDEX | MCR20A_REG_WRITE, + dreg ? 0 : addr | MCR20A_REG_WRITE + }; + struct spi_buf bufs[2] = { + { + .buf = cmd_buf, + .len = dreg ? 1 : 2 + }, + { + .buf = data_buf, + .len = len + } + }; + const struct spi_buf_set tx = { + .buffers = bufs, + .count = 2 + }; - return retval; + return (spi_write(dev->spi, &dev->spi_cfg, &tx) == 0); } /* Read multiple bytes from direct or indirect register */ -bool _mcr20a_read_burst(struct mcr20a_spi *spi, bool dreg, u16_t addr, +bool _mcr20a_read_burst(struct mcr20a_context *dev, bool dreg, u16_t addr, u8_t *data_buf, u8_t len) { - if ((len + 2) > sizeof(spi->cmd_buf)) { - SYS_LOG_ERR("cmd buffer too small"); - return false; - } - - k_sem_take(&spi->spi_sem, K_FOREVER); - - if (dreg) { - spi->cmd_buf[0] = MCR20A_REG_READ | addr; - len += 1; - } else { - spi->cmd_buf[0] = MCR20A_IAR_INDEX | MCR20A_REG_WRITE; - spi->cmd_buf[1] = addr | MCR20A_REG_READ; - len += 2; - } - - spi_slave_select(spi->dev, spi->slave); - - if (spi_transceive(spi->dev, spi->cmd_buf, len, - spi->cmd_buf, len) != 0) { - k_sem_give(&spi->spi_sem); - return false; - } - - if (dreg) { - memcpy(data_buf, &spi->cmd_buf[1], len - 1); - } else { - memcpy(data_buf, &spi->cmd_buf[2], len - 2); - } - - k_sem_give(&spi->spi_sem); + u8_t cmd_buf[2] = { + dreg ? MCR20A_REG_READ | addr : + MCR20A_IAR_INDEX | MCR20A_REG_WRITE, + dreg ? 0 : addr | MCR20A_REG_READ + }; + struct spi_buf bufs[2] = { + { + .buf = cmd_buf, + .len = dreg ? 1 : 2 + }, + { + .buf = data_buf, + .len = len + } + }; + const struct spi_buf_set tx = { + .buffers = bufs, + .count = 1 + }; + const struct spi_buf_set rx = { + .buffers = bufs, + .count = 2 + }; - return true; + return (spi_transceive(dev->spi, &dev->spi_cfg, &tx, &rx) == 0); } /* Mask (msk is true) or unmask all interrupts from asserting IRQ_B */ static bool mcr20a_mask_irqb(struct mcr20a_context *dev, bool msk) { - u8_t ctrl4 = read_reg_phy_ctrl4(&dev->spi); + u8_t ctrl4 = read_reg_phy_ctrl4(dev); if (msk) { ctrl4 |= MCR20A_PHY_CTRL4_TRCV_MSK; @@ -276,7 +269,7 @@ static bool mcr20a_mask_irqb(struct mcr20a_context *dev, bool msk) ctrl4 &= ~MCR20A_PHY_CTRL4_TRCV_MSK; } - return write_reg_phy_ctrl4(&dev->spi, ctrl4); + return write_reg_phy_ctrl4(dev, ctrl4); } /** Set an timeout value for the given compare register */ @@ -288,7 +281,7 @@ static int mcr20a_timer_set(struct mcr20a_context *mcr20a, u32_t next; bool retval; - if (!read_burst_event_timer(&mcr20a->spi, (u8_t *)&now)) { + if (!read_burst_event_timer(mcr20a, (u8_t *)&now)) { goto error; } @@ -299,16 +292,16 @@ static int mcr20a_timer_set(struct mcr20a_context *mcr20a, switch (cmp_reg) { case 1: - retval = write_burst_t1cmp(&mcr20a->spi, (u8_t *)&next); + retval = write_burst_t1cmp(mcr20a, (u8_t *)&next); break; case 2: - retval = write_burst_t2cmp(&mcr20a->spi, (u8_t *)&next); + retval = write_burst_t2cmp(mcr20a, (u8_t *)&next); break; case 3: - retval = write_burst_t3cmp(&mcr20a->spi, (u8_t *)&next); + retval = write_burst_t3cmp(mcr20a, (u8_t *)&next); break; case 4: - retval = write_burst_t4cmp(&mcr20a->spi, (u8_t *)&next); + retval = write_burst_t4cmp(mcr20a, (u8_t *)&next); break; default: goto error; @@ -331,18 +324,18 @@ static int mcr20a_timer_init(struct device *dev, u8_t tb) u8_t buf[3] = {0, 0, 0}; u8_t ctrl4; - if (!write_reg_tmr_prescale(&mcr20a->spi, + if (!write_reg_tmr_prescale(mcr20a, set_bits_tmr_prescale(tb))) { goto error; } - if (!write_burst_t1cmp(&mcr20a->spi, buf)) { + if (!write_burst_t1cmp(mcr20a, buf)) { goto error; } - ctrl4 = read_reg_phy_ctrl4(&mcr20a->spi); + ctrl4 = read_reg_phy_ctrl4(mcr20a); ctrl4 |= MCR20A_PHY_CTRL4_TMRLOAD; - if (!write_reg_phy_ctrl4(&mcr20a->spi, ctrl4)) { + if (!write_reg_phy_ctrl4(mcr20a, ctrl4)) { goto error; } @@ -366,16 +359,16 @@ static int mcr20a_t4cmp_set(struct mcr20a_context *mcr20a, } /* enable and clear irq for the timer 4 */ - irqsts3 = read_reg_irqsts3(&mcr20a->spi); + irqsts3 = read_reg_irqsts3(mcr20a); irqsts3 &= ~MCR20A_IRQSTS3_TMR4MSK; irqsts3 |= MCR20A_IRQSTS3_TMR4IRQ; - if (!write_reg_irqsts3(&mcr20a->spi, irqsts3)) { + if (!write_reg_irqsts3(mcr20a, irqsts3)) { goto error; } - ctrl3 = read_reg_phy_ctrl3(&mcr20a->spi); + ctrl3 = read_reg_phy_ctrl3(mcr20a); ctrl3 |= MCR20A_PHY_CTRL3_TMR4CMP_EN; - if (!write_reg_phy_ctrl3(&mcr20a->spi, ctrl3)) { + if (!write_reg_phy_ctrl3(mcr20a, ctrl3)) { goto error; } @@ -392,15 +385,15 @@ static int mcr20a_t4cmp_clear(struct mcr20a_context *mcr20a) u8_t irqsts3; u8_t ctrl3; - ctrl3 = read_reg_phy_ctrl3(&mcr20a->spi); + ctrl3 = read_reg_phy_ctrl3(mcr20a); ctrl3 &= ~MCR20A_PHY_CTRL3_TMR4CMP_EN; - if (!write_reg_phy_ctrl3(&mcr20a->spi, ctrl3)) { + if (!write_reg_phy_ctrl3(mcr20a, ctrl3)) { goto error; } - irqsts3 = read_reg_irqsts3(&mcr20a->spi); + irqsts3 = read_reg_irqsts3(mcr20a); irqsts3 |= MCR20A_IRQSTS3_TMR4IRQ; - if (!write_reg_irqsts3(&mcr20a->spi, irqsts3)) { + if (!write_reg_irqsts3(mcr20a, irqsts3)) { goto error; } @@ -417,7 +410,7 @@ static inline void _xcvseq_wait_until_idle(struct mcr20a_context *mcr20a) u8_t retries = MCR20A_GET_SEQ_STATE_RETRIES; do { - state = read_reg_seq_state(&mcr20a->spi); + state = read_reg_seq_state(mcr20a); retries--; } while ((state & MCR20A_SEQ_STATE_MASK) && retries); @@ -431,7 +424,7 @@ static inline int mcr20a_abort_sequence(struct mcr20a_context *mcr20a, { u8_t ctrl1; - ctrl1 = read_reg_phy_ctrl1(&mcr20a->spi); + ctrl1 = read_reg_phy_ctrl1(mcr20a); SYS_LOG_DBG("CTRL1 0x%02x", ctrl1); if (((ctrl1 & MCR20A_PHY_CTRL1_XCVSEQ_MASK) == MCR20A_XCVSEQ_TX) || @@ -443,14 +436,14 @@ static inline int mcr20a_abort_sequence(struct mcr20a_context *mcr20a, /* Abort ongoing sequence */ ctrl1 &= ~MCR20A_PHY_CTRL1_XCVSEQ_MASK; - if (!write_reg_phy_ctrl1(&mcr20a->spi, ctrl1)) { + if (!write_reg_phy_ctrl1(mcr20a, ctrl1)) { return -1; } _xcvseq_wait_until_idle(mcr20a); /* Clear relevant interrupt flags */ - if (!write_reg_irqsts1(&mcr20a->spi, MCR20A_IRQSTS1_IRQ_MASK)) { + if (!write_reg_irqsts1(mcr20a, MCR20A_IRQSTS1_IRQ_MASK)) { return -1; } @@ -464,7 +457,7 @@ static inline int mcr20a_set_sequence(struct mcr20a_context *mcr20a, u8_t ctrl1 = 0; seq = set_bits_phy_ctrl1_xcvseq(seq); - ctrl1 = read_reg_phy_ctrl1(&mcr20a->spi); + ctrl1 = read_reg_phy_ctrl1(mcr20a); ctrl1 &= ~MCR20A_PHY_CTRL1_XCVSEQ_MASK; if ((seq == MCR20A_XCVSEQ_TX_RX) && @@ -475,7 +468,7 @@ static inline int mcr20a_set_sequence(struct mcr20a_context *mcr20a, } ctrl1 |= seq; - if (!write_reg_phy_ctrl1(&mcr20a->spi, ctrl1)) { + if (!write_reg_phy_ctrl1(mcr20a, ctrl1)) { return -EIO; } @@ -515,31 +508,33 @@ static inline u8_t *get_mac(struct device *dev) return mcr20a->mac_addr; } -static inline bool read_rxfifo_content(struct mcr20a_spi *spi, +static inline bool read_rxfifo_content(struct mcr20a_context *dev, struct net_buf *buf, u8_t len) { - u8_t data[1 + MCR20A_PSDU_LENGTH]; - - if (len > MCR20A_PSDU_LENGTH) { - SYS_LOG_ERR("Packet length too large"); - return false; - } - - k_sem_take(&spi->spi_sem, K_FOREVER); - - data[0] = MCR20A_BUF_READ; - spi_slave_select(spi->dev, spi->slave); + u8_t cmd = MCR20A_BUF_READ; + struct spi_buf bufs[2] = { + { + .buf = &cmd, + .len = 1 + }, + { + .buf = buf->data, + .len = len + } + }; + const struct spi_buf_set tx = { + .buffers = bufs, + .count = 1 + }; + const struct spi_buf_set rx = { + .buffers = bufs, + .count = 2 + }; - if (spi_transceive(spi->dev, data, len+1, data, len+1) != 0) { - k_sem_give(&spi->spi_sem); - return false; + if (spi_transceive(dev->spi, &dev->spi_cfg, &tx, &rx) == 0) { + net_buf_add(buf, len); } - memcpy(buf->data, &data[1], len); - net_buf_add(buf, len); - - k_sem_give(&spi->spi_sem); - return true; } @@ -565,7 +560,7 @@ static inline void mcr20a_rx(struct mcr20a_context *mcr20a, u8_t len) net_pkt_frag_insert(pkt, frag); - if (!read_rxfifo_content(&mcr20a->spi, frag, pkt_len)) { + if (!read_rxfifo_content(mcr20a, frag, pkt_len)) { SYS_LOG_ERR("No content read"); goto out; } @@ -575,7 +570,7 @@ static inline void mcr20a_rx(struct mcr20a_context *mcr20a, u8_t len) goto out; } - net_pkt_set_ieee802154_lqi(pkt, read_reg_lqi_value(&mcr20a->spi)); + net_pkt_set_ieee802154_lqi(pkt, read_reg_lqi_value(mcr20a)); net_pkt_set_ieee802154_rssi(pkt, mcr20a_get_rssi( net_pkt_ieee802154_lqi(pkt))); @@ -738,7 +733,7 @@ static void mcr20a_thread_main(void *arg) } /* Read the register from IRQSTS1 until CTRL4 */ - if (!read_burst_irqsts1_ctrl4(&mcr20a->spi, dregs)) { + if (!read_burst_irqsts1_ctrl4(mcr20a, dregs)) { SYS_LOG_ERR("Failed to read register"); goto unmask_irqb; } @@ -765,17 +760,17 @@ static void mcr20a_thread_main(void *arg) if (set_new_seq) { /* Reset sequence manager */ ctrl1 &= ~MCR20A_PHY_CTRL1_XCVSEQ_MASK; - if (!write_reg_phy_ctrl1(&mcr20a->spi, ctrl1)) { + if (!write_reg_phy_ctrl1(mcr20a, ctrl1)) { SYS_LOG_ERR("Failed to reset SEQ manager"); } _xcvseq_wait_until_idle(mcr20a); - if (!write_burst_irqsts1_ctrl1(&mcr20a->spi, dregs)) { + if (!write_burst_irqsts1_ctrl1(mcr20a, dregs)) { SYS_LOG_ERR("Failed to write CTRL1"); } } else { - if (!write_burst_irqsts1_irqsts3(&mcr20a->spi, dregs)) { + if (!write_burst_irqsts1_irqsts3(mcr20a, dregs)) { SYS_LOG_ERR("Failed to write IRQSTS3"); } } @@ -835,11 +830,11 @@ static int mcr20a_set_cca_mode(struct device *dev, u8_t mode) struct mcr20a_context *mcr20a = dev->driver_data; u8_t ctrl4; - ctrl4 = read_reg_phy_ctrl4(&mcr20a->spi); + ctrl4 = read_reg_phy_ctrl4(mcr20a); ctrl4 &= ~MCR20A_PHY_CTRL4_CCATYPE_MASK; ctrl4 |= set_bits_phy_ctrl4_ccatype(mode); - if (!write_reg_phy_ctrl4(&mcr20a->spi, ctrl4)) { + if (!write_reg_phy_ctrl4(mcr20a, ctrl4)) { SYS_LOG_ERR("Failed"); return -EIO; } @@ -922,7 +917,7 @@ static int mcr20a_set_channel(struct device *dev, u16_t channel) goto out; } - ctrl1 = read_reg_phy_ctrl1(&mcr20a->spi); + ctrl1 = read_reg_phy_ctrl1(mcr20a); if (mcr20a_abort_sequence(mcr20a, true)) { SYS_LOG_ERR("Failed to reset XCV sequence"); @@ -935,7 +930,7 @@ static int mcr20a_set_channel(struct device *dev, u16_t channel) buf[1] = (u8_t)pll_frac_lt[channel]; buf[2] = (u8_t)(pll_frac_lt[channel] >> 8); - if (!write_burst_pll_int0(&mcr20a->spi, buf)) { + if (!write_burst_pll_int0(mcr20a, buf)) { SYS_LOG_ERR("Failed to set PLL"); goto out; } @@ -965,7 +960,7 @@ static int mcr20a_set_pan_id(struct device *dev, u16_t pan_id) pan_id = sys_le16_to_cpu(pan_id); k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER); - if (!write_burst_pan_id(&mcr20a->spi, (u8_t *) &pan_id)) { + if (!write_burst_pan_id(mcr20a, (u8_t *) &pan_id)) { SYS_LOG_ERR("Failed"); k_mutex_unlock(&mcr20a->phy_mutex); return -EIO; @@ -984,7 +979,7 @@ static int mcr20a_set_short_addr(struct device *dev, u16_t short_addr) short_addr = sys_le16_to_cpu(short_addr); k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER); - if (!write_burst_short_addr(&mcr20a->spi, (u8_t *) &short_addr)) { + if (!write_burst_short_addr(mcr20a, (u8_t *) &short_addr)) { SYS_LOG_ERR("Failed"); k_mutex_unlock(&mcr20a->phy_mutex); return -EIO; @@ -1002,7 +997,7 @@ static int mcr20a_set_ieee_addr(struct device *dev, const u8_t *ieee_addr) k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER); - if (!write_burst_ext_addr(&mcr20a->spi, (void *)ieee_addr)) { + if (!write_burst_ext_addr(mcr20a, (void *)ieee_addr)) { SYS_LOG_ERR("Failed"); k_mutex_unlock(&mcr20a->phy_mutex); return -EIO; @@ -1047,7 +1042,7 @@ static int mcr20a_set_txpower(struct device *dev, s16_t dbm) } pwr = pow_lt[dbm - MCR20A_OUTPUT_POWER_MIN]; - if (!write_reg_pa_pwr(&mcr20a->spi, set_bits_pa_pwr_val(pwr))) { + if (!write_reg_pa_pwr(mcr20a, set_bits_pa_pwr_val(pwr))) { goto error; } @@ -1060,40 +1055,36 @@ static int mcr20a_set_txpower(struct device *dev, s16_t dbm) return -EIO; } -static inline bool write_txfifo_content(struct mcr20a_spi *spi, +static inline bool write_txfifo_content(struct mcr20a_context *dev, struct net_pkt *pkt, struct net_buf *frag) { - u8_t cmd[2 + MCR20A_PSDU_LENGTH]; - u8_t payload_len = net_pkt_ll_reserve(pkt) + frag->len; - u8_t *payload = frag->data - net_pkt_ll_reserve(pkt); - bool retval; - - k_sem_take(&spi->spi_sem, K_FOREVER); - - cmd[0] = MCR20A_BUF_WRITE; - /** - * The length of the packet (PSDU + FSC), - * is stored at index 0, followed by the PSDU. - * Note: maximum FRAME_LEN is 125 + MCR20A_FCS_LENGTH - */ - cmd[1] = payload_len + MCR20A_FCS_LENGTH; + size_t payload_len = net_pkt_ll_reserve(pkt) + frag->len; + u8_t cmd_buf[2] = { + MCR20A_BUF_WRITE, + payload_len + MCR20A_FCS_LENGTH + }; + const struct spi_buf bufs[2] = { + { + .buf = cmd_buf, + .len = 2 + }, + { + .buf = frag->data - net_pkt_ll_reserve(pkt), + .len = payload_len + } + }; + const struct spi_buf_set tx = { + .buffers = bufs, + .count = 2 + }; if (payload_len > MCR20A_PSDU_LENGTH) { SYS_LOG_ERR("Payload too long"); return 0; } - memcpy(&cmd[2], payload, payload_len); - - spi_slave_select(spi->dev, spi->slave); - - retval = (spi_transceive(spi->dev, - cmd, (2 + payload_len), - cmd, (2 + payload_len)) == 0); - - k_sem_give(&spi->spi_sem); - return retval; + return (spi_write(dev->spi, &dev->spi_cfg, &tx) == 0); } static int mcr20a_tx(struct device *dev, @@ -1120,7 +1111,7 @@ static int mcr20a_tx(struct device *dev, goto error; } - if (!write_txfifo_content(&mcr20a->spi, pkt, frag)) { + if (!write_txfifo_content(mcr20a, pkt, frag)) { SYS_LOG_ERR("Did not write properly into TX FIFO"); goto error; } @@ -1162,7 +1153,7 @@ static int mcr20a_start(struct device *dev) k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER); enable_irqb_interrupt(mcr20a, false); - if (!write_reg_pwr_modes(&mcr20a->spi, MCR20A_PM_AUTODOZE)) { + if (!write_reg_pwr_modes(mcr20a, MCR20A_PM_AUTODOZE)) { SYS_LOG_ERR("Error starting MCR20A"); goto error; } @@ -1170,7 +1161,7 @@ static int mcr20a_start(struct device *dev) do { _usleep(50); timeout--; - status = read_reg_pwr_modes(&mcr20a->spi); + status = read_reg_pwr_modes(mcr20a); } while (!(status & MCR20A_PWR_MODES_XTAL_READY) && timeout); if (!(status & MCR20A_PWR_MODES_XTAL_READY)) { @@ -1179,10 +1170,10 @@ static int mcr20a_start(struct device *dev) } /* Clear all interrupt flags */ - write_reg_irqsts1(&mcr20a->spi, MCR20A_IRQSTS1_IRQ_MASK); - write_reg_irqsts2(&mcr20a->spi, MCR20A_IRQSTS2_IRQ_MASK); - write_reg_irqsts3(&mcr20a->spi, MCR20A_IRQSTS3_IRQ_MASK | - MCR20A_IRQSTS3_TMR_MASK); + write_reg_irqsts1(mcr20a, MCR20A_IRQSTS1_IRQ_MASK); + write_reg_irqsts2(mcr20a, MCR20A_IRQSTS2_IRQ_MASK); + write_reg_irqsts3(mcr20a, MCR20A_IRQSTS3_IRQ_MASK | + MCR20A_IRQSTS3_TMR_MASK); if (mcr20a_abort_sequence(mcr20a, true)) { SYS_LOG_ERR("Failed to reset XCV sequence"); @@ -1236,7 +1227,7 @@ static int mcr20a_stop(struct device *dev) power_mode = MCR20A_PM_HIBERNATE; } - if (!write_reg_pwr_modes(&mcr20a->spi, power_mode)) { + if (!write_reg_pwr_modes(mcr20a, power_mode)) { goto error; } @@ -1253,32 +1244,21 @@ static int mcr20a_stop(struct device *dev) static int mcr20a_update_overwrites(struct mcr20a_context *dev) { - struct mcr20a_spi *spi = &dev->spi; - - if (!write_reg_overwrite_ver(spi, overwrites_direct[0].data)) { + if (!write_reg_overwrite_ver(dev, overwrites_direct[0].data)) { goto error; } - k_sem_take(&spi->spi_sem, K_FOREVER); - for (u8_t i = 0; i < sizeof(overwrites_indirect) / sizeof(overwrites_t); i++) { - spi->cmd_buf[0] = MCR20A_IAR_INDEX | MCR20A_REG_WRITE; - spi->cmd_buf[1] = overwrites_indirect[i].address; - spi->cmd_buf[2] = overwrites_indirect[i].data; - - spi_slave_select(spi->dev, spi->slave); - - if (spi_write(spi->dev, spi->cmd_buf, 3)) { - k_sem_give(&spi->spi_sem); + if (_mcr20a_write_reg(dev, true, + overwrites_indirect[i].address, + overwrites_indirect[i].data)) { goto error; } } - k_sem_give(&spi->spi_sem); - return 0; error: @@ -1313,18 +1293,18 @@ static int power_on_and_setup(struct device *dev) } tmp = MCR20A_CLK_OUT_CONFIG | MCR20A_CLK_OUT_EXTEND; - write_reg_clk_out_ctrl(&mcr20a->spi, tmp); + write_reg_clk_out_ctrl(mcr20a, tmp); - if (read_reg_clk_out_ctrl(&mcr20a->spi) != tmp) { + if (read_reg_clk_out_ctrl(mcr20a) != tmp) { SYS_LOG_ERR("Failed to get device up"); return -EIO; } /* Clear all interrupt flags */ - write_reg_irqsts1(&mcr20a->spi, MCR20A_IRQSTS1_IRQ_MASK); - write_reg_irqsts2(&mcr20a->spi, MCR20A_IRQSTS2_IRQ_MASK); - write_reg_irqsts3(&mcr20a->spi, MCR20A_IRQSTS3_IRQ_MASK | - MCR20A_IRQSTS3_TMR_MASK); + write_reg_irqsts1(mcr20a, MCR20A_IRQSTS1_IRQ_MASK); + write_reg_irqsts2(mcr20a, MCR20A_IRQSTS2_IRQ_MASK); + write_reg_irqsts3(mcr20a, MCR20A_IRQSTS3_IRQ_MASK | + MCR20A_IRQSTS3_TMR_MASK); mcr20a_update_overwrites(mcr20a); mcr20a_timer_init(dev, MCR20A_TIMEBASE_62500HZ); @@ -1332,17 +1312,17 @@ static int power_on_and_setup(struct device *dev) mcr20a_set_txpower(dev, MCR20A_DEFAULT_TX_POWER); mcr20a_set_channel(dev, MCR20A_DEFAULT_CHANNEL); mcr20a_set_cca_mode(dev, 1); - write_reg_rx_wtr_mark(&mcr20a->spi, 8); + write_reg_rx_wtr_mark(mcr20a, 8); /* Configure PHY behaviour */ tmp = MCR20A_PHY_CTRL1_CCABFRTX | MCR20A_PHY_CTRL1_AUTOACK | MCR20A_PHY_CTRL1_RXACKRQD; - write_reg_phy_ctrl1(&mcr20a->spi, tmp); + write_reg_phy_ctrl1(mcr20a, tmp); /* Enable Sequence-end interrupt */ tmp = MCR20A_PHY_CTRL2_SEQMSK; - write_reg_phy_ctrl2(&mcr20a->spi, ~tmp); + write_reg_phy_ctrl2(mcr20a, ~tmp); setup_gpio_callbacks(mcr20a); @@ -1386,30 +1366,39 @@ static inline int configure_gpios(struct device *dev) static inline int configure_spi(struct device *dev) { struct mcr20a_context *mcr20a = dev->driver_data; - struct spi_config spi_conf = { - .config = SPI_WORD(8), - .max_sys_freq = CONFIG_IEEE802154_MCR20A_SPI_FREQ, - }; - mcr20a->spi.dev = device_get_binding( + mcr20a->spi = device_get_binding( CONFIG_IEEE802154_MCR20A_SPI_DRV_NAME); - if (!mcr20a->spi.dev) { + if (!mcr20a->spi) { SYS_LOG_ERR("Unable to get SPI device"); return -ENODEV; } - mcr20a->spi.slave = CONFIG_IEEE802154_MCR20A_SPI_SLAVE; - - if (spi_configure(mcr20a->spi.dev, &spi_conf) != 0 || - spi_slave_select(mcr20a->spi.dev, - mcr20a->spi.slave) != 0) { - mcr20a->spi.dev = NULL; - return -EIO; +#if defined(CONFIG_IEEE802154_MCR20A_GPIO_SPI_CS) + mcr20a->cs_ctrl.gpio_dev = device_get_binding( + CONFIG_IEEE802154_MCR20A_GPIO_SPI_CS_DRV_NAME); + if (!mcr20a->cs_ctrl.gpio_dev) { + SYS_LOG_ERR("Unable to get GPIO SPI CS device"); + return -ENODEV; } + mcr20a->cs_ctrl.gpio_pin = CONFIG_IEEE802154_MCR20A_GPIO_SPI_CS_PIN; + mcr20a->cs_ctrl.delay = 0; + + mcr20a->spi_cfg.cs = &mcr20a->cs_ctrl; + + SYS_LOG_DBG("SPI GPIO CS configured on %s:%u", + CONFIG_IEEE802154_MCR20A_GPIO_SPI_CS_DRV_NAME, + CONFIG_IEEE802154_MCR20A_GPIO_SPI_CS_PIN); +#endif /* CONFIG_IEEE802154_MCR20A_GPIO_SPI_CS */ + + mcr20a->spi_cfg.frequency = CONFIG_IEEE802154_MCR20A_SPI_FREQ; + mcr20a->spi_cfg.operation = SPI_WORD_SET(8); + mcr20a->spi_cfg.slave = CONFIG_IEEE802154_MCR20A_SPI_SLAVE; + SYS_LOG_DBG("SPI configured %s, %d", - CONFIG_IEEE802154_MCR20A_SPI_DRV_NAME, - CONFIG_IEEE802154_MCR20A_SPI_SLAVE); + CONFIG_IEEE802154_MCR20A_SPI_DRV_NAME, + CONFIG_IEEE802154_MCR20A_SPI_SLAVE); return 0; } @@ -1418,8 +1407,6 @@ static int mcr20a_init(struct device *dev) { struct mcr20a_context *mcr20a = dev->driver_data; - k_sem_init(&mcr20a->spi.spi_sem, 1, UINT_MAX); - k_mutex_init(&mcr20a->phy_mutex); k_sem_init(&mcr20a->isr_sem, 0, 1); diff --git a/drivers/ieee802154/ieee802154_mcr20a.h b/drivers/ieee802154/ieee802154_mcr20a.h index 2d64a5e036e6..6801b4fd5d42 100644 --- a/drivers/ieee802154/ieee802154_mcr20a.h +++ b/drivers/ieee802154/ieee802154_mcr20a.h @@ -17,24 +17,17 @@ /* Runtime context structure *************************** */ -struct mcr20a_spi { - struct device *dev; - u32_t slave; - struct k_sem spi_sem; - /** - * cmd_buf will use at most 9 bytes: - * dummy bytes + 8 ieee address bytes - */ - u8_t cmd_buf[12]; -}; - struct mcr20a_context { struct net_if *iface; /**************************/ struct device *irq_gpio; struct device *reset_gpio; struct gpio_callback irqb_cb; - struct mcr20a_spi spi; + struct device *spi; + struct spi_config spi_cfg; +#if defined(CONFIG_IEEE802154_MCR20A_GPIO_SPI_CS) + struct spi_cs_control cs_ctrl; +#endif u8_t mac_addr[8]; struct k_mutex phy_mutex; struct k_sem isr_sem; @@ -49,25 +42,25 @@ struct mcr20a_context { #include "ieee802154_mcr20a_regs.h" -u8_t _mcr20a_read_reg(struct mcr20a_spi *spi, bool dreg, u8_t addr); -bool _mcr20a_write_reg(struct mcr20a_spi *spi, bool dreg, u8_t addr, +u8_t _mcr20a_read_reg(struct mcr20a_context *dev, bool dreg, u8_t addr); +bool _mcr20a_write_reg(struct mcr20a_context *dev, bool dreg, u8_t addr, u8_t value); -bool _mcr20a_write_burst(struct mcr20a_spi *spi, bool dreg, u16_t addr, +bool _mcr20a_write_burst(struct mcr20a_context *dev, bool dreg, u16_t addr, u8_t *data_buf, u8_t len); -bool _mcr20a_read_burst(struct mcr20a_spi *spi, bool dreg, u16_t addr, +bool _mcr20a_read_burst(struct mcr20a_context *dev, bool dreg, u16_t addr, u8_t *data_buf, u8_t len); -#define DEFINE_REG_READ(__reg_name, __reg_addr, __dreg) \ - static inline u8_t read_reg_##__reg_name(struct mcr20a_spi *spi) \ - { \ - return _mcr20a_read_reg(spi, __dreg, __reg_addr); \ +#define DEFINE_REG_READ(__reg_name, __reg_addr, __dreg) \ + static inline u8_t read_reg_##__reg_name(struct mcr20a_context *dev) \ + { \ + return _mcr20a_read_reg(dev, __dreg, __reg_addr); \ } -#define DEFINE_REG_WRITE(__reg_name, __reg_addr, __dreg) \ - static inline bool write_reg_##__reg_name(struct mcr20a_spi *spi, \ - u8_t value) \ - { \ - return _mcr20a_write_reg(spi, __dreg, __reg_addr, value); \ +#define DEFINE_REG_WRITE(__reg_name, __reg_addr, __dreg) \ + static inline bool write_reg_##__reg_name(struct mcr20a_context *dev, \ + u8_t value) \ + { \ + return _mcr20a_write_reg(dev, __dreg, __reg_addr, value); \ } #define DEFINE_DREG_READ(__reg_name, __reg_addr) \ @@ -156,18 +149,18 @@ DEFINE_BITS_SET(pa_pwr_val, MCR20A_PA_PWR, _VAL) DEFINE_BITS_SET(tmr_prescale, MCR20A_TMR_PRESCALE, _VAL) DEFINE_BITS_SET(clk_out_div, MCR20A_CLK_OUT, _DIV) -#define DEFINE_BURST_WRITE(__reg_addr, __addr, __sz, __dreg) \ - static inline bool write_burst_##__reg_addr(struct mcr20a_spi *spi, \ - u8_t *buf) \ - { \ - return _mcr20a_write_burst(spi, __dreg, __addr, buf, __sz); \ +#define DEFINE_BURST_WRITE(__reg_addr, __addr, __sz, __dreg) \ + static inline bool write_burst_##__reg_addr( \ + struct mcr20a_context *dev, u8_t *buf) \ + { \ + return _mcr20a_write_burst(dev, __dreg, __addr, buf, __sz); \ } #define DEFINE_BURST_READ(__reg_addr, __addr, __sz, __dreg) \ - static inline bool read_burst_##__reg_addr(struct mcr20a_spi *spi, \ - u8_t *buf) \ + static inline bool read_burst_##__reg_addr(struct mcr20a_context *dev, \ + u8_t *buf) \ { \ - return _mcr20a_read_burst(spi, __dreg, __addr, buf, __sz); \ + return _mcr20a_read_burst(dev, __dreg, __addr, buf, __sz); \ } DEFINE_BURST_WRITE(t1cmp, MCR20A_T1CMP_LSB, 3, true) diff --git a/drivers/led_strip/Kconfig.apa102 b/drivers/led_strip/Kconfig.apa102 index 804434924335..8f0f6c743c26 100644 --- a/drivers/led_strip/Kconfig.apa102 +++ b/drivers/led_strip/Kconfig.apa102 @@ -7,7 +7,6 @@ menuconfig APA102_STRIP bool "APA102 SPI LED strip driver" depends on SPI - depends on !SPI_LEGACY_API select LED_STRIP_RGB_SCRATCH default n help diff --git a/drivers/led_strip/Kconfig.lpd880x b/drivers/led_strip/Kconfig.lpd880x index ed0eff8c3d75..ee7ff02cbf81 100644 --- a/drivers/led_strip/Kconfig.lpd880x +++ b/drivers/led_strip/Kconfig.lpd880x @@ -7,7 +7,6 @@ menuconfig LPD880X_STRIP bool "Enable LPD880x SPI LED strip driver" depends on SPI - depends on !SPI_LEGACY_API default n help Enable LED strip driver for daisy chains of LPD880x diff --git a/drivers/led_strip/Kconfig.ws2812 b/drivers/led_strip/Kconfig.ws2812 index ebc63e04183d..fc60a64cf501 100644 --- a/drivers/led_strip/Kconfig.ws2812 +++ b/drivers/led_strip/Kconfig.ws2812 @@ -11,7 +11,6 @@ menuconfig WS2812_STRIP bool "Enable WS2812 (and compatible) LED strip driver" depends on SPI - depends on !SPI_LEGACY_API default n help Enable LED strip driver for daisy chains of WS2812-ish diff --git a/drivers/led_strip/apa102.c b/drivers/led_strip/apa102.c index 8bf27a40c441..774a1a157c55 100644 --- a/drivers/led_strip/apa102.c +++ b/drivers/led_strip/apa102.c @@ -9,6 +9,7 @@ #include struct apa102_data { + struct device *spi; struct spi_config cfg; }; @@ -17,7 +18,7 @@ static int apa102_update(struct device *dev, void *buf, size_t size) struct apa102_data *data = dev->driver_data; static const u8_t zeros[] = {0, 0, 0, 0}; static const u8_t ones[] = {0xFF, 0xFF, 0xFF, 0xFF}; - struct spi_buf tx[] = { + const struct spi_buf tx_bufs[] = { { /* Start frame: at least 32 zeros */ .buf = (u8_t *)zeros, @@ -37,8 +38,12 @@ static int apa102_update(struct device *dev, void *buf, size_t size) .len = sizeof(ones), }, }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx) + }; - return spi_write(&data->cfg, tx, ARRAY_SIZE(tx)); + return spi_write(data->spi, &data->cfg, &tx); } static int apa102_update_rgb(struct device *dev, struct led_rgb *pixels, @@ -75,14 +80,12 @@ static int apa102_update_channels(struct device *dev, u8_t *channels, static int apa102_init(struct device *dev) { struct apa102_data *data = dev->driver_data; - struct device *spi; - spi = device_get_binding(CONFIG_APA102_STRIP_BUS_NAME); - if (!spi) { + data->spi = device_get_binding(CONFIG_APA102_STRIP_BUS_NAME); + if (!data->spi) { return -ENODEV; } - data->cfg.dev = spi; data->cfg.frequency = CONFIG_APA102_STRIP_FREQUENCY; data->cfg.operation = SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8); diff --git a/drivers/led_strip/lpd880x.c b/drivers/led_strip/lpd880x.c index 78cc36199648..56a58a00de11 100644 --- a/drivers/led_strip/lpd880x.c +++ b/drivers/led_strip/lpd880x.c @@ -29,6 +29,7 @@ SPI_LINES_SINGLE) struct lpd880x_data { + struct device *spi; struct spi_config config; }; @@ -43,23 +44,33 @@ static int lpd880x_update(struct device *dev, void *data, size_t size) u8_t reset_size = ceiling_fraction(ceiling_fraction(size, 3), 32); u8_t reset_buf[reset_size]; u8_t last = 0x00; - struct spi_buf bufs[3]; + const struct spi_buf bufs[3] = { + { + /* Prepares the strip to shift in new data values. */ + .buf = reset_buf, + .len = reset_size + }, + { + /* Displays the serialized pixel data. */ + .buf = data, + .len = size + }, + { + /* Ensures the last byte of pixel data is displayed. */ + .buf = &last, + .len = sizeof(last) + } + + }; + const struct spi_buf_set tx = { + .buffers = bufs, + .count = 3 + }; size_t rc; - /* Prepares the strip to shift in new data values. */ memset(reset_buf, 0x00, reset_size); - bufs[0].buf = reset_buf; - bufs[0].len = reset_size; - - /* Displays the serialized pixel data. */ - bufs[1].buf = data; - bufs[1].len = size; - /* Ensures the last byte of pixel data is displayed. */ - bufs[2].buf = &last; - bufs[2].len = sizeof(last); - - rc = spi_write(&drv_data->config, bufs, ARRAY_SIZE(bufs)); + rc = spi_write(drv_data->spi, &drv_data->config, &tx); if (rc) { SYS_LOG_ERR("can't update strip: %d", rc); } @@ -112,16 +123,14 @@ static int lpd880x_strip_init(struct device *dev) { struct lpd880x_data *data = dev->driver_data; struct spi_config *config = &data->config; - struct device *spi; - spi = device_get_binding(CONFIG_LPD880X_STRIP_SPI_DEV_NAME); - if (!spi) { + data->spi = device_get_binding(CONFIG_LPD880X_STRIP_SPI_DEV_NAME); + if (!data->spi) { SYS_LOG_ERR("SPI device %s not found", CONFIG_LPD880X_STRIP_SPI_DEV_NAME); return -ENODEV; } - config->dev = spi; config->frequency = CONFIG_LPD880X_STRIP_SPI_BAUD_RATE; config->operation = LPD880X_SPI_OPERATION; config->slave = 0; /* MOSI/CLK only; CS is not supported. */ diff --git a/drivers/led_strip/ws2812.c b/drivers/led_strip/ws2812.c index 2bf421565654..b6e37c38c37b 100644 --- a/drivers/led_strip/ws2812.c +++ b/drivers/led_strip/ws2812.c @@ -48,6 +48,7 @@ #define RESET_NFRAMES ((size_t)ceiling_fraction(3 * SPI_FREQ, 4000000) + 1) struct ws2812_data { + struct device *spi; struct spi_config config; }; @@ -82,17 +83,21 @@ static size_t ws2812_serialize_pixel(u8_t px[32], struct led_rgb *pixel) /* * Latch current color values on strip and reset its state machines. */ -static int ws2812_reset_strip(struct spi_config *config) +static int ws2812_reset_strip(struct ws2812_data *data) { u8_t reset_buf[RESET_NFRAMES]; - struct spi_buf reset = { + const struct spi_buf reset = { .buf = reset_buf, .len = sizeof(reset_buf), }; + const struct spi_buf_set tx = { + .buffers = &reset, + .count = 1 + }; memset(reset_buf, 0x00, sizeof(reset_buf)); - return spi_write(config, &reset, 1); + return spi_write(data->spi, &data->config, &tx); } static int ws2812_strip_update_rgb(struct device *dev, struct led_rgb *pixels, @@ -104,25 +109,29 @@ static int ws2812_strip_update_rgb(struct device *dev, struct led_rgb *pixels, struct spi_buf buf = { .buf = px_buf, }; + const struct spi_buf_set tx = { + .buffers = &buf, + .count = 1 + }; size_t i; int rc; for (i = 0; i < num_pixels; i++) { buf.len = ws2812_serialize_pixel(px_buf, &pixels[i]); - rc = spi_write(config, &buf, 1); + rc = spi_write(drv_data->spi, config, &tx); if (rc) { /* * Latch anything we've shifted out first, to * call visual attention to the problematic * pixel. */ - (void)ws2812_reset_strip(config); + (void)ws2812_reset_strip(drv_data); SYS_LOG_ERR("can't set pixel %u: %d", i, rc); return rc; } } - return ws2812_reset_strip(config); + return ws2812_reset_strip(drv_data); } static int ws2812_strip_update_channels(struct device *dev, u8_t *channels, @@ -131,45 +140,47 @@ static int ws2812_strip_update_channels(struct device *dev, u8_t *channels, struct ws2812_data *drv_data = dev->driver_data; struct spi_config *config = &drv_data->config; u8_t px_buf[8]; /* one byte per bit */ - struct spi_buf buf = { + const struct spi_buf buf = { .buf = px_buf, .len = sizeof(px_buf), }; + const struct spi_buf_set tx = { + .buffers = &buf, + .count = 1 + }; size_t i; int rc; for (i = 0; i < num_channels; i++) { ws2812_serialize_color(px_buf, channels[i]); - rc = spi_write(config, &buf, 1); + rc = spi_write(drv_data->spi, config, &tx); if (rc) { /* * Latch anything we've shifted out first, to * call visual attention to the problematic * pixel. */ - (void)ws2812_reset_strip(config); + (void)ws2812_reset_strip(drv_data); SYS_LOG_ERR("can't set channel %u: %d", i, rc); return rc; } } - return ws2812_reset_strip(config); + return ws2812_reset_strip(drv_data); } static int ws2812_strip_init(struct device *dev) { struct ws2812_data *data = dev->driver_data; struct spi_config *config = &data->config; - struct device *spi; - spi = device_get_binding(CONFIG_WS2812_STRIP_SPI_DEV_NAME); - if (!spi) { + data->spi = device_get_binding(CONFIG_WS2812_STRIP_SPI_DEV_NAME); + if (!data->spi) { SYS_LOG_ERR("SPI device %s not found", CONFIG_WS2812_STRIP_SPI_DEV_NAME); return -ENODEV; } - config->dev = spi; config->frequency = SPI_FREQ; config->operation = SPI_OPER; config->slave = 0; /* MOSI only. */ diff --git a/drivers/sensor/adxl362/adxl362.c b/drivers/sensor/adxl362/adxl362.c index 5eb769c2cc24..d54ee2038b5b 100644 --- a/drivers/sensor/adxl362/adxl362.c +++ b/drivers/sensor/adxl362/adxl362.c @@ -20,68 +20,61 @@ static struct adxl362_data adxl362_data; -static int adxl362_set_reg(struct device *dev, u16_t register_value, - u8_t register_address, u8_t count) +static int adxl362_reg_access(struct adxl362_data *ctx, u8_t cmd, + u8_t reg_addr, void *data, size_t length) { - struct adxl362_data *adxl362_data = dev->driver_data; - u8_t buffer[4]; - int ret; + u8_t access[2] = { cmd, reg_addr }; + const struct spi_buf buf[2] = { + { + .buf = access, + .len = 2 + }, + { + .buf = data, + .len = length + } + }; + struct spi_buf_set tx = { + .buffers = buf, + }; - buffer[0] = ADXL362_WRITE_REG; - buffer[1] = register_address; - buffer[2] = (register_value & 0x00FF); - buffer[3] = (register_value >> 8); + if (cmd == ADXL362_READ_REG) { + const struct spi_buf_set rx = { + .buffers = buf, + .count = 2 + }; - ret = spi_slave_select(adxl362_data->spi, - adxl362_data->spi_slave); - if (ret) { - SYS_LOG_DBG("spi_slave_select FAIL %d\n", ret); - return ret; - } + tx.count = 1; - ret = spi_transceive(adxl362_data->spi, buffer, count + 2, - buffer, count + 2); - if (ret) { - SYS_LOG_DBG("spi_transceive FAIL %d\n", ret); - return ret; + return spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx); } - return 0; + tx.count = 2; + + return spi_write(ctx->spi, &ctx->spi_cfg, &tx); } -static int adxl362_get_reg(struct device *dev, u8_t *read_buf, - u8_t register_address, u8_t count) +static inline int adxl362_set_reg(struct device *dev, u16_t register_value, + u8_t register_address, u8_t count) { struct adxl362_data *adxl362_data = dev->driver_data; - u8_t buffer[4]; - u8_t index; - int ret; - buffer[0] = ADXL362_READ_REG; - buffer[1] = register_address; - for (index = 0; index < count; index++) { - buffer[index + 2] = read_buf[index]; - } - - ret = spi_slave_select(adxl362_data->spi, - adxl362_data->spi_slave); - if (ret) { - SYS_LOG_DBG("spi_slave_select FAIL %d\n", ret); - return ret; - } - - ret = spi_transceive(adxl362_data->spi, buffer, count + 2, - buffer, count + 2); - if (ret) { - SYS_LOG_DBG("spi_transceive FAIL %d\n", ret); - return ret; - } + return adxl362_reg_access(adxl362_data, + ADXL362_WRITE_REG, + register_address, + ®ister_value, + count); +} - for (index = 0; index < count; index++) { - read_buf[index] = buffer[index + 2]; - } +static inline int adxl362_get_reg(struct device *dev, u8_t *read_buf, + u8_t register_address, u8_t count) +{ + struct adxl362_data *adxl362_data = dev->driver_data; - return 0; + return adxl362_reg_access(adxl362_data, + ADXL362_READ_REG, + register_address, + read_buf, count); } static int adxl362_software_reset(struct device *dev) @@ -576,7 +569,6 @@ static int adxl362_chip_init(struct device *dev) static int adxl362_init(struct device *dev) { struct adxl362_data *data = dev->driver_data; - struct spi_config spi_config; u8_t value; int ret; @@ -587,17 +579,10 @@ static int adxl362_init(struct device *dev) return -EINVAL; } - spi_config.config = SPI_WORD(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | - SPI_MODE_CPHA; - spi_config.max_sys_freq = 4; - ret = spi_configure(data->spi, &spi_config); - if (ret) { - SYS_LOG_DBG("SPI configuration error %s %d\n", - CONFIG_ADXL362_SPI_DEV_NAME, ret); - return ret; - } - - data->spi_slave = CONFIG_ADXL362_SPI_DEV_SLAVE; + data->spi_cfg.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | + SPI_MODE_CPOL | SPI_MODE_CPHA; + data->spi_cfg.frequency = 8000000; + data->spi_cfg.slave = CONFIG_ADXL362_SPI_DEV_SLAVE; adxl362_software_reset(dev); diff --git a/drivers/sensor/adxl362/adxl362.h b/drivers/sensor/adxl362/adxl362.h index 0b44b4d97dc5..8cff6a7fd4f6 100644 --- a/drivers/sensor/adxl362/adxl362.h +++ b/drivers/sensor/adxl362/adxl362.h @@ -156,11 +156,11 @@ struct adxl362_data { struct device *spi; + struct spi_config spi_cfg; s32_t acc_x; s32_t acc_y; s32_t acc_z; s32_t temp; - u8_t spi_slave; u8_t selected_range; }; diff --git a/drivers/sensor/bme280/Kconfig b/drivers/sensor/bme280/Kconfig index 3d459bd48186..4c69598666f9 100644 --- a/drivers/sensor/bme280/Kconfig +++ b/drivers/sensor/bme280/Kconfig @@ -9,7 +9,7 @@ menuconfig BME280 bool "BME280/BMP280 sensor" depends on I2C || SPI - default n + default n help Enable driver for BME280 I2C-based or SPI-based temperature and pressure sensor. diff --git a/drivers/sensor/bme280/bme280.c b/drivers/sensor/bme280/bme280.c index e8ee9f7d8ebb..06c522b99aa7 100644 --- a/drivers/sensor/bme280/bme280.c +++ b/drivers/sensor/bme280/bme280.c @@ -29,27 +29,38 @@ static int bm280_reg_read(struct bme280_data *data, return i2c_burst_read(data->i2c_master, data->i2c_slave_addr, start, buf, size); #elif defined CONFIG_BME280_DEV_TYPE_SPI - u8_t tx_buf[2]; - u8_t rx_buf[2]; + u8_t addr; + const struct spi_buf tx_buf = { + .buf = &addr, + .len = 1 + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1 + }; + struct spi_buf rx_buf[2]; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = 2 + }; int i; - int ret; + + rx_buf[0].buf = NULL; + rx_buf[0].len = 1; + + rx_buf[1].len = 1; for (i = 0; i < size; i++) { + int ret; - ret = spi_slave_select(data->spi, data->spi_slave); - if (ret) { - SYS_LOG_DBG("spi_slave_select FAIL %d\n", ret); - return ret; - } + addr = (start + i) | 0x80; + rx_buf[1].buf = &buf[i]; - tx_buf[0] = (start + i) | 0x80; - ret = spi_transceive(data->spi, tx_buf, 2, rx_buf, 2); + ret = spi_transceive(data->spi, &data->spi_cfg, &tx, &rx); if (ret) { SYS_LOG_DBG("spi_transceive FAIL %d\n", ret); return ret; } - - buf[i] = rx_buf[1]; } #endif return 0; @@ -61,25 +72,22 @@ static int bm280_reg_write(struct bme280_data *data, u8_t reg, u8_t val) return i2c_reg_write_byte(data->i2c_master, data->i2c_slave_addr, reg, val); #elif defined CONFIG_BME280_DEV_TYPE_SPI - u8_t tx_buf[2]; - u8_t rx_buf[2]; + u8_t cmd[2] = { reg & 0x7F, val }; + const struct spi_buf tx_buf = { + .buf = cmd, + .len = 2 + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1 + }; int ret; - ret = spi_slave_select(data->spi, data->spi_slave); + ret = spi_write(data->spi, &data->spi_cfg, &tx); if (ret) { - SYS_LOG_DBG("spi_slave_select FAIL %d\n", ret); + SYS_LOG_DBG("spi_write FAIL %d\n", ret); return ret; } - - reg &= 0x7F; - tx_buf[0] = reg; - tx_buf[1] = val; - ret = spi_transceive(data->spi, tx_buf, 2, rx_buf, 2); - if (ret) { - SYS_LOG_DBG("spi_transceive FAIL %d\n", ret); - return ret; - } - #endif return 0; } @@ -323,9 +331,6 @@ static int bme280_chip_init(struct device *dev) #ifdef CONFIG_BME280_DEV_TYPE_SPI static inline int bme280_spi_init(struct bme280_data *data) { - struct spi_config spi_config; - int ret; - data->spi = device_get_binding(CONFIG_BME280_SPI_DEV_NAME); if (!data->spi) { SYS_LOG_DBG("spi device not found: %s", @@ -333,16 +338,10 @@ static inline int bme280_spi_init(struct bme280_data *data) return -EINVAL; } - spi_config.config = SPI_WORD(8) | SPI_TRANSFER_MSB | - SPI_MODE_CPOL | SPI_MODE_CPHA; - spi_config.max_sys_freq = 4; - - ret = spi_configure(data->spi, &spi_config); - if (ret) { - SYS_LOG_DBG("SPI configuration error %s %d\n", - CONFIG_BME280_SPI_DEV_NAME, ret); - return ret; - } + data->spi_cfg.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | + SPI_MODE_CPOL | SPI_MODE_CPHA; + data->spi_cfg.frequency = 8000000; + data->spi_cfg.slave = CONFIG_BME280_SPI_DEV_SLAVE; return 0; } @@ -367,8 +366,6 @@ int bme280_init(struct device *dev) CONFIG_BME280_SPI_DEV_NAME); return -EINVAL; } - - data->spi_slave = CONFIG_BME280_SPI_DEV_SLAVE; #endif if (bme280_chip_init(dev) < 0) { diff --git a/drivers/sensor/bme280/bme280.h b/drivers/sensor/bme280/bme280.h index 5e836b0364d8..df0fcd78cf8f 100644 --- a/drivers/sensor/bme280/bme280.h +++ b/drivers/sensor/bme280/bme280.h @@ -108,7 +108,7 @@ struct bme280_data { u16_t i2c_slave_addr; #elif defined CONFIG_BME280_DEV_TYPE_SPI struct device *spi; - int spi_slave; + struct spi_config spi_cfg; #else #error "BME280 device type not specified" #endif diff --git a/drivers/sensor/bmi160/Kconfig b/drivers/sensor/bmi160/Kconfig index 6379a310cb01..ab6a80ee3473 100644 --- a/drivers/sensor/bmi160/Kconfig +++ b/drivers/sensor/bmi160/Kconfig @@ -9,7 +9,6 @@ menuconfig BMI160 bool "Bosch BMI160 inertial measurement unit" depends on SPI - depends on SPI_LEGACY_API default n help Enable Bosch BMI160 inertial measurement unit that provides acceleration diff --git a/drivers/sensor/bmi160/bmi160.c b/drivers/sensor/bmi160/bmi160.c index c7a3bca1d91a..04e4ed9f1210 100644 --- a/drivers/sensor/bmi160/bmi160.c +++ b/drivers/sensor/bmi160/bmi160.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -19,91 +18,70 @@ struct bmi160_device_data bmi160_data; -static int bmi160_transceive(struct device *dev, u8_t *tx_buf, - u8_t tx_buf_len, u8_t *rx_buf, - u8_t rx_buf_len) +static int bmi160_transceive(struct device *dev, u8_t reg, + bool write, void *data, size_t length) { - const struct bmi160_device_config *dev_cfg = dev->config->config_info; struct bmi160_device_data *bmi160 = dev->driver_data; - struct spi_config spi_cfg; + const struct spi_buf buf[2] = { + { + .buf = ®, + .len = 1 + }, + { + .buf = data, + .len = length + } + }; + const struct spi_buf_set tx = { + .buffers = buf, + .count = data ? 2 : 1 + }; - spi_cfg.config = SPI_WORD(8); - spi_cfg.max_sys_freq = dev_cfg->spi_freq; + if (!write) { + const struct spi_buf_set rx = { + .buffers = buf, + .count = 2 + }; - if (spi_configure(bmi160->spi, &spi_cfg) < 0) { - SYS_LOG_DBG("Cannot configure SPI bus."); - return -EIO; + return spi_transceive(bmi160->spi, &bmi160->spi_cfg, &tx, &rx); } - if (spi_slave_select(bmi160->spi, dev_cfg->spi_slave) < 0) { - SYS_LOG_DBG("Cannot select slave."); - return -EIO; - } - - return spi_transceive(bmi160->spi, tx_buf, tx_buf_len, - rx_buf, rx_buf_len); + return spi_write(bmi160->spi, &bmi160->spi_cfg, &tx); } - -int bmi160_read(struct device *dev, u8_t reg_addr, - u8_t *data, u8_t len) +int bmi160_read(struct device *dev, u8_t reg_addr, u8_t *data, u8_t len) { - u8_t tx[3] = {0}; - - tx[0] = reg_addr | (1 << 7); - - return bmi160_transceive(dev, tx, len, data, len); + return bmi160_transceive(dev, reg_addr | BIT(7), false, data, len); } -int bmi160_byte_read(struct device *dev, u8_t reg_addr, - u8_t *byte) +int bmi160_byte_read(struct device *dev, u8_t reg_addr, u8_t *byte) { - u8_t rx_buf[2]; - - if (bmi160_read(dev, reg_addr, rx_buf, 2) < 0) { - return -EIO; - } - - *byte = rx_buf[1]; - - return 0; + return bmi160_transceive(dev, reg_addr | BIT(7), false, byte, 1); } -static int bmi160_word_read(struct device *dev, u8_t reg_addr, - u16_t *word) +static int bmi160_word_read(struct device *dev, u8_t reg_addr, u16_t *word) { - union { - u8_t raw[3]; - struct { - u8_t dummy; - u16_t word; - } __packed; - } buf; - - if (bmi160_read(dev, reg_addr, buf.raw, 3) < 0) { + if (bmi160_transceive(dev, reg_addr | BIT(7), false, word, 2) != 0) { return -EIO; } - *word = sys_le16_to_cpu(buf.word); + *word = sys_le16_to_cpu(*word); return 0; } int bmi160_byte_write(struct device *dev, u8_t reg_addr, u8_t byte) { - u8_t tx_buf[2] = {reg_addr & 0x7F, byte}; - - return bmi160_transceive(dev, tx_buf, 2, NULL, 0); + return bmi160_transceive(dev, reg_addr & 0x7F, true, &byte, 1); } int bmi160_word_write(struct device *dev, u8_t reg_addr, u16_t word) { - u8_t tx_buf[3] = { - reg_addr & 0x7F, + u8_t tx_word[2] = { (u8_t)(word & 0xff), (u8_t)(word >> 8) }; - return bmi160_transceive(dev, tx_buf, 3, NULL, 0); + return bmi160_transceive(dev, reg_addr & 0x7F, true, tx_word, 2); } int bmi160_reg_field_update(struct device *dev, u8_t reg_addr, @@ -115,8 +93,8 @@ int bmi160_reg_field_update(struct device *dev, u8_t reg_addr, return -EIO; } - return bmi160_byte_write(dev, reg_addr, - (old_val & ~mask) | ((val << pos) & mask)); + return bmi160_byte_write(dev, reg_addr, + (old_val & ~mask) | ((val << pos) & mask)); } static int bmi160_pmu_set(struct device *dev, union bmi160_pmu_status *pmu_sts) @@ -148,7 +126,7 @@ static int bmi160_pmu_set(struct device *dev, union bmi160_pmu_status *pmu_sts) /* make sure the PMU_STATUS was set, though */ do { if (bmi160_byte_read(dev, BMI160_REG_PMU_STATUS, - &sts.raw) < 0) { + &sts.raw) < 0) { return -EIO; } @@ -482,8 +460,8 @@ static int bmi160_gyr_range_set(struct device *dev, u16_t range) { struct bmi160_device_data *bmi160 = dev->driver_data; s32_t reg_val = bmi160_range_to_reg_val(range, - bmi160_gyr_range_map, - BMI160_GYR_RANGE_MAP_SIZE); + bmi160_gyr_range_map, + BMI160_GYR_RANGE_MAP_SIZE); if (reg_val < 0) { return reg_val; @@ -645,32 +623,28 @@ static int bmi160_attr_set(struct device *dev, enum sensor_channel chan, static int bmi160_sample_fetch(struct device *dev, enum sensor_channel chan) { struct bmi160_device_data *bmi160 = dev->driver_data; - u8_t tx[BMI160_BUF_SIZE] = {0}; size_t i; __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); - bmi160->sample.raw[1] = 0; - - while ((bmi160->sample.raw[1] & BMI160_DATA_READY_BIT_MASK) == 0) { - tx[0] = BMI160_REG_STATUS | (1 << 7); + bmi160->sample.raw[0] = 0; - if (bmi160_transceive(dev, tx, 2, bmi160->sample.raw, 2) < 0) { + while ((bmi160->sample.raw[0] & BMI160_DATA_READY_BIT_MASK) == 0) { + if (bmi160_transceive(dev, BMI160_REG_STATUS | (1 << 7), false, + bmi160->sample.raw, 1) < 0) { return -EIO; } } - tx[0] = BMI160_SAMPLE_BURST_READ_ADDR | (1 << 7); - - if (bmi160_transceive(dev, tx, BMI160_BUF_SIZE, bmi160->sample.raw, - BMI160_BUF_SIZE) < 0) { + if (bmi160_transceive(dev, BMI160_SAMPLE_BURST_READ_ADDR | (1 << 7), + false, bmi160->sample.raw, BMI160_BUF_SIZE) < 0) { return -EIO; } /* convert samples to cpu endianness */ for (i = 0; i < BMI160_SAMPLE_SIZE; i += 2) { u16_t *sample = - (u16_t *) &bmi160->sample.raw[BMI160_DATA_OFS + i]; + (u16_t *) &bmi160->sample.raw[i]; *sample = sys_le16_to_cpu(*sample); } @@ -814,18 +788,21 @@ static const struct sensor_driver_api bmi160_api = { int bmi160_init(struct device *dev) { - const struct bmi160_device_config *cfg = dev->config->config_info; struct bmi160_device_data *bmi160 = dev->driver_data; u8_t val = 0; s32_t acc_range, gyr_range; - bmi160->spi = device_get_binding((char *)cfg->spi_port); + bmi160->spi = device_get_binding(CONFIG_BMI160_SPI_PORT_NAME); if (!bmi160->spi) { SYS_LOG_DBG("SPI master controller not found: %d.", - bmi160->spi); + CONFIG_BMI160_SPI_PORT_NAME); return -EINVAL; } + bmi160->spi_cfg.operation = SPI_WORD_SET(8); + bmi160->spi_cfg.frequency = CONFIG_BMI160_SPI_BUS_FREQ; + bmi160->spi_cfg.slave = CONFIG_BMI160_SLAVE; + /* reboot the chip */ if (bmi160_byte_write(dev, BMI160_REG_CMD, BMI160_CMD_SOFT_RESET) < 0) { SYS_LOG_DBG("Cannot reboot chip."); @@ -920,9 +897,6 @@ int bmi160_init(struct device *dev) } const struct bmi160_device_config bmi160_config = { - .spi_port = CONFIG_BMI160_SPI_PORT_NAME, - .spi_freq = CONFIG_BMI160_SPI_BUS_FREQ, - .spi_slave = CONFIG_BMI160_SLAVE, #if defined(CONFIG_BMI160_TRIGGER) .gpio_port = CONFIG_BMI160_GPIO_DEV_NAME, .int_pin = CONFIG_BMI160_GPIO_PIN_NUM, diff --git a/drivers/sensor/bmi160/bmi160.h b/drivers/sensor/bmi160/bmi160.h index 5a1a637d3d74..9e2ffc41295a 100644 --- a/drivers/sensor/bmi160/bmi160.h +++ b/drivers/sensor/bmi160/bmi160.h @@ -9,6 +9,7 @@ #define _BMI160_H_ #include +#include #include /* registers */ @@ -383,13 +384,10 @@ struct bmi160_range { }; struct bmi160_device_config { - const char *spi_port; #if defined(CONFIG_BMI160_TRIGGER) const char *gpio_port; u8_t int_pin; #endif - u32_t spi_freq; - u8_t spi_slave; }; union bmi160_pmu_status { @@ -409,9 +407,7 @@ union bmi160_pmu_status { # define BMI160_SAMPLE_SIZE (3 * sizeof(u16_t)) #endif -/* total buffer contains one dummy byte, needed by SPI */ -#define BMI160_BUF_SIZE (BMI160_SAMPLE_SIZE + 1) -#define BMI160_DATA_OFS 1 +#define BMI160_BUF_SIZE (BMI160_SAMPLE_SIZE) union bmi160_sample { u8_t raw[BMI160_BUF_SIZE]; struct { @@ -432,6 +428,7 @@ struct bmi160_scale { struct bmi160_device_data { struct device *spi; + struct spi_config spi_cfg; #if defined(CONFIG_BMI160_TRIGGER) struct device *gpio; struct gpio_callback gpio_cb; diff --git a/drivers/sensor/lis2dh/lis2dh.c b/drivers/sensor/lis2dh/lis2dh.c index ebd935e9e842..599da7d7c076 100644 --- a/drivers/sensor/lis2dh/lis2dh.c +++ b/drivers/sensor/lis2dh/lis2dh.c @@ -10,8 +10,40 @@ #include #include +#if defined(CONFIG_LIS2DH_BUS_SPI) +int lis2dh_spi_access(struct lis2dh_data *ctx, u8_t cmd, + void *data, size_t length) +{ + const struct spi_buf buf[2] = { + { + .buf = &cmd, + .len = 1 + }, + { + .buf = data, + .len = length + } + }; + const struct spi_buf_set tx = { + .buffers = buf, + .count = 2 + }; + + if (cmd & LIS2DH_SPI_READ_BIT) { + const struct spi_buf_set rx = { + .buffers = buf, + .count = 2 + }; + + return spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx); + } + + return spi_write(ctx->spi, &ctx->spi_cfg, &tx); +} +#endif + #if defined(CONFIG_LIS2DH_TRIGGER) || defined(CONFIG_LIS2DH_ACCEL_RANGE_RUNTIME) -int lis2dh_reg_field_update(struct device *bus, u8_t reg_addr, +int lis2dh_reg_field_update(struct device *dev, u8_t reg_addr, u8_t pos, u8_t mask, u8_t val) { int status; @@ -20,12 +52,12 @@ int lis2dh_reg_field_update(struct device *bus, u8_t reg_addr, /* just to remove gcc warning */ old_val = 0; - status = lis2dh_reg_read_byte(bus, reg_addr, &old_val); + status = lis2dh_reg_read_byte(dev, reg_addr, &old_val); if (status < 0) { return status; } - return lis2dh_reg_write_byte(bus, reg_addr, + return lis2dh_reg_write_byte(dev, reg_addr, (old_val & ~mask) | ((val << pos) & mask)); } #endif @@ -98,7 +130,7 @@ static int lis2dh_sample_fetch(struct device *dev, enum sensor_channel chan) * since status and all accel data register addresses are consecutive, * a burst read can be used to read all the samples */ - status = lis2dh_burst_read(lis2dh->bus, LIS2DH_REG_STATUS, + status = lis2dh_burst_read(dev, LIS2DH_REG_STATUS, lis2dh->sample.raw, sizeof(lis2dh->sample.raw)); if (status < 0) { @@ -161,7 +193,7 @@ static int lis2dh_acc_odr_set(struct device *dev, u16_t freq) return odr; } - status = lis2dh_reg_read_byte(lis2dh->bus, LIS2DH_REG_CTRL1, &value); + status = lis2dh_reg_read_byte(dev, LIS2DH_REG_CTRL1, &value); if (status < 0) { return status; } @@ -176,7 +208,7 @@ static int lis2dh_acc_odr_set(struct device *dev, u16_t freq) odr--; } - return lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_CTRL1, + return lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL1, (value & ~LIS2DH_ODR_MASK) | LIS2DH_ODR_RATE(odr)); } @@ -216,7 +248,7 @@ static int lis2dh_acc_range_set(struct device *dev, s32_t range) lis2dh->scale = LIS2DH_ACCEL_SCALE(range); - return lis2dh_reg_field_update(lis2dh->bus, LIS2DH_REG_CTRL4, + return lis2dh_reg_field_update(dev, LIS2DH_REG_CTRL4, LIS2DH_FS_SHIFT, LIS2DH_FS_MASK, fs); @@ -282,17 +314,8 @@ int lis2dh_init(struct device *dev) int status; u8_t raw[LIS2DH_DATA_OFS + 6]; - lis2dh->bus = device_get_binding(LIS2DH_BUS_DEV_NAME); - if (lis2dh->bus == NULL) { - SYS_LOG_ERR("Could not get pointer to %s device", - LIS2DH_BUS_DEV_NAME); - return -EINVAL; - } - - /* configure bus, e.g. spi clock and format */ - status = lis2dh_bus_configure(lis2dh->bus); + status = lis2dh_bus_configure(dev); if (status < 0) { - SYS_LOG_ERR("Failed to configure bus (spi, i2c)"); return status; } @@ -304,7 +327,7 @@ int lis2dh_init(struct device *dev) memset(raw, 0, sizeof(raw)); raw[LIS2DH_DATA_OFS] = LIS2DH_ACCEL_EN_BITS; - status = lis2dh_burst_write(lis2dh->bus, LIS2DH_REG_CTRL1, raw, + status = lis2dh_burst_write(dev, LIS2DH_REG_CTRL1, raw, sizeof(raw)); if (status < 0) { SYS_LOG_ERR("Failed to reset ctrl registers."); @@ -313,7 +336,7 @@ int lis2dh_init(struct device *dev) /* set full scale range and store it for later conversion */ lis2dh->scale = LIS2DH_ACCEL_SCALE(1 << (LIS2DH_FS_IDX + 1)); - status = lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_CTRL4, + status = lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL4, LIS2DH_FS_BITS); if (status < 0) { SYS_LOG_ERR("Failed to set full scale ctrl register."); @@ -333,7 +356,7 @@ int lis2dh_init(struct device *dev) LIS2DH_ODR_IDX, (u8_t)LIS2DH_LP_EN_BIT, lis2dh->scale); /* enable accel measurements and set power mode and data rate */ - return lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_CTRL1, + return lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL1, LIS2DH_ACCEL_EN_BITS | LIS2DH_LP_EN_BIT | LIS2DH_ODR_BITS); } diff --git a/drivers/sensor/lis2dh/lis2dh.h b/drivers/sensor/lis2dh/lis2dh.h index df7e88f8ef38..7a3fab5a2073 100644 --- a/drivers/sensor/lis2dh/lis2dh.h +++ b/drivers/sensor/lis2dh/lis2dh.h @@ -25,7 +25,7 @@ #define LIS2DH_SPI_ADDR_MASK BIT_MASK(6) /* LIS2DH supports only SPI mode 0, word size 8 bits, MSB first */ -#define LIS2DH_SPI_CFG 0x80 +#define LIS2DH_SPI_CFG SPI_WORD_SET(8) #define LIS2DH_BUS_DEV_NAME CONFIG_LIS2DH_SPI_MASTER_DEV_NAME @@ -184,8 +184,12 @@ union lis2dh_sample { }; struct lis2dh_data { +#if defined(CONFIG_LIS2DH_BUS_SPI) + struct device *spi; + struct spi_config spi_cfg; +#else struct device *bus; - +#endif union lis2dh_sample sample; /* current scaling factor, in micro m/s^2 / lsb */ u16_t scale; @@ -216,49 +220,40 @@ struct lis2dh_data { #define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL #include -static inline int lis2dh_burst_read(struct device *bus, u8_t start_addr, - u8_t *buf, u8_t num_bytes) -{ #if defined(CONFIG_LIS2DH_BUS_SPI) - int status; - u8_t tx_buf = LIS2DH_SPI_READ_BIT | LIS2DH_SPI_AUTOINC_ADDR | - start_addr; +int lis2dh_spi_access(struct lis2dh_data *ctx, u8_t cmd, + void *data, size_t length); +#endif - status = spi_slave_select(bus, LIS2DH_BUS_ADDRESS); - status = spi_transceive(bus, &tx_buf, 1, buf, num_bytes); +static inline int lis2dh_burst_read(struct device *dev, u8_t start_addr, + u8_t *buf, u8_t num_bytes) +{ + struct lis2dh_data *lis2dh = dev->driver_data; - SYS_LOG_DBG("tx=0x%x num=0x%x, status=%d", tx_buf, - num_bytes, status); +#if defined(CONFIG_LIS2DH_BUS_SPI) + start_addr |= LIS2DH_SPI_READ_BIT | LIS2DH_SPI_AUTOINC_ADDR; - return status; + return lis2dh_spi_access(lis2dh, start_addr, buf, num_bytes); #elif defined(CONFIG_LIS2DH_BUS_I2C) - return i2c_burst_read(bus, LIS2DH_BUS_ADDRESS, start_addr, buf, - num_bytes); + return i2c_burst_read(lis2dh->bus, LIS2DH_BUS_ADDRESS, start_addr, + buf, num_bytes); #else return -ENODEV; #endif } -static inline int lis2dh_reg_read_byte(struct device *bus, u8_t reg_addr, +static inline int lis2dh_reg_read_byte(struct device *dev, u8_t reg_addr, u8_t *value) { -#if defined(CONFIG_LIS2DH_BUS_SPI) - int status; - u8_t tx_buf = LIS2DH_SPI_READ_BIT | reg_addr; - u8_t rx_buf[2]; - - status = spi_slave_select(bus, LIS2DH_BUS_ADDRESS); - status = spi_transceive(bus, &tx_buf, 1, rx_buf, 2); - - if (status == 0) { - *value = rx_buf[1]; - } + struct lis2dh_data *lis2dh = dev->driver_data; - SYS_LOG_DBG("tx=0x%x rx1=0x%x", tx_buf, rx_buf[1]); +#if defined(CONFIG_LIS2DH_BUS_SPI) + reg_addr |= LIS2DH_SPI_READ_BIT; - return status; + return lis2dh_spi_access(lis2dh, reg_addr, value, 1); #elif defined(CONFIG_LIS2DH_BUS_I2C) - return i2c_reg_read_byte(bus, LIS2DH_BUS_ADDRESS, reg_addr, value); + return i2c_reg_read_byte(lis2dh->bus, LIS2DH_BUS_ADDRESS, + reg_addr, value); #else return -ENODEV; #endif @@ -267,58 +262,64 @@ static inline int lis2dh_reg_read_byte(struct device *bus, u8_t reg_addr, static inline int lis2dh_burst_write(struct device *bus, u8_t start_addr, u8_t *buf, u8_t num_bytes) { -#if defined(CONFIG_LIS2DH_BUS_SPI) - int status; - u8_t dummy; - - buf[0] = LIS2DH_SPI_AUTOINC_ADDR | start_addr; - - status = spi_slave_select(bus, LIS2DH_BUS_ADDRESS); - status = spi_transceive(bus, buf, num_bytes, &dummy, 0); + struct lis2dh_data *lis2dh = dev->driver_data; - SYS_LOG_DBG("tx=0x%x num=0x%x, status=%d", buf[0], - num_bytes, status); +#if defined(CONFIG_LIS2DH_BUS_SPI) + start_addr |= LIS2DH_SPI_AUTOINC_ADDR; - return status; + return lis2dh_spi_access(lis2dh, start_addr, buf, num_bytes); #elif defined(CONFIG_LIS2DH_BUS_I2C) - return i2c_burst_write(bus, LIS2DH_BUS_ADDRESS, start_addr, buf, - num_bytes); + return i2c_burst_write(lis2dh->bus, LIS2DH_BUS_ADDRESS, start_addr, + buf, num_bytes); #else return -ENODEV; #endif } -static inline int lis2dh_reg_write_byte(struct device *bus, u8_t reg_addr, +static inline int lis2dh_reg_write_byte(struct device *dev, u8_t reg_addr, u8_t value) { -#if defined(CONFIG_LIS2DH_BUS_SPI) - u8_t tx_buf[2] = { reg_addr & LIS2DH_SPI_ADDR_MASK, value }; - u8_t dummy; - - spi_slave_select(bus, LIS2DH_BUS_ADDRESS); + struct lis2dh_data *lis2dh = dev->driver_data; - SYS_LOG_DBG("tx0=0x%x tx1=0x%x", tx_buf[0], tx_buf[1]); +#if defined(CONFIG_LIS2DH_BUS_SPI) + reg_addr &= LIS2DH_SPI_ADDR_MASK; - return spi_transceive(bus, tx_buf, 2, &dummy, 0); + return lis2dh_spi_access(lis2dh, reg_addr, &value, 1); #elif defined(CONFIG_LIS2DH_BUS_I2C) u8_t tx_buf[2] = {reg_addr, value}; - return i2c_write(bus, tx_buf, sizeof(tx_buf), LIS2DH_BUS_ADDRESS); + return i2c_write(lis2dh->bus, tx_buf, sizeof(tx_buf), + LIS2DH_BUS_ADDRESS); #else return -ENODEV; #endif } -static inline int lis2dh_bus_configure(struct device *bus) +static inline int lis2dh_bus_configure(struct device *dev) { + struct lis2dh_data *lis2dh = dev->driver_data; + #if defined(CONFIG_LIS2DH_BUS_SPI) - struct spi_config config = { - .config = LIS2DH_SPI_CFG, - .max_sys_freq = CONFIG_LIS2DH_SPI_FREQUENCY, - }; + lis2dh->spi = device_get_binding(LIS2DH_BUS_DEV_NAME); + if (lis2dh->spi == NULL) { + SYS_LOG_ERR("Could not get pointer to %s device", + LIS2DH_BUS_DEV_NAME); + return -EINVAL; + } + + lis2dh->spi_cfg.operation = LIS2DH_SPI_CFG; + lis2dh->spi_cfg.frequency = CONFIG_LIS2DH_SPI_FREQUENCY; + lis2dh->spi_cfg.slave = LIS2DH_BUS_ADDRESS; - return spi_configure(bus, &config); + return 0; #elif defined(CONFIG_LIS2DH_BUS_I2C) + lis2dh->bus = device_get_binding(LIS2DH_BUS_DEV_NAME); + if (lis2dh->bus == NULL) { + SYS_LOG_ERR("Could not get pointer to %s device", + LIS2DH_BUS_DEV_NAME); + return -EINVAL; + } + return 0; #else return -ENODEV; @@ -332,7 +333,7 @@ int lis2dh_trigger_set(struct device *dev, int lis2dh_init_interrupt(struct device *dev); -int lis2dh_reg_field_update(struct device *bus, u8_t reg_addr, +int lis2dh_reg_field_update(struct device *dev, u8_t reg_addr, u8_t pos, u8_t mask, u8_t val); int lis2dh_acc_slope_config(struct device *dev, enum sensor_attribute attr, diff --git a/drivers/sensor/lis2dh/lis2dh_trigger.c b/drivers/sensor/lis2dh/lis2dh_trigger.c index 45bd7bb1784c..c293ea0ee984 100644 --- a/drivers/sensor/lis2dh/lis2dh_trigger.c +++ b/drivers/sensor/lis2dh/lis2dh_trigger.c @@ -25,7 +25,7 @@ static int lis2dh_trigger_drdy_set(struct device *dev, enum sensor_channel chan, /* cancel potentially pending trigger */ atomic_clear_bit(&lis2dh->trig_flags, TRIGGED_INT1); - status = lis2dh_reg_field_update(lis2dh->bus, LIS2DH_REG_CTRL3, + status = lis2dh_reg_field_update(dev, LIS2DH_REG_CTRL3, LIS2DH_EN_DRDY1_INT1_SHIFT, LIS2DH_EN_DRDY1_INT1, 0); @@ -49,18 +49,19 @@ static int lis2dh_trigger_drdy_set(struct device *dev, enum sensor_channel chan, return 0; } -static int lis2dh_start_trigger_int1(const struct lis2dh_data *lis2dh) +static int lis2dh_start_trigger_int1(struct device *dev) { + struct lis2dh_data *lis2dh = dev->driver_data; int status; u8_t raw[LIS2DH_BUF_SZ]; u8_t ctrl1 = 0; /* power down temporarly to align interrupt & data output sampling */ - status = lis2dh_reg_read_byte(lis2dh->bus, LIS2DH_REG_CTRL1, &ctrl1); + status = lis2dh_reg_read_byte(dev, LIS2DH_REG_CTRL1, &ctrl1); if (unlikely(status < 0)) { return status; } - status = lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_CTRL1, + status = lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL1, ctrl1 & ~LIS2DH_ODR_MASK); if (unlikely(status < 0)) { return status; @@ -69,8 +70,7 @@ static int lis2dh_start_trigger_int1(const struct lis2dh_data *lis2dh) SYS_LOG_DBG("ctrl1=0x%x @tick=%u", ctrl1, k_cycle_get_32()); /* empty output data */ - status = lis2dh_burst_read(lis2dh->bus, LIS2DH_REG_STATUS, raw, - sizeof(raw)); + status = lis2dh_burst_read(dev, LIS2DH_REG_STATUS, raw, sizeof(raw)); if (unlikely(status < 0)) { return status; } @@ -78,12 +78,12 @@ static int lis2dh_start_trigger_int1(const struct lis2dh_data *lis2dh) gpio_pin_enable_callback(lis2dh->gpio, CONFIG_LIS2DH_INT1_GPIO_PIN); /* re-enable output sampling */ - status = lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_CTRL1, ctrl1); + status = lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL1, ctrl1); if (unlikely(status < 0)) { return status; } - return lis2dh_reg_field_update(lis2dh->bus, LIS2DH_REG_CTRL3, + return lis2dh_reg_field_update(dev, LIS2DH_REG_CTRL3, LIS2DH_EN_DRDY1_INT1_SHIFT, LIS2DH_EN_DRDY1_INT1, 1); } @@ -104,11 +104,10 @@ static int lis2dh_trigger_anym_set(struct device *dev, atomic_clear_bit(&lis2dh->trig_flags, TRIGGED_INT2); /* disable all interrupt 2 events */ - status = lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_INT2_CFG, 0); + status = lis2dh_reg_write_byte(dev, LIS2DH_REG_INT2_CFG, 0); /* make sure any pending interrupt is cleared */ - status = lis2dh_reg_read_byte(lis2dh->bus, LIS2DH_REG_INT2_SRC, - ®_val); + status = lis2dh_reg_read_byte(dev, LIS2DH_REG_INT2_SRC, ®_val); lis2dh->handler_anymotion = handler; if ((handler == NULL) || (status < 0)) { @@ -127,8 +126,9 @@ static int lis2dh_trigger_anym_set(struct device *dev, return 0; } -static int lis2dh_start_trigger_int2(const struct lis2dh_data *lis2dh) +static int lis2dh_start_trigger_int2(struct device *dev) { + struct lis2dh_data *lis2dh = dev->driver_data; int status; status = gpio_pin_enable_callback(lis2dh->gpio, @@ -137,7 +137,7 @@ static int lis2dh_start_trigger_int2(const struct lis2dh_data *lis2dh) SYS_LOG_ERR("enable callback failed err=%d", status); } - return lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_INT2_CFG, + return lis2dh_reg_write_byte(dev, LIS2DH_REG_INT2_CFG, LIS2DH_ANYM_CFG); } @@ -165,8 +165,7 @@ int lis2dh_acc_slope_config(struct device *dev, enum sensor_attribute attr, u8_t range_g, reg_val; u32_t slope_th_ums2; - status = lis2dh_reg_read_byte(lis2dh->bus, LIS2DH_REG_CTRL4, - ®_val); + status = lis2dh_reg_read_byte(dev, LIS2DH_REG_CTRL4, ®_val); if (status < 0) { return status; } @@ -188,7 +187,7 @@ int lis2dh_acc_slope_config(struct device *dev, enum sensor_attribute attr, SYS_LOG_INF("int2_ths=0x%x range_g=%d ums2=%u", reg_val, range_g, slope_th_ums2 - 1); - status = lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_INT2_THS, + status = lis2dh_reg_write_byte(dev, LIS2DH_REG_INT2_THS, reg_val); } else { /* SENSOR_ATTR_SLOPE_DUR */ /* @@ -201,7 +200,7 @@ int lis2dh_acc_slope_config(struct device *dev, enum sensor_attribute attr, SYS_LOG_INF("int2_dur=0x%x", val->val1); - status = lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_INT2_DUR, + status = lis2dh_reg_write_byte(dev, LIS2DH_REG_INT2_DUR, val->val1); } @@ -249,7 +248,7 @@ static void lis2dh_thread_cb(void *arg) if (unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags, START_TRIG_INT1))) { - int status = lis2dh_start_trigger_int1(lis2dh); + int status = lis2dh_start_trigger_int1(dev); if (unlikely(status < 0)) { SYS_LOG_ERR("lis2dh_start_trigger_int1: %d", status); @@ -259,7 +258,7 @@ static void lis2dh_thread_cb(void *arg) if (unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags, START_TRIG_INT2))) { - int status = lis2dh_start_trigger_int2(lis2dh); + int status = lis2dh_start_trigger_int2(dev); if (unlikely(status < 0)) { SYS_LOG_ERR("lis2dh_start_trigger_int2: %d", status); @@ -290,8 +289,7 @@ static void lis2dh_thread_cb(void *arg) u8_t reg_val; /* clear interrupt 2 to de-assert int2 line */ - lis2dh_reg_read_byte(lis2dh->bus, LIS2DH_REG_INT2_SRC, - ®_val); + lis2dh_reg_read_byte(dev, LIS2DH_REG_INT2_SRC, ®_val); if (likely(lis2dh->handler_anymotion != NULL)) { lis2dh->handler_anymotion(dev, &anym_trigger); @@ -401,7 +399,7 @@ int lis2dh_init_interrupt(struct device *dev) lis2dh->dev = dev; #endif /* disable interrupt 2 in case of warm (re)boot */ - status = lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_INT2_CFG, 0); + status = lis2dh_reg_write_byte(dev, LIS2DH_REG_INT2_CFG, 0); if (status < 0) { SYS_LOG_ERR("Interrupt 2 disable reg write failed (%d)", status); @@ -409,15 +407,14 @@ int lis2dh_init_interrupt(struct device *dev) } memset(raw, 0, sizeof(raw)); - status = lis2dh_burst_write(lis2dh->bus, LIS2DH_REG_INT2_THS, raw, - sizeof(raw)); + status = lis2dh_burst_write(dev, LIS2DH_REG_INT2_THS, raw, sizeof(raw)); if (status < 0) { SYS_LOG_ERR("Burst write to INT2 THS failed (%d)", status); return status; } /* latch int2 line interrupt */ - status = lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_CTRL5, + status = lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL5, LIS2DH_EN_LIR_INT2); if (status < 0) { SYS_LOG_ERR("INT2 latch enable reg write failed (%d)", status); @@ -429,6 +426,6 @@ int lis2dh_init_interrupt(struct device *dev) CONFIG_LIS2DH_INT2_GPIO_PIN, LIS2DH_INT2_CFG); /* enable interrupt 2 on int2 line */ - return lis2dh_reg_write_byte(lis2dh->bus, LIS2DH_REG_CTRL6, + return lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL6, LIS2DH_EN_INT2_INT2); } diff --git a/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index 611e1b0f5d87..f871edf5eaaf 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -1,15 +1,7 @@ -if(CONFIG_SPI_LEGACY_API) - zephyr_sources_ifdef(CONFIG_SPI_DW spi_dw_legacy.c) - zephyr_sources_ifdef(CONFIG_SPIM_NRF52 spim_nrf52_legacy.c) - zephyr_sources_ifdef(CONFIG_SPIS_NRF5 spis_nrf5_legacy.c) - zephyr_sources_ifdef(CONFIG_SPI_INTEL spi_intel.c) - zephyr_sources_ifdef(CONFIG_SPI_MCUX_DSPI spi_mcux_dspi.c) - zephyr_sources_ifdef(CONFIG_SPI_QMSI spi_qmsi.c) - zephyr_sources_ifdef(CONFIG_SPI_QMSI_SS spi_qmsi_ss.c) -else() - zephyr_sources_ifdef(CONFIG_SPI_DW spi_dw.c) - zephyr_sources_ifdef(CONFIG_SPI_STM32 spi_ll_stm32.c) - zephyr_sources_ifdef(CONFIG_SPI_SAM0 spi_sam0.c) -endif() - +zephyr_sources_ifdef(CONFIG_SPI_DW spi_dw.c) +zephyr_sources_ifdef(CONFIG_SPI_INTEL spi_intel.c) +zephyr_sources_ifdef(CONFIG_SPI_STM32 spi_ll_stm32.c) +zephyr_sources_ifdef(CONFIG_SPI_MCUX_DSPI spi_mcux_dspi.c) +zephyr_sources_ifdef(CONFIG_SPI_SAM0 spi_sam0.c) +zephyr_sources_ifdef(CONFIG_NRFX_SPI spi_nrfx_spi.c) zephyr_sources_ifdef(CONFIG_USERSPACE spi_handlers.c) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 5cc19389206b..00efe95d858c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -6,75 +6,31 @@ # SPDX-License-Identifier: Apache-2.0 # -config SPI_LEGACY_API - bool "Use legacy SPI API (default)" - default y - help - Driver and user API is the legacy SPI API (spi_legacy.h). - If unselected, the new API will be used. - # # SPI Drivers # menuconfig SPI - bool - prompt "SPI hardware bus support" + bool "SPI hardware bus support" default n help Enable support for the SPI hardware bus. -config SPI_QMSI - bool "QMSI driver for SPI controller" - depends on SPI && QMSI - default n - help - SPI driver implementation using QMSI library. QMSI is the - Quark Microcontroller Software Interface, providing a common - interface to the Quark family of microcontrollers. +if SPI -config SPI_QMSI_SS - bool "QMSI driver for SPI controller on Sensor Subsystem" - depends on SPI && QMSI +config SPI_ASYNC + bool "Enable Asynchronous call support" default n + select POLL help - SPI driver implementation using QMSI library. This instance is - for the Sensor Subsystem. + This option enables the asynchronous API calls. -config SPI_INTEL - bool - prompt "Intel SPI controller driver" - depends on SPI && CPU_MINUTEIA +config SPI_SLAVE + bool "Enable Slave support [EXPERIMENTAL]" default n help - Enable support for Intel's SPI controllers. Such controller - was formerly found on XScale chips. It can be found nowadays - on CEXXXX Intel media controller and Quark CPU (2 of them). + Enables Driver SPI slave operations. Slave support depends + on the driver and the hardware it runs on. -config SPI_STM32 - bool - prompt "STM32 MCU SPI controller driver" - depends on SPI && SOC_FAMILY_STM32 - select HAS_DTS_SPI - select USE_STM32_LL_SPI - default n - help - Enable SPI support on the STM32 family of processors. - -config SPI_STM32_HAS_FIFO - bool - depends on SPI_STM32 - depends on SOC_SERIES_STM32L4X || SOC_SERIES_STM32F0X || SOC_SERIES_STM32F3X - default y - -config SPI_STM32_INTERRUPT - bool - prompt "STM32 MCU SPI Interrupt Support" - depends on SPI_STM32 - default n - help - Enable Interrupt support for the SPI Driver of STM32 family. - -if SPI config SPI_INIT_PRIORITY int "Init priority" default 70 @@ -82,9 +38,8 @@ config SPI_INIT_PRIORITY Device driver initialization priority. config SYS_LOG_SPI_LEVEL - int - prompt "SPI Driver Log level" - depends on SYS_LOG && SPI + int "SPI Driver Log level" + depends on SYS_LOG default 0 range 0 4 help @@ -102,253 +57,218 @@ config SYS_LOG_SPI_LEVEL - 4 DEBUG, write SYS_LOG_DBG in addition to previous levels -config SPI_CS_GPIO - bool "SPI port CS pin is controlled via a GPIO port" - depends on GPIO - default n - config SPI_0 - bool - prompt "SPI port 0" + bool "SPI port 0" default n help Enable SPI controller port 0. +if SPI_0 + config SPI_0_NAME - string - prompt "SPI port 0 device name" - depends on SPI_0 + string "SPI port 0 device name" + depends on !HAS_DTS_SPI default "SPI_0" -config SPI_0_IRQ_PRI - int - prompt "Port 0 interrupt priority" - depends on SPI_0 - -config SPI_0_DEFAULT_CFG - hex "Port 0 default configuration" - depends on SPI_0 - default 0x80 +config SPI_0_OP_MODES + int "Port 0 supported operation modes (master/slave/both)" + default 1 + range 1 3 + help + This sets the supported operation modes at runtime, by the SPI + port 0, where: + 1 is MASTER mode only (default) + 2 is SLAVE mode only + 3 is both modes are available. -config SPI_0_DEFAULT_BAUD_RATE - int "Port 0 default baud rate" - depends on SPI_0 - default 500000 +config SPI_0_IRQ_PRI + int "Port 0 interrupt priority" config SPI_0_CS_GPIO_PORT - string - prompt "The GPIO port which is used to control CS" - depends on SPI_0 && SPI_CS_GPIO + string "The GPIO port which is used to control CS" + depends on SPI_CS_GPIO default "GPIO_0" config SPI_0_CS_GPIO_PIN int "The GPIO PIN which is used to act as a CS pin" - depends on SPI_0 && SPI_CS_GPIO + depends on SPI_CS_GPIO default 0 +endif # SPI_0 + config SPI_1 - bool - prompt "SPI port 1" + bool "SPI port 1" default n help Enable SPI controller port 1. +if SPI_1 + config SPI_1_NAME - string - prompt "SPI port 1 device name" - depends on SPI_1 && !HAS_DTS_SPI + string "SPI port 1 device name" + depends on !HAS_DTS_SPI default "SPI_1" -config SPI_1_IRQ_PRI - int - prompt "Port 0 interrupt priority" - depends on SPI_1 && !HAS_DTS_SPI - -config SPI_1_DEFAULT_CFG - hex "Port 1 default configuration" - depends on SPI_1 - default 0x80 +config SPI_1_OP_MODES + int "Port 1 supported operation modes (master/slave/both)" + default 1 + range 1 3 + help + This sets the supported operation modes at runtime, by the SPI + port 1, where: + 1 is MASTER mode only (default) + 2 is SLAVE mode only + 3 is both modes are available. -config SPI_1_DEFAULT_BAUD_RATE - int "Port 1 default baud rate" - depends on SPI_1 - default 500000 +config SPI_1_IRQ_PRI + int "Port 0 interrupt priority" + depends on !HAS_DTS_SPI config SPI_1_CS_GPIO_PORT - string - prompt "The GPIO port which is used to control CS" - depends on SPI_1 && SPI_CS_GPIO + string "The GPIO port which is used to control CS" + depends on SPI_CS_GPIO default "GPIO_0" config SPI_1_CS_GPIO_PIN int "The GPIO PIN which is used to act as a CS pin" - depends on SPI_1 && SPI_CS_GPIO + depends on SPI_CS_GPIO default 0 +endif # SPI_1 + config SPI_2 - bool - prompt "SPI port 2" + bool "SPI port 2" default n help Enable SPI controller port 2. +if SPI_2 + config SPI_2_NAME - string - prompt "SPI port 2 device name" - depends on SPI_2 && !HAS_DTS_SPI + string "SPI port 2 device name" + depends on !HAS_DTS_SPI default "SPI_2" -config SPI_2_IRQ_PRI - int - prompt "Port 2 interrupt priority" - depends on SPI_2 && !HAS_DTS_SPI - -config SPI_2_DEFAULT_CFG - hex "Port 2 default configuration" - depends on SPI_2 - default 0x80 +config SPI_2_OP_MODES + int "Port 2 supported operation modes (master/slave/both)" + default 1 + range 1 3 + help + This sets the supported operation modes at runtime, by the SPI + port 2, where: + 1 is MASTER mode only (default) + 2 is SLAVE mode only + 3 is both modes are available. -config SPI_2_DEFAULT_BAUD_RATE - int "Port 2 default baud rate" - depends on SPI_2 - default 500000 +config SPI_2_IRQ_PRI + int "Port 2 interrupt priority" + depends on !HAS_DTS_SPI config SPI_2_CS_GPIO_PORT - string - prompt "The GPIO port which is used to control CS" - depends on SPI_2 && SPI_CS_GPIO + string "The GPIO port which is used to control CS" + depends on SPI_CS_GPIO default "GPIO_0" config SPI_2_CS_GPIO_PIN int "The GPIO PIN which is used to act as a CS pin" - depends on SPI_2 && SPI_CS_GPIO + depends on SPI_CS_GPIO default 0 +endif # SPI_2 + config SPI_3 - bool - prompt "SPI port 3" + bool "SPI port 3" default n help Enable SPI controller port 3. +if SPI_3 + config SPI_3_NAME - string - prompt "SPI port 3 device name" - depends on SPI_3 && !HAS_DTS_SPI + string "SPI port 3 device name" + depends on !HAS_DTS_SPI default "SPI_3" +config SPI_3_OP_MODES + int "Port 3 supported operation modes (master/slave/both)" + default 1 + range 1 3 + help + This sets the supported operation modes at runtime, by the SPI + port 3, where: + 1 is MASTER mode only (default) + 2 is SLAVE mode only + 3 is both modes are available. + config SPI_3_IRQ_PRI - int - prompt "Port 3 interrupt priority" - depends on SPI_3 && !HAS_DTS_SPI + int "Port 3 interrupt priority" + depends on !HAS_DTS_SPI + +endif # SPI_3 config SPI_4 - bool - prompt "SPI port 4" + bool "SPI port 4" default n help Enable SPI controller port 4. config SPI_4_NAME - string - prompt "SPI port 4 device name" + string "SPI port 4 device name" depends on SPI_4 default "SPI_4" +config SPI_4_OP_MODES + int "Port 4 supported operation modes (master/slave/both)" + depends on SPI_4 + default 1 + range 1 3 + help + This sets the supported operation modes at runtime, by the SPI + port 4, where: + 1 is MASTER mode only (default) + 2 is SLAVE mode only + 3 is both modes are available. + config SPI_5 - bool - prompt "SPI port 5" + bool "SPI port 5" default n help Enable SPI controller port 5. config SPI_5_NAME - string - prompt "SPI port 5 device name" + string "SPI port 5 device name" depends on SPI_5 default "SPI_5" -config SPI_SS_INIT_PRIORITY - int "Init priority" - depends on SPI_QMSI_SS - default 70 - help - Device driver initialization priority. - -config SPI_SS_CS_GPIO - bool "SPI port CS pin is controlled via a GPIO port" - select GPIO - depends on SPI_QMSI_SS - default n - -config SPI_SS_0 - bool - prompt "SPI SS port 0" - depends on SPI_QMSI_SS - default n +config SPI_5_OP_MODES + int "Port 5 supported operation modes (master/slave/both)" + depends on SPI_5 + default 1 + range 1 3 help - Enable SPI controller port 0. - -config SPI_SS_0_NAME - string - prompt "SPI SS port 0 device name" - depends on SPI_SS_0 - default "SPI_SS_0" - -config SPI_SS_0_IRQ_PRI - int - prompt "Port 0 interrupt priority" - depends on SPI_SS_0 - -config SPI_SS_0_CS_GPIO_PORT - string - prompt "The GPIO port which is used to control CS" - depends on SPI_SS_0 && SPI_SS_CS_GPIO - default "GPIO_0" + This sets the supported operation modes at runtime, by the SPI + port 5, where: + 1 is MASTER mode only (default) + 2 is SLAVE mode only + 3 is both modes are available. -config SPI_SS_0_CS_GPIO_PIN - int "The GPIO PIN which is used to act as a CS pin" - depends on SPI_SS_0 && SPI_SS_CS_GPIO - default 0 - -config SPI_SS_1 - bool - prompt "SPI SS port 1" - depends on SPI_QMSI_SS +config SPI_INTEL + bool "Intel SPI controller driver" + depends on CPU_MINUTEIA default n help - Enable SPI controller port 1. - -config SPI_SS_1_NAME - string - prompt "SPI port 1 device name" - depends on SPI_SS_1 - default "SPI_SS_1" - -config SPI_SS_1_IRQ_PRI - int - prompt "Port 0 interrupt priority" - depends on SPI_SS_1 - -config SPI_SS_1_CS_GPIO_PORT - string - prompt "The GPIO port which is used to control CS" - depends on SPI_SS_1 && SPI_SS_CS_GPIO - default "GPIO_0" + Enable support for Intel's SPI controllers. Such controller + was formerly found on XScale chips. It can be found nowadays + on CEXXXX Intel media controller and Quark CPU (2 of them). -config SPI_SS_1_CS_GPIO_PIN - int "The GPIO PIN which is used to act as a CS pin" - depends on SPI_SS_1 && SPI_SS_CS_GPIO - default 0 +source "drivers/spi/Kconfig.stm32" source "drivers/spi/Kconfig.dw" source "drivers/spi/Kconfig.mcux_dspi" -if SPI_LEGACY_API -source "drivers/spi/Kconfig.nrf5_legacy" -endif - source "drivers/spi/Kconfig.sam0" +source "drivers/spi/Kconfig.nrfx" + endif # SPI diff --git a/drivers/spi/Kconfig.dw b/drivers/spi/Kconfig.dw index 4f6e663e987f..5d9f6db90aae 100644 --- a/drivers/spi/Kconfig.dw +++ b/drivers/spi/Kconfig.dw @@ -7,9 +7,7 @@ # menuconfig SPI_DW - bool - prompt "Designware SPI controller driver" - depends on SPI + bool "Designware SPI controller driver" default n help Enable support for Designware's SPI controllers. @@ -25,49 +23,116 @@ config SPI_DW_ARC_AUX_REGS registers and thus their access is different than memory mapped registers. +config SPI_DW_FIFO_DEPTH + int "RX and TX FIFO Depth" + help + Corresponds to the SSI_TX_FIFO_DEPTH and + SSI_RX_FIFO_DEPTH of the DesignWare Synchronous + Serial Interface. Depth ranges from 2-256. -choice -depends on SPI_DW -prompt "DesignWare SPI interrupt management logic" -default SPI_DW_INTERRUPT_SINGLE_LINE +if SPI_0 -config SPI_DW_INTERRUPT_SINGLE_LINE +config SPI_DW_PORT_0_INTERRUPT_SINGLE_LINE bool "Single interrupt line for all interrupts" + default y help Only one line is used to trigger interrupts: RX, TX and ERROR interrupt go all through that line, undifferentiated. -config SPI_DW_INTERRUPT_SEPARATED_LINES - bool "One line per-interrupt type (RX, TX and ERROR)" - help - Each interrupt gets a dedicated line -endchoice -config SPI_DW_CLOCK_GATE +config SPI_DW_PORT_0_CLOCK_GATE bool "Enable clock gating" - depends on SPI_DW && SOC_QUARK_SE_C1000 - select CLOCK_CONTROL + depends on CLOCK_CONTROL default n -config SPI_DW_CLOCK_GATE_DRV_NAME +if SPI_DW_PORT_0_CLOCK_GATE + +config SPI_DW_PORT_0_CLOCK_GATE_DRV_NAME string - depends on SPI_DW_CLOCK_GATE default "" -config SPI_DW_FIFO_DEPTH - int "RX and TX FIFO Depth" - help - Corresponds to the SSI_TX_FIFO_DEPTH and - SSI_RX_FIFO_DEPTH of the DesignWare Synchronous - Serial Interface. Depth ranges from 2-256. - config SPI_DW_PORT_0_CLOCK_GATE_SUBSYS int "Clock controller's subsystem" - depends on SPI_DW_CLOCK_GATE +endif # SPI_DW_PORT_0_CLOCK_GATE + +endif # SPI_0 + +if SPI_1 + +config SPI_DW_PORT_1_INTERRUPT_SINGLE_LINE + bool "Single interrupt line for all interrupts" + default y + +config SPI_DW_PORT_1_CLOCK_GATE + bool "Enable clock gating" + depends on CLOCK_CONTROL + default n + +if SPI_DW_PORT_1_CLOCK_GATE + +config SPI_DW_PORT_1_CLOCK_GATE_DRV_NAME + string + default "" config SPI_DW_PORT_1_CLOCK_GATE_SUBSYS int "Clock controller's subsystem" - depends on SPI_DW_CLOCK_GATE +endif # SPI_DW_PORT_1_CLOCK_GATE + +endif # SPI_1 + +if SPI_2 + +config SPI_DW_PORT_2_INTERRUPT_SINGLE_LINE + bool "Single interrupt line for all interrupts" + default y + help + Only one line is used to trigger interrupts: RX, TX and ERROR + interrupt go all through that line, undifferentiated. + +config SPI_DW_PORT_2_CLOCK_GATE + bool "Enable clock gating" + depends on CLOCK_CONTROL + default n + +if SPI_DW_PORT_2_CLOCK_GATE + +config SPI_DW_PORT_2_CLOCK_GATE_DRV_NAME + string + default "" + +config SPI_DW_PORT_2_CLOCK_GATE_SUBSYS + int "Clock controller's subsystem" + +endif # SPI_DW_PORT_2_CLOCK_GATE + +endif # SPI_2 + +if SPI_3 + +config SPI_DW_PORT_3_INTERRUPT_SINGLE_LINE + bool "Single interrupt line for all interrupts" + default y + help + Only one line is used to trigger interrupts: RX, TX and ERROR + interrupt go all through that line, undifferentiated. + +config SPI_DW_PORT_3_CLOCK_GATE + bool "Enable clock gating" + depends on CLOCK_CONTROL + default n + +if SPI_DW_PORT_3_CLOCK_GATE + +config SPI_DW_PORT_3_CLOCK_GATE_DRV_NAME + string + default "" + +config SPI_DW_PORT_3_CLOCK_GATE_SUBSYS + int "Clock controller's subsystem" + +endif # SPI_DW_PORT_3_CLOCK_GATE + +endif # SPI_3 endif # SPI_DW diff --git a/drivers/spi/Kconfig.mcux_dspi b/drivers/spi/Kconfig.mcux_dspi index d0519cfe62c0..99e6db7077e2 100644 --- a/drivers/spi/Kconfig.mcux_dspi +++ b/drivers/spi/Kconfig.mcux_dspi @@ -7,9 +7,8 @@ # menuconfig SPI_MCUX_DSPI - bool - prompt "MCUX SPI driver" - depends on SPI && HAS_MCUX + bool "MCUX SPI driver" + depends on HAS_MCUX default n help Enable support for mcux spi driver. diff --git a/drivers/spi/Kconfig.nrf5_legacy b/drivers/spi/Kconfig.nrf5_legacy deleted file mode 100644 index 6d72ad3d8c50..000000000000 --- a/drivers/spi/Kconfig.nrf5_legacy +++ /dev/null @@ -1,279 +0,0 @@ -# Kconfig - nrf5 series MDK SPI support -# -# Copyright (c) 2017, Intel Corp. -# Copyright (c) 2016-2017, Linaro Limited. -# -# SPDX-License-Identifier: Apache-2.0 -# - -# TODO add nrf51 master - -menuconfig SPI_NRF5 - bool "nRF5 SPI drivers" - depends on SPI && SOC_FAMILY_NRF && GPIO_NRF5_P0 - default n - help - Enable support for nRF5 MCU series SPI drivers. Peripherals - with the same instance id can not be used together, e.g., 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 - -# TODO: rename to SPIM0_NRF5 when nRF51 SPIM driver is available. -config SPIM0_NRF52 - bool "nRF52 SPIM0" - depends on SOC_SERIES_NRF52X - help - nRF52 SPI Master with EasyDMA on port 0 - -# On nRF51, SPI0 is SPIM-only. -config SPIS0_NRF52 - bool "nRF52 SPIS0" - depends on SOC_SERIES_NRF52X - help - nRF51 and nRF52 SPI Slave 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 - -if SPIS0_NRF52 - -config SPIS0_NRF52_GPIO_SCK_PIN - int "SCK pin number" - range 0 31 - help - GPIO pin number for SCK - -config SPIS0_NRF52_GPIO_MOSI_PIN - int "MOSI pin number" - range 0 31 - help - GPIO pin number for MOSI - -config SPIS0_NRF52_GPIO_MISO_PIN - int "MISO pin number" - range 0 31 - help - GPIO pin number for MISO - -config SPIS0_NRF52_GPIO_CSN_PIN - int "CSN pin number" - range 0 255 - default 255 - help - GPIO pin number for slave select (chip select). Not used value - is 255 (0xff). - -config SPIS0_NRF52_DEF - hex "Default character" - default 0 - help - Default character. Character clocked out in case of an ignored - transaction. - -endif # SPIS0_NRF5 - -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 - -config SPIS1_NRF5 - bool "nRF5 SPIS1" - depends on (SOC_SERIES_NRF52X || SOC_SERIES_NRF51X) - help - nRF51 and nRF52 SPI Slave with EasyDMA on port 1 - -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 - -if SPIS1_NRF5 - -config SPIS1_NRF5_GPIO_SCK_PIN - int "SCK pin number" - range 0 31 - help - GPIO pin number for SCK - -config SPIS1_NRF5_GPIO_MOSI_PIN - int "MOSI pin number" - range 0 31 - help - GPIO pin number for MOSI - -config SPIS1_NRF5_GPIO_MISO_PIN - int "MISO pin number" - range 0 31 - help - GPIO pin number for MISO - -config SPIS1_NRF5_GPIO_CSN_PIN - int "CSN pin number" - range 0 255 - default 255 - help - GPIO pin number for slave select (chip select). Not used value - is 255 (0xff). - -config SPIS1_NRF5_DEF - hex "Default character" - default 0 - help - Default character. Character clocked out in case of an ignored - transaction. - -endif # SPIS1_NRF5 - -endif # SPI_1 && !I2C_1 - -# hidden compile options -config SPIM_NRF52 - bool - depends on !I2C_0 || !I2C_1 - default y if (SPIM0_NRF52 || SPIM1_NRF52) - -config SPIS_NRF5 - bool - depends on !I2C_0 || !I2C_1 - default y if (SPIS0_NRF52 || SPIS1_NRF5) - -endif # SPI_NRF5 diff --git a/drivers/spi/Kconfig.nrfx b/drivers/spi/Kconfig.nrfx new file mode 100644 index 000000000000..cd24b2b5f7c5 --- /dev/null +++ b/drivers/spi/Kconfig.nrfx @@ -0,0 +1,210 @@ +# Copyright (c) 2017 - 2018, Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig SPI_NRFX + bool "nRF SPI nrfx drivers" + depends on SOC_FAMILY_NRF + help + Enable support for nrfx SPI drivers for nRF MCU series. + Peripherals with the same instance ID cannot be used together, + e.g. SPI_0 and I2C_0. You may need to disable I2C_0 or I2C_1. + +if SPI_NRFX + +# Nordic TWIx0 and SPIx0 instances can not be used at the same time +if SPI_0 && !I2C_0 + +choice + prompt "SPI Port 0 Driver type" + optional + +config SPI_0_NRF_SPI + bool "nRF SPI 0" + depends on SOC_SERIES_NRF52X || SOC_SERIES_NRF51X + select NRFX_SPI + help + Enable nRF SPI Master without EasyDMA on port 0 + +config SPI_0_NRF_SPIM + bool "nRF SPIM 0" + depends on SOC_SERIES_NRF52X + select NRFX_SPIM + help + Enable nRF SPI Master with EasyDMA on port 0 + +config SPI_0_NRF_SPIS + bool "nRF SPIS 0" + depends on SOC_SERIES_NRF52X + select NRFX_SPIS + help + Enable nRF SPI Slave with EasyDMA on port 0 + +endchoice + +if SPI_0_NRF_SPI || SPI_0_NRF_SPIM || SPI_0_NRF_SPIS + +config SPI_0_NRF_SCK_PIN + int "SCK pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for SCK + +config SPI_0_NRF_MOSI_PIN + int "MOSI pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for MOSI + +config SPI_0_NRF_MISO_PIN + int "MISO pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for MISO + +config SPI_0_NRF_ORC + hex "Over-read Character" + range 0x00 0xff + default 0xff + help + Over-read character. Character clocked out after an over-read + of the transmit buffer. + +endif # SPI_0_NRF_SPI || SPI_0_NRF_SPIM || SPI_0_NRF_SPIS + +endif # SPI_0 && !I2C_0 + +# Nordic TWIx1 and SPIx1 instances can not be used at the same time +if SPI_1 && !I2C_1 + +choice + prompt "SPI Port 1 Driver type" + optional + +config SPI_1_NRF_SPI + bool "nRF SPI 1" + depends on SOC_SERIES_NRF52X || SOC_SERIES_NRF51X + select NRFX_SPI + help + Enable nRF SPI Master without EasyDMA on port 1 + +config SPI_1_NRF_SPIM + bool "nRF SPIM 1" + depends on SOC_SERIES_NRF52X + select NRFX_SPIM + help + Enable nRF SPI Master with EasyDMA on port 1 + +config SPI_1_NRF_SPIS + bool "nRF SPIS 1" + depends on SOC_SERIES_NRF52X || SOC_SERIES_NRF51X + select NRFX_SPIS + help + Enable nRF SPI Slave with EasyDMA on port 1 + +endchoice + +if SPI_1_NRF_SPI || SPI_1_NRF_SPIM || SPI_1_NRF_SPIS + +config SPI_1_NRF_SCK_PIN + int "SCK pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for SCK + +config SPI_1_NRF_MOSI_PIN + int "MOSI pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for MOSI + +config SPI_1_NRF_MISO_PIN + int "MISO pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for MISO + +config SPI_1_NRF_ORC + hex "Over-read Character" + range 0x00 0xff + default 0xff + help + Over-read character. Character clocked out after an over-read + of the transmit buffer. + +endif # SPI_1_NRF_SPI || SPI_1_NRF_SPIM || SPI_1_NRF_SPIS + +endif # SPI_1 && !I2C_1 + +if SPI_2 + +choice + prompt "SPI Port 2 Driver type" + optional + +config SPI_2_NRF_SPI + bool "nRF SPI 2" + depends on SOC_SERIES_NRF52X + select NRFX_SPI + help + Enable nRF SPI Master without EasyDMA on port 2 + +config SPI_2_NRF_SPIM + bool "nRF SPIM 2" + depends on SOC_SERIES_NRF52X + select NRFX_SPIM + help + Enable nRF SPI Master with EasyDMA on port 2 + +config SPI_2_NRF_SPIS + bool "nRF SPIS 2" + depends on SOC_SERIES_NRF52X + select NRFX_SPIS + help + Enable nRF SPI Slave with EasyDMA on port 2 + +endchoice + +if SPI_2_NRF_SPI || SPI_2_NRF_SPIM || SPI_2_NRF_SPIS + +config SPI_2_NRF_SCK_PIN + int "SCK pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for SCK + +config SPI_2_NRF_MOSI_PIN + int "MOSI pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for MOSI + +config SPI_2_NRF_MISO_PIN + int "MISO pin number" + range 0 47 if SOC_NRF52840_QIAA + range 0 31 + help + GPIO pin number to use for MISO + +config SPI_2_NRF_ORC + hex "Over-read Character" + range 0x00 0xff + default 0xff + help + Over-read character. Character clocked out after an over-read + of the transmit buffer. + +endif # SPI_2_NRF_SPI || SPI_2_NRF_SPIM || SPI_2_NRF_SPIS + +endif # SPI_2 + +endif # SPI_NRFX diff --git a/drivers/spi/Kconfig.stm32 b/drivers/spi/Kconfig.stm32 new file mode 100644 index 000000000000..4d60f32635d0 --- /dev/null +++ b/drivers/spi/Kconfig.stm32 @@ -0,0 +1,31 @@ +# Kconfig - STM32 SPI driver configuration options + +# +# Copyright (c) 2015-2016 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig SPI_STM32 + bool "STM32 MCU SPI controller driver" + depends on SPI && SOC_FAMILY_STM32 + select HAS_DTS_SPI + select USE_STM32_LL_SPI + default n + help + Enable SPI support on the STM32 family of processors. + +if SPI_STM32 + +config SPI_STM32_HAS_FIFO + bool + depends on SOC_SERIES_STM32L4X || SOC_SERIES_STM32F0X || SOC_SERIES_STM32F3X + default y + +config SPI_STM32_INTERRUPT + bool "STM32 MCU SPI Interrupt Support" + default n + help + Enable Interrupt support for the SPI Driver of STM32 family. + +endif # SPI_STM32 diff --git a/drivers/spi/spi_context.h b/drivers/spi/spi_context.h index 66b11d2be742..650997d37bf6 100644 --- a/drivers/spi/spi_context.h +++ b/drivers/spi/spi_context.h @@ -19,23 +19,28 @@ extern "C" { #endif +enum spi_ctx_runtime_op_mode { + SPI_CTX_RUNTIME_OP_MODE_MASTER = BIT(0), + SPI_CTX_RUNTIME_OP_MODE_SLAVE = BIT(1), +}; + struct spi_context { - struct spi_config *config; + const struct spi_config *config; struct k_sem lock; struct k_sem sync; int sync_status; -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC struct k_poll_signal *signal; bool asynchronous; -#endif +#endif /* CONFIG_SPI_ASYNC */ const struct spi_buf *current_tx; size_t tx_count; - struct spi_buf *current_rx; + const struct spi_buf *current_rx; size_t rx_count; - u8_t *tx_buf; + const u8_t *tx_buf; size_t tx_len; u8_t *rx_buf; size_t rx_len; @@ -48,36 +53,42 @@ struct spi_context { ._ctx_name.sync = _K_SEM_INITIALIZER(_data._ctx_name.sync, 0, 1) static inline bool spi_context_configured(struct spi_context *ctx, - struct spi_config *config) + const struct spi_config *config) { return !!(ctx->config == config); } +static inline bool spi_context_is_slave(struct spi_context *ctx) +{ + return (ctx->config->operation & SPI_OP_MODE_SLAVE); +} + static inline void spi_context_lock(struct spi_context *ctx, bool asynchronous, struct k_poll_signal *signal) { k_sem_take(&ctx->lock, K_FOREVER); -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC ctx->asynchronous = asynchronous; ctx->signal = signal; -#endif +#endif /* CONFIG_SPI_ASYNC */ } static inline void spi_context_release(struct spi_context *ctx, int status) { - if (!status && (ctx->config->operation & SPI_LOCK_ON)) { + if (!status && + (ctx->config->operation & (SPI_LOCK_ON | SPI_OP_MODE_SLAVE))) { return; } -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC if (!ctx->asynchronous || status) { k_sem_give(&ctx->lock); } #else k_sem_give(&ctx->lock); -#endif +#endif /* CONFIG_SPI_ASYNC */ } static inline void spi_context_unlock_unconditionally(struct spi_context *ctx) @@ -90,7 +101,7 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx) static inline int spi_context_wait_for_completion(struct spi_context *ctx) { int status = 0; -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC if (!ctx->asynchronous) { k_sem_take(&ctx->sync, K_FOREVER); status = ctx->sync_status; @@ -98,13 +109,13 @@ static inline int spi_context_wait_for_completion(struct spi_context *ctx) #else k_sem_take(&ctx->sync, K_FOREVER); status = ctx->sync_status; -#endif +#endif /* CONFIG_SPI_ASYNC */ return status; } static inline void spi_context_complete(struct spi_context *ctx, int status) { -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC if (!ctx->asynchronous) { ctx->sync_status = status; k_sem_give(&ctx->sync); @@ -113,14 +124,33 @@ static inline void spi_context_complete(struct spi_context *ctx, int status) k_poll_signal(ctx->signal, status); } - if (!(ctx->config->operation & SPI_LOCK_ON)) { + if (!(ctx->config->operation & (SPI_LOCK_ON | + SPI_OP_MODE_SLAVE))) { k_sem_give(&ctx->lock); } } #else ctx->sync_status = status; k_sem_give(&ctx->sync); -#endif +#endif /* CONFIG_SPI_ASYNC */ +} + +static inline int spi_context_cs_active_value(struct spi_context *ctx) +{ + if (ctx->config->operation & SPI_CS_ACTIVE_HIGH) { + return 1; + } + + return 0; +} + +static inline int spi_context_cs_inactive_value(struct spi_context *ctx) +{ + if (ctx->config->operation & SPI_CS_ACTIVE_HIGH) { + return 0; + } + + return 1; } static inline void spi_context_cs_configure(struct spi_context *ctx) @@ -129,7 +159,8 @@ static inline void spi_context_cs_configure(struct spi_context *ctx) gpio_pin_configure(ctx->config->cs->gpio_dev, ctx->config->cs->gpio_pin, GPIO_DIR_OUT); gpio_pin_write(ctx->config->cs->gpio_dev, - ctx->config->cs->gpio_pin, 1); + ctx->config->cs->gpio_pin, + spi_context_cs_inactive_value(ctx)); } else { SYS_LOG_INF("CS control inhibited (no GPIO device)"); } @@ -140,7 +171,8 @@ static inline void spi_context_cs_control(struct spi_context *ctx, bool on) if (ctx->config->cs && ctx->config->cs->gpio_dev) { if (on) { gpio_pin_write(ctx->config->cs->gpio_dev, - ctx->config->cs->gpio_pin, 0); + ctx->config->cs->gpio_pin, + spi_context_cs_active_value(ctx)); k_busy_wait(ctx->config->cs->delay); } else { if (ctx->config->operation & SPI_HOLD_ON_CS) { @@ -149,38 +181,40 @@ static inline void spi_context_cs_control(struct spi_context *ctx, bool on) k_busy_wait(ctx->config->cs->delay); gpio_pin_write(ctx->config->cs->gpio_dev, - ctx->config->cs->gpio_pin, 1); + ctx->config->cs->gpio_pin, + spi_context_cs_inactive_value(ctx)); } } } -static inline void spi_context_buffers_setup(struct spi_context *ctx, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count, - u8_t dfs) +static inline +void spi_context_buffers_setup(struct spi_context *ctx, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + u8_t dfs) { - SYS_LOG_DBG("tx_bufs %p (%zu) - rx_bufs %p (%zu) - %u", - tx_bufs, tx_count, rx_bufs, rx_count, dfs); - - ctx->current_tx = tx_bufs; - ctx->tx_count = tx_count; - ctx->current_rx = rx_bufs; - ctx->rx_count = rx_count; + SYS_LOG_DBG("tx_bufs %p - rx_bufs %p - %u", tx_bufs, rx_bufs, dfs); if (tx_bufs) { - ctx->tx_buf = tx_bufs->buf; - ctx->tx_len = tx_bufs->len / dfs; + ctx->current_tx = tx_bufs->buffers; + ctx->tx_count = tx_bufs->count; + ctx->tx_buf = ctx->current_tx->buf; + ctx->tx_len = ctx->current_tx->len / dfs; } else { + ctx->current_tx = NULL; + ctx->tx_count = 0; ctx->tx_buf = NULL; ctx->tx_len = 0; } if (rx_bufs) { - ctx->rx_buf = rx_bufs->buf; - ctx->rx_len = rx_bufs->len / dfs; + ctx->current_rx = rx_bufs->buffers; + ctx->rx_count = rx_bufs->count; + ctx->rx_buf = ctx->current_rx->buf; + ctx->rx_len = ctx->current_rx->len / dfs; } else { + ctx->current_rx = NULL; + ctx->rx_count = 0; ctx->rx_buf = NULL; ctx->rx_len = 0; } @@ -208,10 +242,9 @@ void spi_context_update_tx(struct spi_context *ctx, u8_t dfs, u32_t len) ctx->tx_len -= len; if (!ctx->tx_len) { - ctx->current_tx++; ctx->tx_count--; - if (ctx->tx_count) { + ctx->current_tx++; ctx->tx_buf = ctx->current_tx->buf; ctx->tx_len = ctx->current_tx->len / dfs; } else { @@ -250,10 +283,9 @@ void spi_context_update_rx(struct spi_context *ctx, u8_t dfs, u32_t len) ctx->rx_len -= len; if (!ctx->rx_len) { - ctx->current_rx++; ctx->rx_count--; - if (ctx->rx_count) { + ctx->current_rx++; ctx->rx_buf = ctx->current_rx->buf; ctx->rx_len = ctx->current_rx->len / dfs; } else { diff --git a/drivers/spi/spi_dw.c b/drivers/spi/spi_dw.c index f638b1e3943d..0d2deeb5f19e 100644 --- a/drivers/spi/spi_dw.c +++ b/drivers/spi/spi_dw.c @@ -44,7 +44,13 @@ #include "spi_dw.h" #include "spi_context.h" -static void completed(struct device *dev, u8_t error) +static inline bool spi_dw_is_slave(struct spi_dw_data *spi) +{ + return (IS_ENABLED(CONFIG_SPI_SLAVE) && + spi_context_is_slave(&spi->ctx)); +} + +static void completed(struct device *dev, int error) { const struct spi_dw_config *info = dev->config->config_info; struct spi_dw_data *spi = dev->driver_data; @@ -73,7 +79,7 @@ static void completed(struct device *dev, u8_t error) SYS_LOG_DBG("SPI transaction completed %s error", error ? "with" : "without"); - spi_context_complete(&spi->ctx, error ? -EIO : 0); + spi_context_complete(&spi->ctx, error); } static void push_data(struct device *dev) @@ -186,7 +192,7 @@ static void pull_data(struct device *dev) static int spi_dw_configure(const struct spi_dw_config *info, struct spi_dw_data *spi, - struct spi_config *config) + const struct spi_config *config) { u32_t ctrlr0 = 0; @@ -197,8 +203,22 @@ static int spi_dw_configure(const struct spi_dw_config *info, return 0; } - if (config->operation & (SPI_OP_MODE_SLAVE || SPI_TRANSFER_LSB - || SPI_LINES_DUAL || SPI_LINES_QUAD)) { + /* Verify if requested op mode is relevant to this controller */ + if (config->operation & SPI_OP_MODE_SLAVE) { + if (!(info->op_modes & SPI_CTX_RUNTIME_OP_MODE_SLAVE)) { + SYS_LOG_ERR("Slave mode not supported"); + return -ENOTSUP; + } + } else { + if (!(info->op_modes & SPI_CTX_RUNTIME_OP_MODE_MASTER)) { + SYS_LOG_ERR("Master mode not supported"); + return -ENOTSUP; + } + } + + if (config->operation & (SPI_TRANSFER_LSB | + SPI_LINES_DUAL | SPI_LINES_QUAD)) { + SYS_LOG_ERR("Unsupported configuration"); return -EINVAL; } @@ -224,49 +244,96 @@ static int spi_dw_configure(const struct spi_dw_config *info, /* Installing the configuration */ write_ctrlr0(ctrlr0, info->regs); - /* Setting up baud rate */ - write_baudr(SPI_DW_CLK_DIVIDER(config->frequency), info->regs); - - /* Slave select */ - write_ser(config->slave, info->regs); - /* At this point, it's mandatory to set this on the context! */ spi->ctx.config = config; + if (!spi_dw_is_slave(spi)) { + /* Baud rate and Slave select, for master only */ + write_baudr(SPI_DW_CLK_DIVIDER(config->frequency), info->regs); + write_ser(config->slave, info->regs); + } + spi_context_cs_configure(&spi->ctx); - SYS_LOG_DBG("Installed config %p: freq %uHz (div = %u)," - " ws/dfs %u/%u, mode %u/%u/%u, slave %u", - config, config->frequency, - SPI_DW_CLK_DIVIDER(config->frequency), spi->dfs, - SPI_WORD_SIZE_GET(config->operation), - (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) ? 1 : 0, - (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) ? 1 : 0, - (SPI_MODE_GET(config->operation) & SPI_MODE_LOOP) ? 1 : 0, - config->slave); + if (spi_dw_is_slave(spi)) { + SYS_LOG_DBG("Installed slave config %p: slave_cb %p," + " ws/dfs %u/%u, mode %u/%u/%u", + config, config->slave_cb, + SPI_WORD_SIZE_GET(config->operation), spi->dfs, + (SPI_MODE_GET(config->operation) & + SPI_MODE_CPOL) ? 1 : 0, + (SPI_MODE_GET(config->operation) & + SPI_MODE_CPHA) ? 1 : 0, + (SPI_MODE_GET(config->operation) & + SPI_MODE_LOOP) ? 1 : 0); + } else { + SYS_LOG_DBG("Installed master config %p: freq %uHz (div = %u)," + " ws/dfs %u/%u, mode %u/%u/%u, slave %u", + config, config->frequency, + SPI_DW_CLK_DIVIDER(config->frequency), + SPI_WORD_SIZE_GET(config->operation), spi->dfs, + (SPI_MODE_GET(config->operation) & + SPI_MODE_CPOL) ? 1 : 0, + (SPI_MODE_GET(config->operation) & + SPI_MODE_CPHA) ? 1 : 0, + (SPI_MODE_GET(config->operation) & + SPI_MODE_LOOP) ? 1 : 0, + config->slave); + } return 0; } -static int transceive(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count, +static uint32_t spi_dw_compute_ndf(const struct spi_buf *rx_bufs, + size_t rx_count, u8_t dfs) +{ + u32_t len = 0; + + for (; rx_count; rx_bufs++, rx_count--) { + if (len > (UINT16_MAX - rx_bufs->len)) { + goto error; + } + + len += rx_bufs->len; + } + + if (len) { + return (len / dfs) - 1; + } +error: + return UINT32_MAX; +} + +static void spi_dw_update_txftlr(const struct spi_dw_config *info, + struct spi_dw_data *spi) +{ + u32_t reg_data = DW_SPI_TXFTLR_DFLT; + + if (spi_dw_is_slave(spi)) { + if (!spi->ctx.tx_len) { + reg_data = 0; + } else if (spi->ctx.tx_len < DW_SPI_TXFTLR_DFLT) { + reg_data = spi->ctx.tx_len - 1; + } + } + + SYS_LOG_DBG("TxFTLR: %u", reg_data); + + write_txftlr(reg_data, info->regs); +} + +static int transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, bool asynchronous, struct k_poll_signal *signal) { - const struct spi_dw_config *info = config->dev->config->config_info; - struct spi_dw_data *spi = config->dev->driver_data; - u32_t rx_thsld = DW_SPI_RXFTLR_DFLT; - u32_t imask = DW_SPI_IMR_UNMASK; - int ret = 0; - - /* Check status */ - if (test_bit_ssienr(info->regs) || test_bit_sr_busy(info->regs)) { - SYS_LOG_DBG("Controller is busy"); - return -EBUSY; - } + const struct spi_dw_config *info = dev->config->config_info; + struct spi_dw_data *spi = dev->driver_data; + u32_t tmod = DW_SPI_CTRLR0_TMOD_TX_RX; + u32_t reg_data; + int ret; spi_context_lock(&spi->ctx, asynchronous, signal); @@ -276,34 +343,84 @@ static int transceive(struct spi_config *config, goto out; } + if (!rx_bufs || !rx_bufs->buffers) { + tmod = DW_SPI_CTRLR0_TMOD_TX; + } else if (!tx_bufs || !tx_bufs->buffers) { + tmod = DW_SPI_CTRLR0_TMOD_RX; + } + + /* ToDo: add a way to determine EEPROM mode */ + + if (tmod >= DW_SPI_CTRLR0_TMOD_RX && + !spi_dw_is_slave(spi)) { + reg_data = spi_dw_compute_ndf(rx_bufs->buffers, + rx_bufs->count, + spi->dfs); + if (reg_data == UINT32_MAX) { + ret = -EINVAL; + goto out; + } + + write_ctrlr1(reg_data, info->regs); + } else { + write_ctrlr1(0, info->regs); + } + + + if (spi_dw_is_slave(spi)) { + /* Enabling MISO line relevantly */ + if (tmod == DW_SPI_CTRLR0_TMOD_RX) { + tmod |= DW_SPI_CTRLR0_SLV_OE; + } else { + tmod &= ~DW_SPI_CTRLR0_SLV_OE; + } + } + + /* Updating TMOD in CTRLR0 register */ + write_ctrlr0(read_ctrlr0(info->regs) | tmod, info->regs); + /* Set buffers info */ - spi_context_buffers_setup(&spi->ctx, tx_bufs, tx_count, - rx_bufs, rx_count, spi->dfs); + spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, spi->dfs); spi->fifo_diff = 0; /* Tx Threshold */ - write_txftlr(DW_SPI_TXFTLR_DFLT, info->regs); + spi_dw_update_txftlr(info, spi); /* Does Rx thresholds needs to be lower? */ - if (spi->ctx.rx_len && spi->ctx.rx_len < DW_SPI_FIFO_DEPTH) { - rx_thsld = spi->ctx.rx_len - 1; - } + reg_data = DW_SPI_RXFTLR_DFLT; - /* Rx Threshold */ - write_rxftlr(rx_thsld, info->regs); + if (spi_dw_is_slave(spi)) { + if (spi->ctx.rx_len && + spi->ctx.rx_len < DW_SPI_RXFTLR_DFLT) { + reg_data = spi->ctx.rx_len - 1; + } - if (!rx_bufs) { - /* if there is no rx buffer, keep all rx interrupts masked */ - imask &= DW_SPI_IMR_MASK_RX; + reg_data = 0; + } else { + if (spi->ctx.rx_len && spi->ctx.rx_len < DW_SPI_FIFO_DEPTH) { + reg_data = spi->ctx.rx_len - 1; + } } + /* Rx Threshold */ + write_rxftlr(reg_data, info->regs); + /* Enable interrupts */ - write_imr(imask, info->regs); + reg_data = !rx_bufs ? + DW_SPI_IMR_UNMASK & DW_SPI_IMR_MASK_RX : + DW_SPI_IMR_UNMASK; + write_imr(reg_data, info->regs); + + SYS_LOG_DBG("Ctrlr0 0x%08x Ctrlr1 0x%04x Txftlr 0x%08x" + " Rxftlr 0x%08x Imr 0x%02x", + read_ctrlr0(info->regs), read_ctrlr1(info->regs), + read_txftlr(info->regs), read_rxftlr(info->regs), + read_imr(info->regs)); spi_context_cs_control(&spi->ctx, true); - /* Enable the controller */ + SYS_LOG_DBG("Enabling controller"); set_bit_ssienr(info->regs); ret = spi_context_wait_for_completion(&spi->ctx); @@ -313,43 +430,35 @@ static int transceive(struct spi_config *config, return ret; } -static int spi_dw_transceive(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count) +static int spi_dw_transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) { - SYS_LOG_DBG("%p, %p (%zu), %p (%zu)", - config->dev, tx_bufs, tx_count, rx_bufs, rx_count); + SYS_LOG_DBG("%p, %p, %p", dev, tx_bufs, rx_bufs); - return transceive(config, tx_bufs, tx_count, - rx_bufs, rx_count, false, NULL); + return transceive(dev, config, tx_bufs, rx_bufs, false, NULL); } -#ifdef CONFIG_POLL -static int spi_dw_transceive_async(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count, +#ifdef CONFIG_SPI_ASYNC +static int spi_dw_transceive_async(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, struct k_poll_signal *async) { - SYS_LOG_DBG("%p, %p (%zu), %p (%zu), %p", - config->dev, tx_bufs, tx_count, rx_bufs, rx_count, async); + SYS_LOG_DBG("%p, %p, %p, %p", dev, tx_bufs, rx_bufs, async); - return transceive(config, tx_bufs, tx_count, - rx_bufs, rx_count, true, async); + return transceive(dev, config, tx_bufs, rx_bufs, true, async); } -#endif /* CONFIG_POLL */ +#endif /* CONFIG_SPI_ASYNC */ -static int spi_dw_release(struct spi_config *config) +static int spi_dw_release(struct device *dev, const struct spi_config *config) { - const struct spi_dw_config *info = config->dev->config->config_info; - struct spi_dw_data *spi = config->dev->driver_data; + struct spi_dw_data *spi = dev->driver_data; - if (!spi_context_configured(&spi->ctx, config) || - test_bit_ssienr(info->regs) || test_bit_sr_busy(info->regs)) { - return -EBUSY; + if (!spi_context_configured(&spi->ctx, config)) { + return -EINVAL; } spi_context_unlock_unconditionally(&spi->ctx); @@ -361,15 +470,15 @@ void spi_dw_isr(struct device *dev) { const struct spi_dw_config *info = dev->config->config_info; u32_t int_status; - u8_t error; + int error; int_status = read_isr(info->regs); - SYS_LOG_DBG("SPI int_status 0x%x - (tx: %d, rx: %d)", + SYS_LOG_DBG("SPI %p int_status 0x%x - (tx: %d, rx: %d)", dev, int_status, read_txflr(info->regs), read_rxflr(info->regs)); if (int_status & DW_SPI_ISR_ERRORS_MASK) { - error = 1; + error = -EIO; goto out; } @@ -390,9 +499,9 @@ void spi_dw_isr(struct device *dev) static const struct spi_driver_api dw_spi_api = { .transceive = spi_dw_transceive, -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC .transceive_async = spi_dw_transceive_async, -#endif +#endif /* CONFIG_SPI_ASYNC */ .release = spi_dw_release, }; @@ -428,10 +537,12 @@ struct spi_dw_data spi_dw_data_port_0 = { const struct spi_dw_config spi_dw_config_0 = { .regs = SPI_DW_PORT_0_REGS, -#ifdef CONFIG_SPI_DW_CLOCK_GATE - .clock_data = UINT_TO_POINTER(CONFIG_SPI_0_CLOCK_GATE_SUBSYS), -#endif /* CONFIG_SPI_DW_CLOCK_GATE */ - .config_func = spi_config_0_irq +#ifdef CONFIG_SPI_DW_PORT_0_CLOCK_GATE + .clock_name = CONFIG_SPI_DW_PORT_1_CLOCK_GATE_DRV_NAME, + .clock_data = UINT_TO_POINTER(CONFIG_SPI_DW_PORT_0_CLOCK_GATE_SUBSYS), +#endif /* CONFIG_SPI_DW_PORT_0_CLOCK_GATE */ + .config_func = spi_config_0_irq, + .op_modes = CONFIG_SPI_0_OP_MODES }; DEVICE_AND_API_INIT(spi_dw_port_0, CONFIG_SPI_0_NAME, spi_dw_init, @@ -441,12 +552,12 @@ DEVICE_AND_API_INIT(spi_dw_port_0, CONFIG_SPI_0_NAME, spi_dw_init, void spi_config_0_irq(void) { -#ifdef CONFIG_SPI_DW_INTERRUPT_SINGLE_LINE +#ifdef CONFIG_SPI_DW_PORT_0_INTERRUPT_SINGLE_LINE IRQ_CONNECT(SPI_DW_PORT_0_IRQ, CONFIG_SPI_0_IRQ_PRI, spi_dw_isr, DEVICE_GET(spi_dw_port_0), SPI_DW_IRQ_FLAGS); irq_enable(SPI_DW_PORT_0_IRQ); _spi_int_unmask(SPI_DW_PORT_0_INT_MASK); -#else /* SPI_DW_INTERRUPT_SEPARATED_LINES */ +#else IRQ_CONNECT(IRQ_SPI0_RX_AVAIL, CONFIG_SPI_0_IRQ_PRI, spi_dw_isr, DEVICE_GET(spi_dw_port_0), SPI_DW_IRQ_FLAGS); IRQ_CONNECT(IRQ_SPI0_TX_REQ, CONFIG_SPI_0_IRQ_PRI, @@ -474,10 +585,12 @@ struct spi_dw_data spi_dw_data_port_1 = { static const struct spi_dw_config spi_dw_config_1 = { .regs = SPI_DW_PORT_1_REGS, -#ifdef CONFIG_SPI_DW_CLOCK_GATE - .clock_data = UINT_TO_POINTER(CONFIG_SPI_1_CLOCK_GATE_SUBSYS), -#endif /* CONFIG_SPI_DW_CLOCK_GATE */ - .config_func = spi_config_1_irq +#ifdef CONFIG_SPI_DW_PORT_1_CLOCK_GATE + .clock_name = CONFIG_SPI_DW_PORT_1_CLOCK_GATE_DRV_NAME, + .clock_data = UINT_TO_POINTER(CONFIG_SPI_DW_PORT_1_CLOCK_GATE_SUBSYS), +#endif /* CONFIG_SPI_DW_PORT_1_CLOCK_GATE */ + .config_func = spi_config_1_irq, + .op_modes = CONFIG_SPI_1_OP_MODES }; DEVICE_AND_API_INIT(spi_dw_port_1, CONFIG_SPI_1_NAME, spi_dw_init, @@ -487,12 +600,12 @@ DEVICE_AND_API_INIT(spi_dw_port_1, CONFIG_SPI_1_NAME, spi_dw_init, void spi_config_1_irq(void) { -#ifdef CONFIG_SPI_DW_INTERRUPT_SINGLE_LINE +#ifdef CONFIG_SPI_DW_PORT_1_INTERRUPT_SINGLE_LINE IRQ_CONNECT(SPI_DW_PORT_1_IRQ, CONFIG_SPI_1_IRQ_PRI, spi_dw_isr, DEVICE_GET(spi_dw_port_1), SPI_DW_IRQ_FLAGS); irq_enable(SPI_DW_PORT_1_IRQ); _spi_int_unmask(SPI_DW_PORT_1_INT_MASK); -#else /* SPI_DW_INTERRUPT_SEPARATED_LINES */ +#else IRQ_CONNECT(IRQ_SPI1_RX_AVAIL, CONFIG_SPI_1_IRQ_PRI, spi_dw_isr, DEVICE_GET(spi_dw_port_1), SPI_DW_IRQ_FLAGS); IRQ_CONNECT(IRQ_SPI1_TX_REQ, CONFIG_SPI_1_IRQ_PRI, @@ -510,3 +623,99 @@ void spi_config_1_irq(void) #endif } #endif /* CONFIG_SPI_1 */ +#ifdef CONFIG_SPI_2 +void spi_config_2_irq(void); + +struct spi_dw_data spi_dw_data_port_2 = { + SPI_CONTEXT_INIT_LOCK(spi_dw_data_port_2, ctx), + SPI_CONTEXT_INIT_SYNC(spi_dw_data_port_2, ctx), +}; + +static const struct spi_dw_config spi_dw_config_2 = { + .regs = SPI_DW_PORT_2_REGS, +#ifdef CONFIG_SPI_DW_PORT_2_CLOCK_GATE + .clock_name = CONFIG_SPI_DW_PORT_2_CLOCK_GATE_DRV_NAME, + .clock_data = UINT_TO_POINTER(CONFIG_SPI_DW_PORT_2_CLOCK_GATE_SUBSYS), +#endif /* CONFIG_SPI_DW_PORT_2_CLOCK_GATE */ + .config_func = spi_config_2_irq, + .op_modes = CONFIG_SPI_2_OP_MODES +}; + +DEVICE_AND_API_INIT(spi_dw_port_2, CONFIG_SPI_2_NAME, spi_dw_init, + &spi_dw_data_port_2, &spi_dw_config_2, + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, + &dw_spi_api); + +void spi_config_2_irq(void) +{ +#ifdef CONFIG_SPI_DW_PORT_2_INTERRUPT_SINGLE_LINE + IRQ_CONNECT(SPI_DW_PORT_2_IRQ, CONFIG_SPI_2_IRQ_PRI, + spi_dw_isr, DEVICE_GET(spi_dw_port_2), SPI_DW_IRQ_FLAGS); + irq_enable(SPI_DW_PORT_2_IRQ); + _spi_int_unmask(SPI_DW_PORT_2_INT_MASK); +#else + IRQ_CONNECT(IRQ_SPI2_RX_AVAIL, CONFIG_SPI_2_IRQ_PRI, + spi_dw_isr, DEVICE_GET(spi_dw_port_2), SPI_DW_IRQ_FLAGS); + IRQ_CONNECT(IRQ_SPI2_TX_REQ, CONFIG_SPI_2_IRQ_PRI, + spi_dw_isr, DEVICE_GET(spi_dw_port_2), SPI_DW_IRQ_FLAGS); + IRQ_CONNECT(IRQ_SPI2_ERR_INT, CONFIG_SPI_2_IRQ_PRI, + spi_dw_isr, DEVICE_GET(spi_dw_port_2), SPI_DW_IRQ_FLAGS); + + irq_enable(IRQ_SPI2_RX_AVAIL); + irq_enable(IRQ_SPI2_TX_REQ); + irq_enable(IRQ_SPI2_ERR_INT); + + _spi_int_unmask(SPI_DW_PORT_2_RX_INT_MASK); + _spi_int_unmask(SPI_DW_PORT_2_TX_INT_MASK); + _spi_int_unmask(SPI_DW_PORT_2_ERROR_INT_MASK); +#endif +} +#endif /* CONFIG_SPI_2 */ +#ifdef CONFIG_SPI_3 +void spi_config_3_irq(void); + +struct spi_dw_data spi_dw_data_port_3 = { + SPI_CONTEXT_INIT_LOCK(spi_dw_data_port_3, ctx), + SPI_CONTEXT_INIT_SYNC(spi_dw_data_port_3, ctx), +}; + +static const struct spi_dw_config spi_dw_config_3 = { + .regs = SPI_DW_PORT_3_REGS, +#ifdef CONFIG_SPI_DW_PORT_3_CLOCK_GATE + .clock_name = CONFIG_SPI_DW_PORT_3_CLOCK_GATE_DRV_NAME, + .clock_data = UINT_TO_POINTER(CONFIG_SPI_DW_PORT_3_CLOCK_GATE_SUBSYS), +#endif /* CONFIG_SPI_DW_PORT_3_CLOCK_GATE */ + .config_func = spi_config_3_irq, + .op_modes = CONFIG_SPI_3_OP_MODES +}; + +DEVICE_AND_API_INIT(spi_dw_port_3, CONFIG_SPI_3_NAME, spi_dw_init, + &spi_dw_data_port_3, &spi_dw_config_3, + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, + &dw_spi_api); + +void spi_config_3_irq(void) +{ +#ifdef CONFIG_SPI_DW_PORT_3_INTERRUPT_SINGLE_LINE + IRQ_CONNECT(SPI_DW_PORT_3_IRQ, CONFIG_SPI_3_IRQ_PRI, + spi_dw_isr, DEVICE_GET(spi_dw_port_3), SPI_DW_IRQ_FLAGS); + irq_enable(SPI_DW_PORT_3_IRQ); + _spi_int_unmask(SPI_DW_PORT_3_INT_MASK); +#else + IRQ_CONNECT(IRQ_SPI3_RX_AVAIL, CONFIG_SPI_3_IRQ_PRI, + spi_dw_isr, DEVICE_GET(spi_dw_port_3), SPI_DW_IRQ_FLAGS); + IRQ_CONNECT(IRQ_SPI3_TX_REQ, CONFIG_SPI_3_IRQ_PRI, + spi_dw_isr, DEVICE_GET(spi_dw_port_3), SPI_DW_IRQ_FLAGS); + IRQ_CONNECT(IRQ_SPI3_ERR_INT, CONFIG_SPI_3_IRQ_PRI, + spi_dw_isr, DEVICE_GET(spi_dw_port_3), SPI_DW_IRQ_FLAGS); + + irq_enable(IRQ_SPI3_RX_AVAIL); + irq_enable(IRQ_SPI3_TX_REQ); + irq_enable(IRQ_SPI3_ERR_INT); + + _spi_int_unmask(SPI_DW_PORT_3_RX_INT_MASK); + _spi_int_unmask(SPI_DW_PORT_3_TX_INT_MASK); + _spi_int_unmask(SPI_DW_PORT_3_ERROR_INT_MASK); +#endif +} +#endif /* CONFIG_SPI_3 */ diff --git a/drivers/spi/spi_dw.h b/drivers/spi/spi_dw.h index 858d58478b35..4d320cea9d38 100644 --- a/drivers/spi/spi_dw.h +++ b/drivers/spi/spi_dw.h @@ -20,43 +20,25 @@ typedef void (*spi_dw_config_t)(void); /* Private structures */ struct spi_dw_config { u32_t regs; -#ifdef CONFIG_SPI_DW_CLOCK_GATE +#ifdef CONFIG_CLOCK_CONTROL + const char *clock_name; void *clock_data; -#endif /* CONFIG_SPI_DW_CLOCK_GATE */ +#endif /* CONFIG_CLOCK_CONTROL */ spi_dw_config_t config_func; + u8_t op_modes; }; -#if defined(CONFIG_SPI_LEGACY_API) -struct spi_dw_data { - struct k_sem device_sync_sem; - u32_t error:1; - u32_t dfs:3; /* dfs in bytes: 1,2 or 4 */ - u32_t slave:17; /* up 16 slaves */ - u32_t fifo_diff:9; /* cannot be bigger than FIFO depth */ - u32_t last_tx:1; - u32_t _unused:1; -#ifdef CONFIG_SPI_DW_CLOCK_GATE - struct device *clock; -#endif /* CONFIG_SPI_DW_CLOCK_GATE */ - const u8_t *tx_buf; - u32_t tx_buf_len; - u8_t *rx_buf; - u32_t rx_buf_len; -}; -#else - #include "spi_context.h" struct spi_dw_data { -#ifdef CONFIG_SPI_DW_CLOCK_GATE +#ifdef CONFIG_CLOCK_CONTROL struct device *clock; -#endif /* CONFIG_SPI_DW_CLOCK_GATE */ +#endif /* CONFIG_CLOCK_CONTROL */ struct spi_context ctx; u8_t dfs; /* dfs in bytes: 1,2 or 4 */ u8_t fifo_diff; /* cannot be bigger than FIFO depth */ u16_t _unused; }; -#endif /* CONFIG_SPI_LEGACY_API */ /* Helper macros */ @@ -124,6 +106,15 @@ struct spi_dw_data { #define DW_SPI_CTRLR0_SCPOL BIT(DW_SPI_CTRLR0_SCPOL_BIT) #define DW_SPI_CTRLR0_SRL BIT(DW_SPI_CTRLR0_SRL_BIT) +#define DW_SPI_CTRLR0_SLV_OE_BIT (10) +#define DW_SPI_CTRLR0_SLV_OE BIT(DW_SPI_CTRLR0_SLV_OE_BIT) + +#define DW_SPI_CTRLR0_TMOD_SHIFT (8) +#define DW_SPI_CTRLR0_TMOD_TX_RX (0) +#define DW_SPI_CTRLR0_TMOD_TX (1 << DW_SPI_CTRLR0_TMOD_SHIFT) +#define DW_SPI_CTRLR0_TMOD_RX (2 << DW_SPI_CTRLR0_TMOD_SHIFT) +#define DW_SPI_CTRLR0_TMOD_EEPROM (3 << DW_SPI_CTRLR0_TMOD_SHIFT) + #define DW_SPI_CTRLR0_DFS_16(__bpw) ((__bpw) - 1) #define DW_SPI_CTRLR0_DFS_32(__bpw) (((__bpw) - 1) << 16) @@ -208,47 +199,11 @@ struct spi_dw_data { #include "spi_dw_quark_se_ss_regs.h" #else #include "spi_dw_regs.h" -#endif - -/* GPIO used to emulate CS */ -#if defined(CONFIG_SPI_LEGACY_API) -#ifdef CONFIG_SPI_DW_CS_GPIO - -#include - -static inline void _spi_config_cs(struct device *dev) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - struct device *gpio; - gpio = device_get_binding(info->cs_gpio_name); - if (!gpio) { - spi->cs_gpio_port = NULL; - return; - } - - gpio_pin_configure(gpio, info->cs_gpio_pin, GPIO_DIR_OUT); - /* Default CS line to high (idling) */ - gpio_pin_write(gpio, info->cs_gpio_pin, 1); - - spi->cs_gpio_port = gpio; -} - -static inline void _spi_control_cs(struct device *dev, int on) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; +#define _extra_clock_on(...) +#define _extra_clock_off(...) - if (spi->cs_gpio_port) { - gpio_pin_write(spi->cs_gpio_port, info->cs_gpio_pin, !on); - } -} -#else -#define _spi_control_cs(...) -#define _spi_config_cs(...) -#endif /* CONFIG_SPI_DW_CS_GPIO */ -#endif /* CONFIG_SPI_LEGACY_API */ +#endif /* Interrupt mask * SoC SPECIFIC! @@ -271,6 +226,7 @@ DEFINE_MM_REG_WRITE(baudr, DW_SPI_REG_BAUDR, 16) DEFINE_MM_REG_READ(txflr, DW_SPI_REG_TXFLR, 32) DEFINE_MM_REG_READ(rxflr, DW_SPI_REG_RXFLR, 32) DEFINE_MM_REG_WRITE(imr, DW_SPI_REG_IMR, 8) +DEFINE_MM_REG_READ(imr, DW_SPI_REG_IMR, 8) DEFINE_MM_REG_READ(isr, DW_SPI_REG_ISR, 8) DEFINE_SET_BIT_OP(ssienr, DW_SPI_REG_SSIENR, DW_SPI_SSIENR_SSIEN_BIT) @@ -278,6 +234,59 @@ DEFINE_CLEAR_BIT_OP(ssienr, DW_SPI_REG_SSIENR, DW_SPI_SSIENR_SSIEN_BIT) DEFINE_TEST_BIT_OP(ssienr, DW_SPI_REG_SSIENR, DW_SPI_SSIENR_SSIEN_BIT) DEFINE_TEST_BIT_OP(sr_busy, DW_SPI_REG_SR, DW_SPI_SR_BUSY_BIT) +#ifdef CONFIG_CLOCK_CONTROL + +#include + +static inline int _clock_config(struct device *dev) +{ + const struct spi_dw_config *info = dev->config->config_info; + struct spi_dw_data *spi = dev->driver_data; + + if (!info->clock_name || strlen(info->clock_name) == 0) { + spi->clock = NULL; + return 0; + } + + spi->clock = device_get_binding(info->clock_name); + if (!spi->clock) { + return -ENODEV; + } + + return 0; +} + +static inline void _clock_on(struct device *dev) +{ + struct spi_dw_data *spi = dev->driver_data; + + if (spi->clock) { + const struct spi_dw_config *info = dev->config->config_info; + + clock_control_on(spi->clock, info->clock_data); + } + + _extra_clock_on(dev); +} + +static inline void _clock_off(struct device *dev) +{ + struct spi_dw_data *spi = dev->driver_data; + + if (spi->clock) { + const struct spi_dw_config *info = dev->config->config_info; + + clock_control_off(spi->clock, info->clock_data); + } + + _extra_clock_off(dev); +} +#else +#define _clock_config(...) +#define _clock_on(...) +#define _clock_off(...) +#endif /* CONFIG_CLOCK_CONTROL */ + #ifdef __cplusplus } #endif diff --git a/drivers/spi/spi_dw_legacy.c b/drivers/spi/spi_dw_legacy.c deleted file mode 100644 index a339f99e03b0..000000000000 --- a/drivers/spi/spi_dw_legacy.c +++ /dev/null @@ -1,513 +0,0 @@ -/* spi_dw.c - Designware SPI driver implementation */ - -/* - * Copyright (c) 2015 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include "spi_dw.h" - -#ifdef CONFIG_IOAPIC -#include -#endif - -#define SYS_LOG_DOMAIN "SPI DW" -#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL -#include - -#if (CONFIG_SYS_LOG_SPI_LEVEL == 4) -#define DBG_COUNTER_INIT() \ - u32_t __cnt = 0 -#define DBG_COUNTER_INC() \ - (__cnt++) -#define DBG_COUNTER_RESULT() \ - (__cnt) -#else -#define DBG_COUNTER_INIT() {; } -#define DBG_COUNTER_INC() {; } -#define DBG_COUNTER_RESULT() 0 -#endif - -static void completed(struct device *dev, int error) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - - if (error) { - goto out; - } - - /* - * There are several situations here. - * 1. spi_write w rx_buf - need last_tx && rx_buf_len zero to be done. - * 2. spi_write w/o rx_buf - only need to determine when write is done. - * 3. spi_read - need rx_buf_len zero. - */ - if (spi->tx_buf && spi->rx_buf) { - if (!spi->last_tx || spi->rx_buf_len) { - return; - } - } else if (spi->tx_buf) { - if (!spi->last_tx) { - return; - } - } else { /* or, spi->rx_buf!=0 */ - if (spi->rx_buf_len) { - return; - } - } - -out: - /* need to give time for FIFOs to drain before issuing more commands */ - while (test_bit_sr_busy(info->regs)) { - } - - spi->error = error; - - /* Disabling interrupts */ - write_imr(DW_SPI_IMR_MASK, info->regs); - /* Disabling the controller */ - clear_bit_ssienr(info->regs); - - _spi_control_cs(dev, 0); - - SYS_LOG_DBG("SPI transaction completed %s error", - error ? "with" : "without"); - - k_sem_give(&spi->device_sync_sem); -} - -static void push_data(struct device *dev) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - u32_t data = 0; - u32_t f_tx; - DBG_COUNTER_INIT(); - - if (spi->rx_buf) { - f_tx = DW_SPI_FIFO_DEPTH - read_txflr(info->regs) - - read_rxflr(info->regs); - if ((int)f_tx < 0) { - f_tx = 0; /* if rx-fifo is full, hold off tx */ - } - } else { - f_tx = DW_SPI_FIFO_DEPTH - read_txflr(info->regs); - } - - if (f_tx && (spi->tx_buf_len == 0)) { - /* room in fifo, yet nothing to send */ - spi->last_tx = 1; /* setting last_tx indicates TX is done */ - } - - while (f_tx) { - if (spi->tx_buf && spi->tx_buf_len > 0) { - switch (spi->dfs) { - case 1: - data = UNALIGNED_GET((u8_t *)(spi->tx_buf)); - break; - case 2: - data = UNALIGNED_GET((u16_t *)(spi->tx_buf)); - break; -#ifndef CONFIG_ARC - case 4: - data = UNALIGNED_GET((u32_t *)(spi->tx_buf)); - break; -#endif - } - - spi->tx_buf += spi->dfs; - spi->tx_buf_len--; - } else if (spi->rx_buf && spi->rx_buf_len > 0) { - /* No need to push more than necessary */ - if (spi->rx_buf_len - spi->fifo_diff <= 0) { - break; - } - - data = 0; - } else { - /* Nothing to push anymore */ - break; - } - - write_dr(data, info->regs); - f_tx--; - spi->fifo_diff++; - DBG_COUNTER_INC(); - } - - if (spi->last_tx) { - write_txftlr(0, info->regs); - /* prevents any further interrupts demanding TX fifo fill */ - } - - SYS_LOG_DBG("Pushed: %d", DBG_COUNTER_RESULT()); -} - -static void pull_data(struct device *dev) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - u32_t data = 0; - DBG_COUNTER_INIT(); - - while (read_rxflr(info->regs)) { - data = read_dr(info->regs); - DBG_COUNTER_INC(); - - if (spi->rx_buf && spi->rx_buf_len > 0) { - switch (spi->dfs) { - case 1: - UNALIGNED_PUT(data, (u8_t *)spi->rx_buf); - break; - case 2: - UNALIGNED_PUT(data, (u16_t *)spi->rx_buf); - break; -#ifndef CONFIG_ARC - case 4: - UNALIGNED_PUT(data, (u32_t *)spi->rx_buf); - break; -#endif - } - - spi->rx_buf += spi->dfs; - spi->rx_buf_len--; - } - - spi->fifo_diff--; - } - - if (!spi->rx_buf_len && spi->tx_buf_len < DW_SPI_FIFO_DEPTH) { - write_rxftlr(spi->tx_buf_len - 1, info->regs); - } else if (read_rxftlr(info->regs) >= spi->rx_buf_len) { - write_rxftlr(spi->rx_buf_len - 1, info->regs); - } - - SYS_LOG_DBG("Pulled: %d", DBG_COUNTER_RESULT()); -} - -static inline bool _spi_dw_is_controller_ready(struct device *dev) -{ - const struct spi_dw_config *info = dev->config->config_info; - - if (test_bit_ssienr(info->regs) || test_bit_sr_busy(info->regs)) { - return false; - } - - return true; -} - -static int spi_dw_configure(struct device *dev, - struct spi_config *config) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - u32_t flags = config->config; - u32_t ctrlr0 = 0; - u32_t mode; - - SYS_LOG_DBG("%p (0x%x), %p", dev, info->regs, config); - - /* Check status */ - if (!_spi_dw_is_controller_ready(dev)) { - SYS_LOG_DBG("Controller is busy"); - return -EBUSY; - } - - /* Word size */ - ctrlr0 |= DW_SPI_CTRLR0_DFS(SPI_WORD_SIZE_GET(flags)); - - /* Determine how many bytes are required per-frame */ - spi->dfs = SPI_WS_TO_DFS(SPI_WORD_SIZE_GET(flags)); - - /* SPI mode */ - mode = SPI_MODE(flags); - if (mode & SPI_MODE_CPOL) { - ctrlr0 |= DW_SPI_CTRLR0_SCPOL; - } - - if (mode & SPI_MODE_CPHA) { - ctrlr0 |= DW_SPI_CTRLR0_SCPH; - } - - if (mode & SPI_MODE_LOOP) { - ctrlr0 |= DW_SPI_CTRLR0_SRL; - } - - /* Installing the configuration */ - write_ctrlr0(ctrlr0, info->regs); - - /* - * Configure the rate. Use this small hack to allow the user to call - * spi_configure() with both a divider (as the driver was initially - * written) and a frequency (as the SPI API suggests to). The clock - * divider is a 16bit value, hence we can fairly, and safely, assume - * that everything above this value is a frequency. The trade-off is - * that if one wants to use a bus frequency of 64kHz (or less), it has - * the use a divider... - */ - if (config->max_sys_freq > 0xffff) { - write_baudr(SPI_DW_CLK_DIVIDER(config->max_sys_freq), - info->regs); - } else { - write_baudr(config->max_sys_freq, info->regs); - } - - return 0; -} - -static int spi_dw_slave_select(struct device *dev, u32_t slave) -{ - struct spi_dw_data *spi = dev->driver_data; - - SYS_LOG_DBG("%p %d", dev, slave); - - if (slave == 0 || slave > 16) { - return -EINVAL; - } - - spi->slave = 1 << (slave - 1); - - return 0; -} - -static int spi_dw_transceive(struct device *dev, - const void *tx_buf, u32_t tx_buf_len, - void *rx_buf, u32_t rx_buf_len) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - u32_t rx_thsld = DW_SPI_RXFTLR_DFLT; - u32_t imask; - - SYS_LOG_DBG("%p, %p, %u, %p, %u", - dev, tx_buf, tx_buf_len, rx_buf, rx_buf_len); - - /* Check status */ - if (!_spi_dw_is_controller_ready(dev)) { - SYS_LOG_DBG("Controller is busy"); - return -EBUSY; - } - - /* Set buffers info */ - spi->tx_buf = tx_buf; - spi->tx_buf_len = tx_buf_len/spi->dfs; - spi->rx_buf = rx_buf; - if (rx_buf) { - spi->rx_buf_len = rx_buf_len/spi->dfs; - } else { - spi->rx_buf_len = 0; /* must be zero if no buffer */ - } - spi->fifo_diff = 0; - spi->last_tx = 0; - - /* Tx Threshold */ - write_txftlr(DW_SPI_TXFTLR_DFLT, info->regs); - - /* Does Rx thresholds needs to be lower? */ - if (spi->rx_buf_len && spi->rx_buf_len < DW_SPI_FIFO_DEPTH) { - rx_thsld = spi->rx_buf_len - 1; - } else if (!spi->rx_buf_len && spi->tx_buf_len < DW_SPI_FIFO_DEPTH) { - rx_thsld = spi->tx_buf_len - 1; - /* TODO: why? */ - } - - write_rxftlr(rx_thsld, info->regs); - - /* Slave select */ - write_ser(spi->slave, info->regs); - - _spi_control_cs(dev, 1); - - /* Enable interrupts */ - imask = DW_SPI_IMR_UNMASK; - if (!rx_buf) { - /* if there is no rx buffer, keep all rx interrupts masked */ - imask &= DW_SPI_IMR_MASK_RX; - } - - write_imr(imask, info->regs); - - /* Enable the controller */ - set_bit_ssienr(info->regs); - - k_sem_take(&spi->device_sync_sem, K_FOREVER); - - if (spi->error) { - spi->error = 0; - return -EIO; - } - - return 0; -} - -void spi_dw_isr(void *arg) -{ - struct device *dev = (struct device *)arg; - const struct spi_dw_config *info = dev->config->config_info; - u32_t error = 0; - u32_t int_status; - - int_status = read_isr(info->regs); - - SYS_LOG_DBG("SPI int_status 0x%x - (tx: %d, rx: %d)", - int_status, read_txflr(info->regs), read_rxflr(info->regs)); - - if (int_status & DW_SPI_ISR_ERRORS_MASK) { - error = 1; - goto out; - } - - if (int_status & DW_SPI_ISR_RXFIS) { - pull_data(dev); - } - - if (int_status & DW_SPI_ISR_TXEIS) { - push_data(dev); - } - -out: - clear_interrupts(info->regs); - completed(dev, error); -} - -static const struct spi_driver_api dw_spi_api = { - .configure = spi_dw_configure, - .slave_select = spi_dw_slave_select, - .transceive = spi_dw_transceive, -}; - -int spi_dw_init(struct device *dev) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - - _clock_config(dev); - _clock_on(dev); - - info->config_func(); - - k_sem_init(&spi->device_sync_sem, 0, UINT_MAX); - - _spi_config_cs(dev); - - /* Masking interrupt and making sure controller is disabled */ - write_imr(DW_SPI_IMR_MASK, info->regs); - clear_bit_ssienr(info->regs); - - SYS_LOG_DBG("Designware SPI driver initialized on device: %p", dev); - - return 0; -} - - -#ifdef CONFIG_SPI_0 -void spi_config_0_irq(void); - -struct spi_dw_data spi_dw_data_port_0; - -const struct spi_dw_config spi_dw_config_0 = { - .regs = SPI_DW_PORT_0_REGS, -#ifdef CONFIG_SPI_DW_CLOCK_GATE - .clock_data = UINT_TO_POINTER(CONFIG_SPI_0_CLOCK_GATE_SUBSYS), -#endif /* CONFIG_SPI_DW_CLOCK_GATE */ -#ifdef CONFIG_SPI_DW_CS_GPIO - .cs_gpio_name = CONFIG_SPI_0_CS_GPIO_PORT, - .cs_gpio_pin = CONFIG_SPI_0_CS_GPIO_PIN, -#endif - .config_func = spi_config_0_irq -}; - -DEVICE_AND_API_INIT(spi_dw_port_0, CONFIG_SPI_0_NAME, spi_dw_init, - &spi_dw_data_port_0, &spi_dw_config_0, - POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, - &dw_spi_api); - -void spi_config_0_irq(void) -{ -#ifdef CONFIG_SPI_DW_INTERRUPT_SINGLE_LINE - IRQ_CONNECT(SPI_DW_PORT_0_IRQ, CONFIG_SPI_0_IRQ_PRI, - spi_dw_isr, DEVICE_GET(spi_dw_port_0), SPI_DW_IRQ_FLAGS); - irq_enable(SPI_DW_PORT_0_IRQ); - _spi_int_unmask(SPI_DW_PORT_0_INT_MASK); -#else /* SPI_DW_INTERRUPT_SEPARATED_LINES */ - IRQ_CONNECT(IRQ_SPI0_RX_AVAIL, CONFIG_SPI_0_IRQ_PRI, - spi_dw_isr, DEVICE_GET(spi_dw_port_0), SPI_DW_IRQ_FLAGS); - IRQ_CONNECT(IRQ_SPI0_TX_REQ, CONFIG_SPI_0_IRQ_PRI, - spi_dw_isr, DEVICE_GET(spi_dw_port_0), SPI_DW_IRQ_FLAGS); - IRQ_CONNECT(IRQ_SPI0_ERR_INT, CONFIG_SPI_0_IRQ_PRI, - spi_dw_isr, DEVICE_GET(spi_dw_port_0), SPI_DW_IRQ_FLAGS); - - irq_enable(IRQ_SPI0_RX_AVAIL); - irq_enable(IRQ_SPI0_TX_REQ); - irq_enable(IRQ_SPI0_ERR_INT); - - _spi_int_unmask(SPI_DW_PORT_0_RX_INT_MASK); - _spi_int_unmask(SPI_DW_PORT_0_TX_INT_MASK); - _spi_int_unmask(SPI_DW_PORT_0_ERROR_INT_MASK); -#endif -} -#endif /* CONFIG_SPI_0 */ -#ifdef CONFIG_SPI_1 -void spi_config_1_irq(void); - -struct spi_dw_data spi_dw_data_port_1; - -static const struct spi_dw_config spi_dw_config_1 = { - .regs = SPI_DW_PORT_1_REGS, -#ifdef CONFIG_SPI_DW_CLOCK_GATE - .clock_data = UINT_TO_POINTER(CONFIG_SPI_1_CLOCK_GATE_SUBSYS), -#endif /* CONFIG_SPI_DW_CLOCK_GATE */ -#ifdef CONFIG_SPI_DW_CS_GPIO - .cs_gpio_name = CONFIG_SPI_1_CS_GPIO_PORT, - .cs_gpio_pin = CONFIG_SPI_1_CS_GPIO_PIN, -#endif - .config_func = spi_config_1_irq -}; - -DEVICE_AND_API_INIT(spi_dw_port_1, CONFIG_SPI_1_NAME, spi_dw_init, - &spi_dw_data_port_1, &spi_dw_config_1, - POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, - &dw_spi_api); - -void spi_config_1_irq(void) -{ -#ifdef CONFIG_SPI_DW_INTERRUPT_SINGLE_LINE - IRQ_CONNECT(SPI_DW_PORT_1_IRQ, CONFIG_SPI_1_IRQ_PRI, - spi_dw_isr, DEVICE_GET(spi_dw_port_1), SPI_DW_IRQ_FLAGS); - irq_enable(SPI_DW_PORT_1_IRQ); - _spi_int_unmask(SPI_DW_PORT_1_INT_MASK); -#else /* SPI_DW_INTERRUPT_SEPARATED_LINES */ - IRQ_CONNECT(IRQ_SPI1_RX_AVAIL, CONFIG_SPI_1_IRQ_PRI, - spi_dw_isr, DEVICE_GET(spi_dw_port_1), SPI_DW_IRQ_FLAGS); - IRQ_CONNECT(IRQ_SPI1_TX_REQ, CONFIG_SPI_1_IRQ_PRI, - spi_dw_isr, DEVICE_GET(spi_dw_port_1), SPI_DW_IRQ_FLAGS); - IRQ_CONNECT(IRQ_SPI1_ERR_INT, CONFIG_SPI_1_IRQ_PRI, - spi_dw_isr, DEVICE_GET(spi_dw_port_1), SPI_DW_IRQ_FLAGS); - - irq_enable(IRQ_SPI1_RX_AVAIL); - irq_enable(IRQ_SPI1_TX_REQ); - irq_enable(IRQ_SPI1_ERR_INT); - - _spi_int_unmask(SPI_DW_PORT_1_RX_INT_MASK); - _spi_int_unmask(SPI_DW_PORT_1_TX_INT_MASK); - _spi_int_unmask(SPI_DW_PORT_1_ERROR_INT_MASK); -#endif -} -#endif /* CONFIG_SPI_1 */ diff --git a/drivers/spi/spi_dw_quark_se_ss_regs.h b/drivers/spi/spi_dw_quark_se_ss_regs.h index 930ac610d1bd..ae3b81559109 100644 --- a/drivers/spi/spi_dw_quark_se_ss_regs.h +++ b/drivers/spi/spi_dw_quark_se_ss_regs.h @@ -59,6 +59,11 @@ extern "C" { * *_b function only used for creating proper ser one */ DEFINE_MM_REG_READ(ctrlr0_b, DW_SPI_REG_CTRLR0, 16) +static inline u32_t read_ctrlr0(u32_t addr) +{ + return read_ctrlr0_b(addr); +} + DEFINE_MM_REG_WRITE(ctrlr0_b, DW_SPI_REG_CTRLR0, 16) static inline void write_ctrlr0(u32_t data, u32_t addr) { @@ -66,6 +71,13 @@ static inline void write_ctrlr0(u32_t data, u32_t addr) data, addr); } +DEFINE_MM_REG_READ(ctrlr1_b, DW_SPI_REG_CTRLR0, 32) +DEFINE_MM_REG_WRITE(ctrlr1_b, DW_SPI_REG_CTRLR0, 32) +static inline void write_ctrlr1(u32_t data, u32_t addr) +{ + write_ctrlr1_b((read_ctrlr1_b(addr) & (data << 16)), addr); +} + DEFINE_MM_REG_READ(ssienr_b, DW_SPI_REG_SSIENR, 8) DEFINE_MM_REG_WRITE(ssienr_b, DW_SPI_REG_SSIENR, 8) static inline void write_ser(u32_t data, u32_t addr) @@ -120,16 +132,14 @@ static inline u32_t read_dr(u32_t addr) DEFINE_SET_BIT_OP(clk_ena, DW_SPI_REG_CTRLR0, DW_SPI_CTRLR0_CLK_ENA_BIT) DEFINE_CLEAR_BIT_OP(clk_ena, DW_SPI_REG_CTRLR0, DW_SPI_CTRLR0_CLK_ENA_BIT) -#define _clock_config(...) - -static inline void _clock_on(struct device *dev) +static inline void _extra_clock_on(struct device *dev) { const struct spi_dw_config *info = dev->config->config_info; set_bit_clk_ena(info->regs); } -static inline void _clock_off(struct device *dev) +static inline void _extra_clock_off(struct device *dev) { const struct spi_dw_config *info = dev->config->config_info; diff --git a/drivers/spi/spi_dw_regs.h b/drivers/spi/spi_dw_regs.h index 8f002f7a3f20..600f78fd5933 100644 --- a/drivers/spi/spi_dw_regs.h +++ b/drivers/spi/spi_dw_regs.h @@ -42,6 +42,9 @@ extern "C" { /* Register helpers */ DEFINE_MM_REG_WRITE(ctrlr0, DW_SPI_REG_CTRLR0, 32) +DEFINE_MM_REG_READ(ctrlr0, DW_SPI_REG_CTRLR0, 32) +DEFINE_MM_REG_WRITE(ctrlr1, DW_SPI_REG_CTRLR1, 16) +DEFINE_MM_REG_READ(ctrlr1, DW_SPI_REG_CTRLR1, 16) DEFINE_MM_REG_WRITE(ser, DW_SPI_REG_SER, 8) DEFINE_MM_REG_WRITE(txftlr, DW_SPI_REG_TXFTLR, 32) DEFINE_MM_REG_WRITE(rxftlr, DW_SPI_REG_RXFTLR, 32) @@ -55,41 +58,6 @@ DEFINE_MM_REG_READ(ssi_comp_version, DW_SPI_REG_SSI_COMP_VERSION, 32) DEFINE_TEST_BIT_OP(icr, DW_SPI_REG_ICR, DW_SPI_SR_ICR_BIT) #define clear_interrupts(addr) test_bit_icr(addr) -#ifdef CONFIG_SPI_DW_CLOCK_GATE -static inline void _clock_config(struct device *dev) -{ - struct device *clk; - char *drv = CONFIG_SPI_DW_CLOCK_GATE_DRV_NAME; - - clk = device_get_binding(drv); - if (clk) { - struct spi_dw_data *spi = dev->driver_data; - - spi->clock = clk; - } -} - -static inline void _clock_on(struct device *dev) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - - clock_control_on(spi->clock, info->clock_data); -} - -static inline void _clock_off(struct device *dev) -{ - const struct spi_dw_config *info = dev->config->config_info; - struct spi_dw_data *spi = dev->driver_data; - - clock_control_off(spi->clock, info->clock_data); -} -#else -#define _clock_config(...) -#define _clock_on(...) -#define _clock_off(...) -#endif /* CONFIG_SPI_DW_CLOCK_GATE */ - #ifdef __cplusplus } #endif diff --git a/drivers/spi/spi_handlers.c b/drivers/spi/spi_handlers.c index 32e9b69a9e3a..92ad80a3c262 100644 --- a/drivers/spi/spi_handlers.c +++ b/drivers/spi/spi_handlers.c @@ -7,8 +7,7 @@ #include #include -#ifndef CONFIG_SPI_LEGACY_API -static void verify_spi_buf_array(struct spi_buf *bufs, size_t len, +static void verify_spi_buf_array(const struct spi_buf *bufs, size_t len, int writable, void *ssf) { /* Empty array, nothing to do */ @@ -27,22 +26,34 @@ static void verify_spi_buf_array(struct spi_buf *bufs, size_t len, } } -_SYSCALL_HANDLER(spi_transceive, config_p, tx_bufs, tx_count, rx_bufs, - rx_count) +_SYSCALL_HANDLER(spi_transceive, dev, config_p, tx_bufs, rx_bufs) { - struct spi_config *config = (struct spi_config *)config_p; + const struct spi_config *config = (const struct spi_config *)config_p; _SYSCALL_MEMORY_READ(config, sizeof(*config)); - _SYSCALL_OBJ(config->dev, K_OBJ_DRIVER_SPI); + _SYSCALL_OBJ(dev, K_OBJ_DRIVER_SPI); /* ssf is implicit system call stack frame parameter, used by * _SYSCALL_* APIs when something goes wrong. */ - verify_spi_buf_array((struct spi_buf *)tx_bufs, tx_count, 0, ssf); - verify_spi_buf_array((struct spi_buf *)rx_bufs, rx_count, 1, ssf); + if (tx_bufs) { + const struct spi_buf_set *tx = + (const struct spi_buf_set *)tx_bufs; + + _SYSCALL_MEMORY_READ(tx_bufs, sizeof(struct spi_buf_set)); + verify_spi_buf_array(tx->buffers, tx->count, 0, ssf); + } + + if (rx_bufs) { + const struct spi_buf_set *rx = + (const struct spi_buf_set *)rx_bufs; + + _SYSCALL_MEMORY_READ(rx_bufs, sizeof(struct spi_buf_set)); + verify_spi_buf_array(rx->buffers, rx->count, 1, ssf); + } if (config->cs) { - struct spi_cs_control *cs = config->cs; + const struct spi_cs_control *cs = config->cs; _SYSCALL_MEMORY_READ(cs, sizeof(*cs)); if (cs->gpio_dev) { @@ -50,17 +61,16 @@ _SYSCALL_HANDLER(spi_transceive, config_p, tx_bufs, tx_count, rx_bufs, } } - return _impl_spi_transceive(config, (const struct spi_buf *)tx_bufs, - tx_count, (struct spi_buf *)rx_bufs, - rx_count); + return _impl_spi_transceive((struct device *)dev, config, + (const struct spi_buf_set *)tx_bufs, + (const struct spi_buf_set *)rx_bufs); } -_SYSCALL_HANDLER(spi_release, config_p) +_SYSCALL_HANDLER(spi_release, dev, config_p) { - struct spi_config *config = (struct spi_config *)config_p; + const struct spi_config *config = (const struct spi_config *)config_p; _SYSCALL_MEMORY_READ(config, sizeof(*config)); - _SYSCALL_OBJ(config->dev, K_OBJ_DRIVER_SPI); - return _impl_spi_release(config); + _SYSCALL_OBJ(dev, K_OBJ_DRIVER_SPI); + return _impl_spi_release((struct device *)dev, config); } -#endif diff --git a/drivers/spi/spi_intel.c b/drivers/spi/spi_intel.c index 791b313dd8d8..eb868c087fff 100644 --- a/drivers/spi/spi_intel.c +++ b/drivers/spi/spi_intel.c @@ -6,6 +6,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define SYS_LOG_DOMAIN "SPI Intel" +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL +#include + #include #include @@ -19,286 +23,243 @@ #include #include -#include #include "spi_intel.h" #ifdef CONFIG_IOAPIC #include #endif -#define SYS_LOG_DOMAIN "SPI Intel" -#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL -#include - - -#define DEFINE_MM_REG_READ(__reg, __off, __sz) \ - static inline u32_t read_##__reg(u32_t addr) \ - { \ - return sys_read##__sz(addr + __off); \ - } -#define DEFINE_MM_REG_WRITE(__reg, __off, __sz) \ - static inline void write_##__reg(u32_t data, u32_t addr) \ - { \ - sys_write##__sz(data, addr + __off); \ - } - -DEFINE_MM_REG_WRITE(sscr0, INTEL_SPI_REG_SSCR0, 32) -DEFINE_MM_REG_WRITE(sscr1, INTEL_SPI_REG_SSCR1, 32) -DEFINE_MM_REG_READ(sssr, INTEL_SPI_REG_SSSR, 32) -DEFINE_MM_REG_READ(ssdr, INTEL_SPI_REG_SSDR, 32) -DEFINE_MM_REG_WRITE(ssdr, INTEL_SPI_REG_SSDR, 32) -DEFINE_MM_REG_WRITE(dds_rate, INTEL_SPI_REG_DDS_RATE, 32) - -#define DEFINE_SET_BIT_OP(__reg_bit, __reg_off, __bit) \ - static inline void set_bit_##__reg_bit(u32_t addr) \ - { \ - sys_set_bit(addr + __reg_off, __bit); \ - } - -#define DEFINE_CLEAR_BIT_OP(__reg_bit, __reg_off, __bit) \ - static inline void clear_bit_##__reg_bit(u32_t addr) \ - { \ - sys_clear_bit(addr + __reg_off, __bit); \ - } - -#define DEFINE_TEST_BIT_OP(__reg_bit, __reg_off, __bit) \ - static inline int test_bit_##__reg_bit(u32_t addr) \ - { \ - return sys_test_bit(addr + __reg_off, __bit); \ - } - -DEFINE_SET_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT) -DEFINE_CLEAR_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT) -DEFINE_TEST_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT) -DEFINE_TEST_BIT_OP(sssr_bsy, INTEL_SPI_REG_SSSR, INTEL_SPI_SSSR_BSY_BIT) -DEFINE_CLEAR_BIT_OP(sscr1_tie, INTEL_SPI_REG_SSCR1, INTEL_SPI_SSCR1_TIE_BIT) -DEFINE_TEST_BIT_OP(sscr1_tie, INTEL_SPI_REG_SSCR1, INTEL_SPI_SSCR1_TIE_BIT) -DEFINE_CLEAR_BIT_OP(sssr_ror, INTEL_SPI_REG_SSSR, INTEL_SPI_SSSR_ROR_BIT) - -#ifdef CONFIG_SPI_CS_GPIO - -#include - -static inline void _spi_config_cs(struct device *dev) -{ - const struct spi_intel_config *info = dev->config->config_info; - struct spi_intel_data *spi = dev->driver_data; - struct device *gpio; - - gpio = device_get_binding(info->cs_gpio_name); - if (!gpio) { - spi->cs_gpio_port = NULL; - return; - } - - gpio_pin_configure(gpio, info->cs_gpio_pin, GPIO_DIR_OUT); - /* Default CS line to high (idling) */ - gpio_pin_write(gpio, info->cs_gpio_pin, 1); - - spi->cs_gpio_port = gpio; -} - -static inline void _spi_control_cs(struct device *dev, int on) +static void completed(struct device *dev, u32_t error) { - const struct spi_intel_config *info = dev->config->config_info; struct spi_intel_data *spi = dev->driver_data; - if (!spi->cs_gpio_port) { - return; + if (error) { + goto out; } - gpio_pin_write(spi->cs_gpio_port, info->cs_gpio_pin, !on); -} -#else -#define _spi_control_cs(...) { ; } -#define _spi_config_cs(...) { ; } -#endif /* CONFIG_SPI_CS_GPIO */ - -static void completed(struct device *dev, u32_t error) -{ - struct spi_intel_data *spi = dev->driver_data; - - /* if received == trans_len, then transmitted == trans_len */ - if (!(spi->received == spi->trans_len) && !error) { + if (spi_context_tx_on(&spi->ctx) || + spi_context_rx_on(&spi->ctx)) { return; } - - spi->error = error; - - _spi_control_cs(dev, 0); - +out: write_sscr1(spi->sscr1, spi->regs); clear_bit_sscr0_sse(spi->regs); - k_sem_give(&spi->device_sync_sem); + spi_context_cs_control(&spi->ctx, false); + + SYS_LOG_DBG("SPI transaction completed %s error", + error ? "with" : "without"); + + spi_context_complete(&spi->ctx, error ? -EIO : 0); } static void pull_data(struct device *dev) { struct spi_intel_data *spi = dev->driver_data; - u32_t cnt = 0; - u8_t data = 0; while (read_sssr(spi->regs) & INTEL_SPI_SSSR_RNE) { - data = (u8_t) read_ssdr(spi->regs); - cnt++; - spi->received++; - - if ((spi->received - 1) < spi->r_buf_len) { - *(u8_t *)(spi->rx_buf) = data; - spi->rx_buf++; + u32_t data = read_ssdr(spi->regs); + + if (spi_context_rx_buf_on(&spi->ctx)) { + switch (spi->dfs) { + case 1: + UNALIGNED_PUT(data, (u8_t *)spi->ctx.rx_buf); + break; + case 2: + UNALIGNED_PUT(data, (u16_t *)spi->ctx.rx_buf); + break; + case 4: + UNALIGNED_PUT(data, (u32_t *)spi->ctx.rx_buf); + break; + } + + spi_context_update_rx(&spi->ctx, spi->dfs, 1); } } - - SYS_LOG_DBG("Pulled: %d (total: %d)", cnt, spi->received); } static void push_data(struct device *dev) { struct spi_intel_data *spi = dev->driver_data; - u32_t cnt = 0; - u8_t data; u32_t status; while ((status = read_sssr(spi->regs)) & INTEL_SPI_SSSR_TNF) { + u32_t data = 0; + if (status & INTEL_SPI_SSSR_RFS) { break; } - if (spi->tx_buf && (spi->transmitted < spi->t_buf_len)) { - data = *(u8_t *)(spi->tx_buf); - spi->tx_buf++; - } else if (spi->transmitted < spi->trans_len) { - data = 0; - } else { - /* Nothing to push anymore for now */ - break; + + if (spi_context_tx_buf_on(&spi->ctx)) { + switch (spi->dfs) { + case 1: + data = UNALIGNED_GET((u8_t *) + (spi->ctx.tx_buf)); + case 2: + data = UNALIGNED_GET((u16_t *) + (spi->ctx.tx_buf)); + break; + case 4: + data = UNALIGNED_GET((u32_t *) + (spi->ctx.tx_buf)); + break; + } } - cnt++; - SYS_LOG_DBG("Pushing 1 byte (total: %d)", cnt); write_ssdr(data, spi->regs); - spi->transmitted++; + spi_context_update_tx(&spi->ctx, spi->dfs, 1); } - SYS_LOG_DBG("Pushed: %d (total: %d)", cnt, spi->transmitted); - - if (spi->transmitted == spi->trans_len) { + if (!spi_context_tx_on(&spi->ctx)) { clear_bit_sscr1_tie(spi->regs); } } static int spi_intel_configure(struct device *dev, - struct spi_config *config) + const struct spi_config *config) { struct spi_intel_data *spi = dev->driver_data; - u32_t flags = config->config; - u32_t mode; - SYS_LOG_DBG("spi_intel_configure: %p (0x%x), %p", dev, spi->regs, - config); + SYS_LOG_DBG("%p (0x%x), %p", dev, spi->regs, config); - /* Check status */ - if (test_bit_sscr0_sse(spi->regs) && test_bit_sssr_bsy(spi->regs)) { - SYS_LOG_DBG("spi_intel_configure: Controller is busy"); - return -EBUSY; + if (spi_context_configured(&spi->ctx, config)) { + /* Nothing to do */ + return 0; } - /* Pre-configuring the registers to a clean state*/ - spi->sscr0 = spi->sscr1 = 0; - write_sscr0(spi->sscr0, spi->regs); - write_sscr1(spi->sscr1, spi->regs); + if (config->operation & (SPI_OP_MODE_SLAVE || SPI_TRANSFER_LSB + || SPI_LINES_DUAL || SPI_LINES_QUAD || + SPI_LINES_OCTAL)) { + return -EINVAL; + } + + /* Determine how many bytes are required per-frame */ + spi->dfs = SPI_WS_TO_DFS(SPI_WORD_SIZE_GET(config->operation)); - SYS_LOG_DBG("spi_intel_configure: WS: %d, DDS_RATE: 0x%x SCR: %d", - SPI_WORD_SIZE_GET(flags), - INTEL_SPI_DSS_RATE(config->max_sys_freq), - INTEL_SPI_SSCR0_SCR(config->max_sys_freq) >> 8); + /* Pre-configuring the registers to a clean state*/ + write_sscr0(0, spi->regs); + write_sscr1(0, spi->regs); /* Word size and clock rate */ - spi->sscr0 = INTEL_SPI_SSCR0_DSS(SPI_WORD_SIZE_GET(flags)) | - INTEL_SPI_SSCR0_SCR(config->max_sys_freq); + spi->sscr0 = INTEL_SPI_SSCR0_DSS(SPI_WORD_SIZE_GET(config->operation)) | + INTEL_SPI_SSCR0_SCR(config->operation); /* Tx/Rx thresholds * Note: Rx thresholds needs to be 1, it does not seem to be able * to trigger reliably any interrupt with another value though the * rx fifo would be full */ - spi->sscr1 |= INTEL_SPI_SSCR1_TFT(INTEL_SPI_SSCR1_TFT_DFLT) | - INTEL_SPI_SSCR1_RFT(INTEL_SPI_SSCR1_RFT_DFLT); + spi->sscr1 = INTEL_SPI_SSCR1_TFT(INTEL_SPI_SSCR1_TFT_DFLT) | + INTEL_SPI_SSCR1_RFT(INTEL_SPI_SSCR1_RFT_DFLT); /* SPI mode */ - mode = SPI_MODE(flags); - if (mode & SPI_MODE_CPOL) { + if (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) { spi->sscr1 |= INTEL_SPI_SSCR1_SPO; } - if (mode & SPI_MODE_CPHA) { + if (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) { spi->sscr1 |= INTEL_SPI_SSCR1_SPH; } - if (mode & SPI_MODE_LOOP) { + if (SPI_MODE_GET(config->operation) & SPI_MODE_LOOP) { spi->sscr1 |= INTEL_SPI_SSCR1_LBM; } /* Configuring the rate */ - write_dds_rate(INTEL_SPI_DSS_RATE(config->max_sys_freq), spi->regs); + write_dds_rate(INTEL_SPI_DSS_RATE(config->frequency), spi->regs); + + spi_context_cs_configure(&spi->ctx); return 0; } -static int spi_intel_transceive(struct device *dev, - const void *tx_buf, u32_t tx_buf_len, - void *rx_buf, u32_t rx_buf_len) +static int transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + bool asynchronous, + struct k_poll_signal *signal) { struct spi_intel_data *spi = dev->driver_data; - - SYS_LOG_DBG("spi_dw_transceive: %p, %p, %u, %p, %u", - dev, tx_buf, tx_buf_len, rx_buf, rx_buf_len); + int ret; /* Check status */ if (test_bit_sscr0_sse(spi->regs) && test_bit_sssr_bsy(spi->regs)) { - SYS_LOG_DBG("spi_intel_transceive: Controller is busy"); + SYS_LOG_DBG("Controller is busy"); return -EBUSY; } + spi_context_lock(&spi->ctx, asynchronous, signal); + + ret = spi_intel_configure(dev, config); + if (ret) { + goto out; + } + /* Set buffers info */ - spi->tx_buf = tx_buf; - spi->rx_buf = rx_buf; - spi->t_buf_len = tx_buf_len; - spi->r_buf_len = rx_buf_len; - spi->transmitted = 0; - spi->received = 0; - spi->trans_len = max(tx_buf_len, rx_buf_len); + spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, spi->dfs); - _spi_control_cs(dev, 1); + spi_context_cs_control(&spi->ctx, true); - /* Enabling the controller */ + /* Installing and Enabling the controller */ write_sscr0(spi->sscr0 | INTEL_SPI_SSCR0_SSE, spi->regs); + write_sscr1(spi->sscr1 | INTEL_SPI_SSCR1_RIE | INTEL_SPI_SSCR1_TIE, + spi->regs); + + ret = spi_context_wait_for_completion(&spi->ctx); +out: + spi_context_release(&spi->ctx, ret); - /* Installing the registers */ - write_sscr1(spi->sscr1 | INTEL_SPI_SSCR1_RIE | - INTEL_SPI_SSCR1_TIE, spi->regs); + return ret; +} + +static int spi_intel_transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + SYS_LOG_DBG("%p, %p, %p", dev, tx_bufs, rx_bufs); + + return transceive(dev, config, tx_bufs, rx_bufs, false, NULL); +} - k_sem_take(&spi->device_sync_sem, K_FOREVER); +#ifdef CONFIG_SPI_ASYNC +static int spi_intel_transceive_async(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + struct k_poll_signal *async) +{ + SYS_LOG_DBG("%p, %p, %p, %p", dev, tx_bufs, rx_bufs, async); + + return transceive(dev, config, tx_bufs, rx_bufs, true, async); +} +#endif /* CONFIG_SPI_ASYNC */ + +static int spi_intel_release(struct device *dev, + const struct spi_config *config) +{ + struct spi_intel_data *spi = dev->driver_data; - if (spi->error) { - spi->error = 0; - return -EIO; + if (test_bit_sscr0_sse(spi->regs) && test_bit_sssr_bsy(spi->regs)) { + SYS_LOG_DBG("Controller is busy"); + return -EBUSY; } + spi_context_unlock_unconditionally(&spi->ctx); + return 0; } -void spi_intel_isr(void *arg) +void spi_intel_isr(struct device *dev) { - struct device *dev = arg; struct spi_intel_data *spi = dev->driver_data; u32_t error = 0; u32_t status; - SYS_LOG_DBG("spi_intel_isr: %p", dev); + SYS_LOG_DBG("%p", dev); status = read_sssr(spi->regs); - if (status & INTEL_SPI_SSSR_ROR) { /* Unrecoverable error, ack it */ clear_bit_sssr_ror(spi->regs); @@ -320,9 +281,11 @@ void spi_intel_isr(void *arg) } static const struct spi_driver_api intel_spi_api = { - .configure = spi_intel_configure, - .slave_select = NULL, .transceive = spi_intel_transceive, +#ifdef CONFIG_SPI_ASYNC + .transceive_async = spi_intel_transceive_async, +#endif /* CONFIG_SPI_ASYNC */ + .release = spi_intel_release, }; #ifdef CONFIG_PCI @@ -354,9 +317,9 @@ static inline int spi_intel_setup(struct device *dev) static void spi_intel_set_power_state(struct device *dev, u32_t power_state) { - struct spi_intel_data *context = dev->driver_data; + struct spi_intel_data *spi = dev->driver_data; - context->device_power_state = power_state; + spi->device_power_state = power_state; } #else #define spi_intel_set_power_state(...) @@ -365,7 +328,6 @@ static void spi_intel_set_power_state(struct device *dev, u32_t power_state) int spi_intel_init(struct device *dev) { const struct spi_intel_config *info = dev->config->config_info; - struct spi_intel_data *spi = dev->driver_data; if (!spi_intel_setup(dev)) { return -EPERM; @@ -373,18 +335,12 @@ int spi_intel_init(struct device *dev) info->config_func(); - _spi_config_cs(dev); - - k_sem_init(&spi->device_sync_sem, 0, UINT_MAX); - spi_intel_set_power_state(dev, DEVICE_PM_ACTIVE_STATE); irq_enable(info->irq); SYS_LOG_DBG("SPI Intel Driver initialized on device: %p", dev); - dev->driver_api = &intel_spi_api; - return 0; } @@ -392,9 +348,9 @@ int spi_intel_init(struct device *dev) static u32_t spi_intel_get_power_state(struct device *dev) { - struct spi_intel_data *context = dev->driver_data; + struct spi_intel_data *spi = dev->driver_data; - return context->device_power_state; + return spi->device_power_state; } static int spi_intel_suspend(struct device *dev) @@ -402,7 +358,7 @@ static int spi_intel_suspend(struct device *dev) const struct spi_intel_config *info = dev->config->config_info; struct spi_intel_data *spi = dev->driver_data; - SYS_LOG_DBG("spi_intel_suspend: %p", dev); + SYS_LOG_DBG("%p", dev); clear_bit_sscr0_sse(spi->regs); irq_disable(info->irq); @@ -417,7 +373,7 @@ static int spi_intel_resume_from_suspend(struct device *dev) const struct spi_intel_config *info = dev->config->config_info; struct spi_intel_data *spi = dev->driver_data; - SYS_LOG_DBG("spi_intel_resume: %p", dev); + SYS_LOG_DBG("%p", dev); set_bit_sscr0_sse(spi->regs); irq_enable(info->irq); @@ -457,6 +413,8 @@ static int spi_intel_device_ctrl(struct device *dev, u32_t ctrl_command, void spi_config_0_irq(void); struct spi_intel_data spi_intel_data_port_0 = { + SPI_CONTEXT_INIT_LOCK(spi_intel_data_port_0, ctx), + SPI_CONTEXT_INIT_SYNC(spi_intel_data_port_0, ctx), .regs = SPI_INTEL_PORT_0_REGS, #if CONFIG_PCI .pci_dev.class_type = SPI_INTEL_CLASS, @@ -470,17 +428,13 @@ struct spi_intel_data spi_intel_data_port_0 = { const struct spi_intel_config spi_intel_config_0 = { .irq = SPI_INTEL_PORT_0_IRQ, -#ifdef CONFIG_SPI_CS_GPIO - .cs_gpio_name = CONFIG_SPI_0_CS_GPIO_PORT, - .cs_gpio_pin = CONFIG_SPI_0_CS_GPIO_PIN, -#endif .config_func = spi_config_0_irq }; -/* SPI may use GPIO pin for CS, thus it needs to be initialized after GPIO */ DEVICE_DEFINE(spi_intel_port_0, CONFIG_SPI_0_NAME, spi_intel_init, spi_intel_device_ctrl, &spi_intel_data_port_0, - &spi_intel_config_0, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, NULL); + &spi_intel_config_0, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, + &intel_spi_api); void spi_config_0_irq(void) { @@ -495,6 +449,8 @@ void spi_config_0_irq(void) void spi_config_1_irq(void); struct spi_intel_data spi_intel_data_port_1 = { + SPI_CONTEXT_INIT_LOCK(spi_intel_data_port_1, ctx), + SPI_CONTEXT_INIT_SYNC(spi_intel_data_port_1, ctx), .regs = SPI_INTEL_PORT_1_REGS, #if CONFIG_PCI .pci_dev.class_type = SPI_INTEL_CLASS, @@ -508,17 +464,13 @@ struct spi_intel_data spi_intel_data_port_1 = { const struct spi_intel_config spi_intel_config_1 = { .irq = SPI_INTEL_PORT_1_IRQ, -#ifdef CONFIG_SPI_CS_GPIO - .cs_gpio_name = CONFIG_SPI_1_CS_GPIO_PORT, - .cs_gpio_pin = CONFIG_SPI_1_CS_GPIO_PIN, -#endif .config_func = spi_config_1_irq }; -/* SPI may use GPIO pin for CS, thus it needs to be initialized after GPIO */ DEVICE_DEFINE(spi_intel_port_1, CONFIG_SPI_1_NAME, spi_intel_init, spi_intel_device_ctrl, &spi_intel_data_port_1, - &spi_intel_config_1, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, NULL); + &spi_intel_config_1, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, + &intel_spi_api); void spi_config_1_irq(void) { diff --git a/drivers/spi/spi_intel.h b/drivers/spi/spi_intel.h index a11d5d304fa2..b10679ebdb9f 100644 --- a/drivers/spi/spi_intel.h +++ b/drivers/spi/spi_intel.h @@ -6,13 +6,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __SPI_INTEL_PRIV_H__ -#define __SPI_INTEL_PRIV_H__ +#ifndef __SPI_INTEL_H__ +#define __SPI_INTEL_H__ + +#include "spi_intel_regs.h" +#include "spi_context.h" #ifdef CONFIG_PCI #include #include #endif /* CONFIG_PCI */ + #ifdef __cplusplus extern "C" { #endif @@ -22,98 +26,77 @@ typedef void (*spi_intel_config_t)(void); struct spi_intel_config { u32_t irq; spi_intel_config_t config_func; -#ifdef CONFIG_SPI_CS_GPIO - char *cs_gpio_name; - u32_t cs_gpio_pin; -#endif /* CONFIG_SPI_CS_GPIO */ }; struct spi_intel_data { + struct spi_context ctx; u32_t regs; #ifdef CONFIG_PCI struct pci_dev_info pci_dev; #endif /* CONFIG_PCI */ - struct k_sem device_sync_sem; - u8_t error; - u8_t padding[3]; -#ifdef CONFIG_SPI_CS_GPIO - struct device *cs_gpio_port; -#endif /* CONFIG_SPI_CS_GPIO */ u32_t sscr0; u32_t sscr1; - const u8_t *tx_buf; - u8_t *rx_buf; - u32_t t_buf_len; - u32_t r_buf_len; - u32_t transmitted; - u32_t received; - u32_t trans_len; #ifdef CONFIG_DEVICE_POWER_MANAGEMENT u32_t device_power_state; #endif + u8_t dfs; }; -/* Registers */ -#define INTEL_SPI_REG_SSCR0 (0x00) -#define INTEL_SPI_REG_SSCR1 (0x04) -#define INTEL_SPI_REG_SSSR (0x08) -#define INTEL_SPI_REG_SSDR (0x10) -#define INTEL_SPI_REG_DDS_RATE (0x28) - -#define INTEL_SPI_CLK_DIV_MASK (0x000000ff) -#define INTEL_SPI_DDS_RATE_MASK (0xffffff00) - -/* SSCR0 settings */ -#define INTEL_SPI_SSCR0_DSS(__bpw) ((__bpw) - 1) -#define INTEL_SPI_SSCR0_SSE (0x1 << 7) -#define INTEL_SPI_SSCR0_SSE_BIT (7) -#define INTEL_SPI_SSCR0_SCR(__msf) \ - ((__msf & INTEL_SPI_CLK_DIV_MASK) << 8) - -/* SSCR1 settings */ -#define INTEL_SPI_SSCR1_TIE_BIT (1) - -#define INTEL_SPI_SSCR1_RIE (0x1) -#define INTEL_SPI_SSCR1_TIE (0x1 << 1) -#define INTEL_SPI_SSCR1_LBM (0x1 << 2) -#define INTEL_SPI_SSCR1_SPO (0x1 << 3) -#define INTEL_SPI_SSCR1_SPH (0x1 << 4) -#define INTEL_SPI_SSCR1_TFT_MASK (0x1f << 6) -#define INTEL_SPI_SSCR1_TFT(__tft) \ - (((__tft) - 1) << 6) -#define INTEL_SPI_SSCR1_RFT_MASK (0x1f << 11) -#define INTEL_SPI_SSCR1_RFT(__rft) \ - (((__rft) - 1) << 11) -#define INTEL_SPI_SSCR1_EFWR (0x1 << 16) -#define INTEL_SPI_SSCR1_STRF (0x1 << 17) - -#define INTEL_SPI_SSCR1_TFT_DFLT (8) -#define INTEL_SPI_SSCR1_RFT_DFLT (1) - -/* SSSR settings */ -#define INTEL_SPI_SSSR_TNF (0x4) -#define INTEL_SPI_SSSR_RNE (0x8) -#define INTEL_SPI_SSSR_TFS (0x20) -#define INTEL_SPI_SSSR_RFS (0x40) -#define INTEL_SPI_SSSR_ROR (0x80) -#define INTEL_SPI_SSSR_TFL_MASK (0x1f << 8) -#define INTEL_SPI_SSSR_TFL_EMPTY (0x00) -#define INTEL_SPI_SSSR_RFL_MASK (0x1f << 13) -#define INTEL_SPI_SSSR_RFL_EMPTY (0x1f) - -#define INTEL_SPI_SSSR_TFL(__status) \ - ((__status & INTEL_SPI_SSSR_TFL_MASK) >> 8) -#define INTEL_SPI_SSSR_RFL(__status) \ - ((__status & INTEL_SPI_SSSR_RFL_MASK) >> 13) - -#define INTEL_SPI_SSSR_BSY_BIT (4) -#define INTEL_SPI_SSSR_ROR_BIT (7) - -/* DSS_RATE settings */ -#define INTEL_SPI_DSS_RATE(__msf) \ - ((__msf & (INTEL_SPI_DDS_RATE_MASK)) >> 8) +#define DEFINE_MM_REG_READ(__reg, __off, __sz) \ + static inline u32_t read_##__reg(u32_t addr) \ + { \ + return sys_read##__sz(addr + __off); \ + } +#define DEFINE_MM_REG_WRITE(__reg, __off, __sz) \ + static inline void write_##__reg(u32_t data, u32_t addr) \ + { \ + sys_write##__sz(data, addr + __off); \ + } + +DEFINE_MM_REG_WRITE(sscr0, INTEL_SPI_REG_SSCR0, 32) +DEFINE_MM_REG_WRITE(sscr1, INTEL_SPI_REG_SSCR1, 32) +DEFINE_MM_REG_READ(sssr, INTEL_SPI_REG_SSSR, 32) +DEFINE_MM_REG_READ(ssdr, INTEL_SPI_REG_SSDR, 32) +DEFINE_MM_REG_WRITE(ssdr, INTEL_SPI_REG_SSDR, 32) +DEFINE_MM_REG_WRITE(dds_rate, INTEL_SPI_REG_DDS_RATE, 32) + +#define DEFINE_SET_BIT_OP(__reg_bit, __reg_off, __bit) \ + static inline void set_bit_##__reg_bit(u32_t addr) \ + { \ + sys_set_bit(addr + __reg_off, __bit); \ + } + +#define DEFINE_CLEAR_BIT_OP(__reg_bit, __reg_off, __bit) \ + static inline void clear_bit_##__reg_bit(u32_t addr) \ + { \ + sys_clear_bit(addr + __reg_off, __bit); \ + } + +#define DEFINE_TEST_BIT_OP(__reg_bit, __reg_off, __bit) \ + static inline int test_bit_##__reg_bit(u32_t addr) \ + { \ + return sys_test_bit(addr + __reg_off, __bit); \ + } + +DEFINE_SET_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT) +DEFINE_CLEAR_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT) +DEFINE_TEST_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT) +DEFINE_TEST_BIT_OP(sssr_bsy, INTEL_SPI_REG_SSSR, INTEL_SPI_SSSR_BSY_BIT) +DEFINE_CLEAR_BIT_OP(sscr1_tie, INTEL_SPI_REG_SSCR1, INTEL_SPI_SSCR1_TIE_BIT) +DEFINE_TEST_BIT_OP(sscr1_tie, INTEL_SPI_REG_SSCR1, INTEL_SPI_SSCR1_TIE_BIT) +DEFINE_CLEAR_BIT_OP(sssr_ror, INTEL_SPI_REG_SSSR, INTEL_SPI_SSSR_ROR_BIT) + +/* 0x38 represents the bits 8, 16 and 32. Knowing that 24 is bits 8 and 16 + * These are the bits were when you divide by 8, you keep the result as it is. + * For all the other ones, 4 to 7, 9 to 15, etc... you need a +1, + * since on such division it takes only the result above 0 + */ +#define SPI_WS_TO_DFS(__bpw) (((__bpw) & ~0x38) ? \ + (((__bpw) / 8) + 1) : \ + ((__bpw) / 8)) + #ifdef __cplusplus } #endif -#endif /* __SPI_INTEL_PRIV_H__ */ +#endif /* __SPI_INTEL_H__ */ diff --git a/drivers/spi/spi_intel_regs.h b/drivers/spi/spi_intel_regs.h new file mode 100644 index 000000000000..5c07f64b34cc --- /dev/null +++ b/drivers/spi/spi_intel_regs.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __SPI_INTEL_REGS_H__ +#define __SPI_INTEL_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Intel's SPI driver registers definition */ + +/* Registers */ +#define INTEL_SPI_REG_SSCR0 (0x00) +#define INTEL_SPI_REG_SSCR1 (0x04) +#define INTEL_SPI_REG_SSSR (0x08) +#define INTEL_SPI_REG_SSDR (0x10) +#define INTEL_SPI_REG_DDS_RATE (0x28) + +#define INTEL_SPI_CLK_DIV_MASK (0x000000ff) +#define INTEL_SPI_DDS_RATE_MASK (0xffffff00) + +/* SSCR0 settings */ +#define INTEL_SPI_SSCR0_DSS(__bpw) ((__bpw) - 1) +#define INTEL_SPI_SSCR0_SSE (0x1 << 7) +#define INTEL_SPI_SSCR0_SSE_BIT (7) +#define INTEL_SPI_SSCR0_SCR(__msf) \ + ((__msf & INTEL_SPI_CLK_DIV_MASK) << 8) + +/* SSCR1 settings */ +#define INTEL_SPI_SSCR1_TIE_BIT (1) + +#define INTEL_SPI_SSCR1_RIE (0x1) +#define INTEL_SPI_SSCR1_TIE (0x1 << 1) +#define INTEL_SPI_SSCR1_LBM (0x1 << 2) +#define INTEL_SPI_SSCR1_SPO (0x1 << 3) +#define INTEL_SPI_SSCR1_SPH (0x1 << 4) +#define INTEL_SPI_SSCR1_TFT_MASK (0x1f << 6) +#define INTEL_SPI_SSCR1_TFT(__tft) \ + (((__tft) - 1) << 6) +#define INTEL_SPI_SSCR1_RFT_MASK (0x1f << 11) +#define INTEL_SPI_SSCR1_RFT(__rft) \ + (((__rft) - 1) << 11) +#define INTEL_SPI_SSCR1_EFWR (0x1 << 16) +#define INTEL_SPI_SSCR1_STRF (0x1 << 17) + +#define INTEL_SPI_SSCR1_TFT_DFLT (8) +#define INTEL_SPI_SSCR1_RFT_DFLT (1) + +/* SSSR settings */ +#define INTEL_SPI_SSSR_TNF (0x4) +#define INTEL_SPI_SSSR_RNE (0x8) +#define INTEL_SPI_SSSR_TFS (0x20) +#define INTEL_SPI_SSSR_RFS (0x40) +#define INTEL_SPI_SSSR_ROR (0x80) +#define INTEL_SPI_SSSR_TFL_MASK (0x1f << 8) +#define INTEL_SPI_SSSR_TFL_EMPTY (0x00) +#define INTEL_SPI_SSSR_RFL_MASK (0x1f << 13) +#define INTEL_SPI_SSSR_RFL_EMPTY (0x1f) + +#define INTEL_SPI_SSSR_TFL(__status) \ + ((__status & INTEL_SPI_SSSR_TFL_MASK) >> 8) +#define INTEL_SPI_SSSR_RFL(__status) \ + ((__status & INTEL_SPI_SSSR_RFL_MASK) >> 13) + +#define INTEL_SPI_SSSR_BSY_BIT (4) +#define INTEL_SPI_SSSR_ROR_BIT (7) + +/* DSS_RATE settings */ +#define INTEL_SPI_DSS_RATE(__msf) \ + ((__msf & (INTEL_SPI_DDS_RATE_MASK)) >> 8) + +#ifdef __cplusplus +} +#endif + +#endif /* __SPI_INTEL_REGS_H__ */ diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 29080d1802b8..a8e7d00ddd4a 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -19,11 +19,11 @@ #include "spi_ll_stm32.h" -#define CONFIG_CFG(cfg) \ -((const struct spi_stm32_config * const)(cfg)->dev->config->config_info) +#define DEV_CFG(dev) \ +(const struct spi_stm32_config * const)(dev->config->config_info) -#define CONFIG_DATA(cfg) \ -((struct spi_stm32_data * const)(cfg)->dev->driver_data) +#define DEV_DATA(dev) \ +(struct spi_stm32_data * const)(dev->driver_data) /* * Check for SPI_SR_FRE to determine support for TI mode frame format @@ -222,10 +222,11 @@ static void spi_stm32_isr(void *arg) } #endif -static int spi_stm32_configure(struct spi_config *config) +static int spi_stm32_configure(struct device *dev, + const struct spi_config *config) { - const struct spi_stm32_config *cfg = CONFIG_CFG(config); - struct spi_stm32_data *data = CONFIG_DATA(config); + const struct spi_stm32_config *cfg = DEV_CFG(dev); + struct spi_stm32_data *data = DEV_DATA(dev); const u32_t scaler[] = { LL_SPI_BAUDRATEPRESCALER_DIV2, LL_SPI_BAUDRATEPRESCALER_DIV4, @@ -340,26 +341,28 @@ static int spi_stm32_configure(struct spi_config *config) return 0; } -static int spi_stm32_release(struct spi_config *config) +static int spi_stm32_release(struct device *dev, + const struct spi_config *config) { - struct spi_stm32_data *data = CONFIG_DATA(config); + struct spi_stm32_data *data = DEV_DATA(dev); spi_context_unlock_unconditionally(&data->ctx); return 0; } -static int transceive(struct spi_config *config, - const struct spi_buf *tx_bufs, u32_t tx_count, - struct spi_buf *rx_bufs, u32_t rx_count, +static int transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, bool asynchronous, struct k_poll_signal *signal) { - const struct spi_stm32_config *cfg = CONFIG_CFG(config); - struct spi_stm32_data *data = CONFIG_DATA(config); + const struct spi_stm32_config *cfg = DEV_CFG(dev); + struct spi_stm32_data *data = DEV_DATA(dev); SPI_TypeDef *spi = cfg->spi; int ret; - if (!tx_count && !rx_count) { + if (!tx_bufs && !rx_bufs) { return 0; } @@ -371,14 +374,13 @@ static int transceive(struct spi_config *config, spi_context_lock(&data->ctx, asynchronous, signal); - ret = spi_stm32_configure(config); + ret = spi_stm32_configure(dev, config); if (ret) { return ret; } /* Set buffers info */ - spi_context_buffers_setup(&data->ctx, tx_bufs, tx_count, - rx_bufs, rx_count, 1); + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); #if defined(CONFIG_SPI_STM32_HAS_FIFO) /* Flush RX buffer */ @@ -419,30 +421,28 @@ static int transceive(struct spi_config *config, return ret ? -EIO : 0; } -static int spi_stm32_transceive(struct spi_config *config, - const struct spi_buf *tx_bufs, u32_t tx_count, - struct spi_buf *rx_bufs, u32_t rx_count) +static int spi_stm32_transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) { - return transceive(config, tx_bufs, tx_count, - rx_bufs, rx_count, false, NULL); + return transceive(dev, config, tx_bufs, rx_bufs, false, NULL); } -#ifdef CONFIG_POLL -static int spi_stm32_transceive_async(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count, +#ifdef CONFIG_SPI_ASYNC +static int spi_stm32_transceive_async(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, struct k_poll_signal *async) { - return transceive(config, tx_bufs, tx_count, - rx_bufs, rx_count, true, async); + return transceive(dev, config, tx_bufs, rx_bufs, true, async); } -#endif /* CONFIG_POLL */ +#endif /* CONFIG_SPI_ASYNC */ static const struct spi_driver_api api_funcs = { .transceive = spi_stm32_transceive, -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC .transceive_async = spi_stm32_transceive_async, #endif .release = spi_stm32_release, diff --git a/drivers/spi/spi_mcux_dspi.c b/drivers/spi/spi_mcux_dspi.c index 4b1dc5591f28..793752e63c73 100644 --- a/drivers/spi/spi_mcux_dspi.c +++ b/drivers/spi/spi_mcux_dspi.c @@ -14,43 +14,127 @@ #define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL #include +#include "spi_context.h" + struct spi_mcux_config { SPI_Type *base; clock_name_t clock_source; void (*irq_config_func)(struct device *dev); - struct spi_config default_cfg; }; struct spi_mcux_data { dspi_master_handle_t handle; - struct k_sem sync; - status_t callback_status; - u32_t slave; + struct spi_context ctx; + size_t transfer_len; }; +static void spi_mcux_transfer_next_packet(struct device *dev) +{ + const struct spi_mcux_config *config = dev->config->config_info; + struct spi_mcux_data *data = dev->driver_data; + SPI_Type *base = config->base; + struct spi_context *ctx = &data->ctx; + dspi_transfer_t transfer; + status_t status; + + if ((ctx->tx_len == 0) && (ctx->rx_len == 0)) { + /* nothing left to rx or tx, we're done! */ + spi_context_cs_control(&data->ctx, false); + spi_context_complete(&data->ctx, 0); + return; + } + + transfer.configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcsContinuous | + (ctx->config->slave << DSPI_MASTER_PCS_SHIFT); + + if (ctx->tx_len == 0) { + /* rx only, nothing to tx */ + transfer.txData = NULL; + transfer.rxData = ctx->rx_buf; + transfer.dataSize = ctx->rx_len; + } else if (ctx->rx_len == 0) { + /* tx only, nothing to rx */ + transfer.txData = (u8_t *) ctx->tx_buf; + transfer.rxData = NULL; + transfer.dataSize = ctx->tx_len; + } else if (ctx->tx_len == ctx->rx_len) { + /* rx and tx are the same length */ + transfer.txData = (u8_t *) ctx->tx_buf; + transfer.rxData = ctx->rx_buf; + transfer.dataSize = ctx->tx_len; + } else if (ctx->tx_len > ctx->rx_len) { + /* Break up the tx into multiple transfers so we don't have to + * rx into a longer intermediate buffer. Leave chip select + * active between transfers. + */ + transfer.txData = (u8_t *) ctx->tx_buf; + transfer.rxData = ctx->rx_buf; + transfer.dataSize = ctx->rx_len; + transfer.configFlags |= kDSPI_MasterActiveAfterTransfer; + } else { + /* Break up the rx into multiple transfers so we don't have to + * tx from a longer intermediate buffer. Leave chip select + * active between transfers. + */ + transfer.txData = (u8_t *) ctx->tx_buf; + transfer.rxData = ctx->rx_buf; + transfer.dataSize = ctx->tx_len; + transfer.configFlags |= kDSPI_MasterActiveAfterTransfer; + } + + if (!(ctx->tx_count <= 1 && ctx->rx_count <= 1)) { + transfer.configFlags |= kDSPI_MasterActiveAfterTransfer; + } + + data->transfer_len = transfer.dataSize; + + status = DSPI_MasterTransferNonBlocking(base, &data->handle, &transfer); + if (status != kStatus_Success) { + SYS_LOG_ERR("Transfer could not start"); + } +} + +static void spi_mcux_isr(void *arg) +{ + struct device *dev = (struct device *)arg; + const struct spi_mcux_config *config = dev->config->config_info; + struct spi_mcux_data *data = dev->driver_data; + SPI_Type *base = config->base; + + DSPI_MasterTransferHandleIRQ(base, &data->handle); +} + static void spi_mcux_master_transfer_callback(SPI_Type *base, dspi_master_handle_t *handle, status_t status, void *userData) { struct device *dev = userData; struct spi_mcux_data *data = dev->driver_data; - data->callback_status = status; - k_sem_give(&data->sync); + spi_context_update_tx(&data->ctx, 1, data->transfer_len); + spi_context_update_rx(&data->ctx, 1, data->transfer_len); + + spi_mcux_transfer_next_packet(dev); } -static int spi_mcux_configure(struct device *dev, struct spi_config *spi_config) +static int spi_mcux_configure(struct device *dev, + const struct spi_config *spi_cfg) { const struct spi_mcux_config *config = dev->config->config_info; struct spi_mcux_data *data = dev->driver_data; SPI_Type *base = config->base; dspi_master_config_t master_config; - u32_t flags = spi_config->config; u32_t clock_freq; u32_t word_size; DSPI_MasterGetDefaultConfig(&master_config); - word_size = SPI_WORD_SIZE_GET(flags); + if (spi_cfg->slave > FSL_FEATURE_DSPI_CHIP_SELECT_COUNT) { + SYS_LOG_ERR("Slave %d is greater than %d", + spi_cfg->slave, FSL_FEATURE_DSPI_CHIP_SELECT_COUNT); + return -EINVAL; + } + + word_size = SPI_WORD_SIZE_GET(spi_cfg->operation); if (word_size > FSL_FEATURE_DSPI_MAX_DATA_WIDTH) { SYS_LOG_ERR("Word size %d is greater than %d", word_size, FSL_FEATURE_DSPI_MAX_DATA_WIDTH); @@ -59,182 +143,117 @@ static int spi_mcux_configure(struct device *dev, struct spi_config *spi_config) master_config.ctarConfig.bitsPerFrame = word_size; - master_config.ctarConfig.cpol = (flags & SPI_MODE_CPOL) - ? kDSPI_ClockPolarityActiveLow - : kDSPI_ClockPolarityActiveHigh; - - master_config.ctarConfig.cpha = (flags & SPI_MODE_CPHA) - ? kDSPI_ClockPhaseSecondEdge - : kDSPI_ClockPhaseFirstEdge; + master_config.ctarConfig.cpol = + (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL) + ? kDSPI_ClockPolarityActiveLow + : kDSPI_ClockPolarityActiveHigh; - master_config.ctarConfig.direction = (flags & SPI_TRANSFER_LSB) - ? kDSPI_LsbFirst - : kDSPI_MsbFirst; + master_config.ctarConfig.cpha = + (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA) + ? kDSPI_ClockPhaseSecondEdge + : kDSPI_ClockPhaseFirstEdge; - master_config.ctarConfig.baudRate = spi_config->max_sys_freq; + master_config.ctarConfig.direction = + (SPI_MODE_GET(spi_cfg->operation) & SPI_TRANSFER_LSB) + ? kDSPI_LsbFirst + : kDSPI_MsbFirst; - SYS_LOG_DBG("word size = %d, baud rate = %d", - word_size, spi_config->max_sys_freq); + master_config.ctarConfig.baudRate = spi_cfg->frequency; clock_freq = CLOCK_GetFreq(config->clock_source); if (!clock_freq) { SYS_LOG_ERR("Got frequency of 0"); return -EINVAL; } + DSPI_MasterInit(base, &master_config, clock_freq); DSPI_MasterTransferCreateHandle(base, &data->handle, - spi_mcux_master_transfer_callback, dev); - - return 0; -} - -static int spi_mcux_slave_select(struct device *dev, u32_t slave) -{ - struct spi_mcux_data *data = dev->driver_data; + spi_mcux_master_transfer_callback, dev); - if (slave > FSL_FEATURE_DSPI_CHIP_SELECT_COUNT) { - SYS_LOG_ERR("Slave %d is greater than %d", - slave, FSL_FEATURE_DSPI_CHIP_SELECT_COUNT); - return -EINVAL; - } - - data->slave = slave; + data->ctx.config = spi_cfg; + spi_context_cs_configure(&data->ctx); return 0; } -static int spi_mcux_transceive(struct device *dev, - const void *tx_buf, u32_t tx_buf_len, - void *rx_buf, u32_t rx_buf_len) +static int transceive(struct device *dev, + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + bool asynchronous, + struct k_poll_signal *signal) { - const struct spi_mcux_config *config = dev->config->config_info; struct spi_mcux_data *data = dev->driver_data; - SPI_Type *base = config->base; - u8_t buf[CONFIG_SPI_MCUX_BUF_SIZE]; - dspi_transfer_t transfer; - status_t status; + int ret; - /* Initialize the transfer descriptor */ + spi_context_lock(&data->ctx, asynchronous, signal); - SYS_LOG_DBG("tx_buf_len = %d, rx_buf_len = %d, local buf len = %d", - tx_buf_len, rx_buf_len, sizeof(buf)); - - if (tx_buf_len == rx_buf_len) { - /* The tx and rx buffers are the same length, so we can use - * them directly. - */ - transfer.txData = (u8_t *)tx_buf; - transfer.rxData = rx_buf; - transfer.dataSize = rx_buf_len; - SYS_LOG_DBG("Using tx and rx buffers directly"); - } else if (tx_buf_len == 0) { - /* The tx buffer length is zero, so this is a one-way spi read - * operation. - */ - transfer.txData = NULL; - transfer.rxData = rx_buf; - transfer.dataSize = rx_buf_len; - SYS_LOG_DBG("Using rx buffer directly, tx buffer is null"); - } else if (rx_buf_len == 0) { - /* The rx buffer length is zero, so this is a one-way spi write - * operation. - */ - transfer.txData = (u8_t *)tx_buf; - transfer.rxData = NULL; - transfer.dataSize = tx_buf_len; - SYS_LOG_DBG("Using tx buffer directly, rx buffer is null"); - } else if ((tx_buf_len < rx_buf_len) && (rx_buf_len <= sizeof(buf))) { - /* The tx buffer is shorter than the rx buffer, so copy the tx - * buffer to the longer local buffer. - */ - transfer.txData = buf; - transfer.rxData = rx_buf; - transfer.dataSize = rx_buf_len; - memcpy(buf, tx_buf, tx_buf_len); - memset(&buf[tx_buf_len], CONFIG_SPI_MCUX_DUMMY_CHAR, - rx_buf_len - tx_buf_len); - SYS_LOG_DBG("Using local buffer for tx"); - } else if ((rx_buf_len < tx_buf_len) && (tx_buf_len <= sizeof(buf))) { - /* The rx buffer is shorter than the tx buffer, so use the - * longer local buffer for rx. After the transfer is complete, - * we'll need to copy the local buffer back to the rx buffer. - */ - transfer.txData = (u8_t *)tx_buf; - transfer.rxData = buf; - transfer.dataSize = tx_buf_len; - SYS_LOG_DBG("Using local buffer for rx"); - } else { - SYS_LOG_ERR("Local buffer too small for transfer"); - return -EINVAL; + ret = spi_mcux_configure(dev, spi_cfg); + if (ret) { + goto out; } - transfer.configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcsContinuous | - (data->slave << DSPI_MASTER_PCS_SHIFT); + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); - /* Start the transfer */ - status = DSPI_MasterTransferNonBlocking(base, &data->handle, &transfer); + spi_context_cs_control(&data->ctx, true); - /* Return an error if the transfer didn't start successfully e.g., if - * the bus was busy - */ - if (status != kStatus_Success) { - SYS_LOG_ERR("Transfer could not start"); - return -EIO; - } + spi_mcux_transfer_next_packet(dev); - /* Wait for the transfer to complete */ - k_sem_take(&data->sync, K_FOREVER); + ret = spi_context_wait_for_completion(&data->ctx); +out: + spi_context_release(&data->ctx, ret); - /* Return an error if the transfer didn't complete successfully. */ - if (data->callback_status != kStatus_Success) { - SYS_LOG_ERR("Transfer could not complete"); - return -EIO; - } + return ret; +} - /* Copy the local buffer back to the rx buffer. */ - if ((rx_buf_len < tx_buf_len) && (tx_buf_len <= sizeof(buf))) { - memcpy(rx_buf, buf, rx_buf_len); - } +static int spi_mcux_transceive(struct device *dev, + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL); +} - return 0; +#ifdef CONFIG_SPI_ASYNC +static int spi_mcux_transceive_async(struct device *dev, + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + struct k_poll_signal *async) +{ + return transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, async); } +#endif /* CONFIG_SPI_ASYNC */ -static void spi_mcux_isr(void *arg) +static int spi_mcux_release(struct device *dev, + const struct spi_config *spi_cfg) { - struct device *dev = (struct device *)arg; - const struct spi_mcux_config *config = dev->config->config_info; struct spi_mcux_data *data = dev->driver_data; - SPI_Type *base = config->base; - DSPI_MasterTransferHandleIRQ(base, &data->handle); + spi_context_unlock_unconditionally(&data->ctx); + + return 0; } static int spi_mcux_init(struct device *dev) { const struct spi_mcux_config *config = dev->config->config_info; struct spi_mcux_data *data = dev->driver_data; - struct spi_config *spi_config; - int error; - - k_sem_init(&data->sync, 0, UINT_MAX); - - spi_config = (struct spi_config *)&config->default_cfg; - error = spi_mcux_configure(dev, spi_config); - if (error) { - SYS_LOG_ERR("Could not configure"); - return error; - } config->irq_config_func(dev); + spi_context_unlock_unconditionally(&data->ctx); + return 0; } static const struct spi_driver_api spi_mcux_driver_api = { - .configure = spi_mcux_configure, - .slave_select = spi_mcux_slave_select, .transceive = spi_mcux_transceive, +#ifdef CONFIG_SPI_ASYNC + .transceive_async = spi_mcux_transceive_async, +#endif + .release = spi_mcux_release, }; #ifdef CONFIG_SPI_0 @@ -244,13 +263,12 @@ static const struct spi_mcux_config spi_mcux_config_0 = { .base = DSPI0, .clock_source = DSPI0_CLK_SRC, .irq_config_func = spi_mcux_config_func_0, - .default_cfg = { - .config = CONFIG_SPI_0_DEFAULT_CFG, - .max_sys_freq = CONFIG_SPI_0_DEFAULT_BAUD_RATE, - } }; -static struct spi_mcux_data spi_mcux_data_0; +static struct spi_mcux_data spi_mcux_data_0 = { + SPI_CONTEXT_INIT_LOCK(spi_mcux_data_0, ctx), + SPI_CONTEXT_INIT_SYNC(spi_mcux_data_0, ctx), +}; DEVICE_AND_API_INIT(spi_mcux_0, CONFIG_SPI_0_NAME, &spi_mcux_init, &spi_mcux_data_0, &spi_mcux_config_0, @@ -273,13 +291,12 @@ static const struct spi_mcux_config spi_mcux_config_1 = { .base = DSPI1, .clock_source = DSPI1_CLK_SRC, .irq_config_func = spi_mcux_config_func_1, - .default_cfg = { - .config = CONFIG_SPI_1_DEFAULT_CFG, - .max_sys_freq = CONFIG_SPI_1_DEFAULT_BAUD_RATE, - } }; -static struct spi_mcux_data spi_mcux_data_1; +static struct spi_mcux_data spi_mcux_data_1 = { + SPI_CONTEXT_INIT_LOCK(spi_mcux_data_1, ctx), + SPI_CONTEXT_INIT_SYNC(spi_mcux_data_1, ctx), +}; DEVICE_AND_API_INIT(spi_mcux_1, CONFIG_SPI_1_NAME, &spi_mcux_init, &spi_mcux_data_1, &spi_mcux_config_1, @@ -302,13 +319,12 @@ static const struct spi_mcux_config spi_mcux_config_2 = { .base = DSPI2, .clock_source = DSPI2_CLK_SRC, .irq_config_func = spi_mcux_config_func_2, - .default_cfg = { - .config = CONFIG_SPI_2_DEFAULT_CFG, - .max_sys_freq = CONFIG_SPI_2_DEFAULT_BAUD_RATE, - } }; -static struct spi_mcux_data spi_mcux_data_2; +static struct spi_mcux_data spi_mcux_data_2 = { + SPI_CONTEXT_INIT_LOCK(spi_mcux_data_2, ctx), + SPI_CONTEXT_INIT_SYNC(spi_mcux_data_2, ctx), +}; DEVICE_AND_API_INIT(spi_mcux_2, CONFIG_SPI_2_NAME, &spi_mcux_init, &spi_mcux_data_2, &spi_mcux_config_2, diff --git a/drivers/spi/spi_nrfx_spi.c b/drivers/spi/spi_nrfx_spi.c new file mode 100644 index 000000000000..86ad7dbf3f87 --- /dev/null +++ b/drivers/spi/spi_nrfx_spi.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define SYS_LOG_DOMAIN "spi_nrfx_spi" +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL +#include + +#include "spi_context.h" + +struct spi_nrfx_data { + struct spi_context ctx; + size_t chunk_len; + bool busy; +}; + +struct spi_nrfx_config { + nrfx_spi_t spi; +}; + +static inline struct spi_nrfx_data *get_dev_data(struct device *dev) +{ + return dev->driver_data; +} + +static inline const struct spi_nrfx_config *get_dev_config(struct device *dev) +{ + return dev->config->config_info; +} + +static inline nrf_spi_frequency_t get_nrf_spi_frequency(u32_t frequency) +{ + /* Get the highest supported frequency not exceeding the requested one. + */ + if (frequency < 250000) { + return NRF_SPI_FREQ_125K; + } else if (frequency < 500000) { + return NRF_SPI_FREQ_250K; + } else if (frequency < 1000000) { + return NRF_SPI_FREQ_500K; + } else if (frequency < 2000000) { + return NRF_SPI_FREQ_1M; + } else if (frequency < 4000000) { + return NRF_SPI_FREQ_2M; + } else if (frequency < 8000000) { + return NRF_SPI_FREQ_4M; + } else { + return NRF_SPI_FREQ_8M; + } +} + +static inline nrf_spi_mode_t get_nrf_spi_mode(u16_t operation) +{ + if (SPI_MODE_GET(operation) & SPI_MODE_CPOL) { + if (SPI_MODE_GET(operation) & SPI_MODE_CPHA) { + return NRF_SPI_MODE_3; + } else { + return NRF_SPI_MODE_2; + } + } else { + if (SPI_MODE_GET(operation) & SPI_MODE_CPHA) { + return NRF_SPI_MODE_1; + } else { + return NRF_SPI_MODE_0; + } + } +} + +static inline nrf_spi_bit_order_t get_nrf_spi_bit_order(u16_t operation) +{ + if (operation & SPI_TRANSFER_LSB) { + return NRF_SPI_BIT_ORDER_LSB_FIRST; + } else { + return NRF_SPI_BIT_ORDER_MSB_FIRST; + } +} + +static int configure(struct device *dev, + const struct spi_config *spi_cfg) +{ + struct spi_context *ctx = &get_dev_data(dev)->ctx; + const nrfx_spi_t *spi = &get_dev_config(dev)->spi; + + if (spi_context_configured(ctx, spi_cfg)) { + /* Already configured. No need to do it again. */ + return 0; + } + + if (spi_cfg->operation & SPI_OP_MODE_SLAVE) { + SYS_LOG_ERR("Slave mode is not supported for %s", + dev->config->name); + return -EINVAL; + } + + if (spi_cfg->operation & SPI_MODE_LOOP) { + SYS_LOG_ERR("Loopback mode is not supported"); + return -EINVAL; + } + + if ((spi_cfg->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) { + SYS_LOG_ERR("Only single line mode is supported"); + return -EINVAL; + } + + if (SPI_WORD_SIZE_GET(spi_cfg->operation) != 8) { + SYS_LOG_ERR("Word sizes other than 8 bits" + " are not supported"); + return -EINVAL; + } + + if (spi_cfg->frequency < 125000) { + SYS_LOG_ERR("Frequencies lower than 125 kHz are not supported"); + return -EINVAL; + } + + ctx->config = spi_cfg; + spi_context_cs_configure(ctx); + + nrf_spi_configure(spi->p_reg, + get_nrf_spi_mode(spi_cfg->operation), + get_nrf_spi_bit_order(spi_cfg->operation)); + nrf_spi_frequency_set(spi->p_reg, + get_nrf_spi_frequency(spi_cfg->frequency)); + + return 0; +} + +static void transfer_next_chunk(struct device *dev) +{ + struct spi_nrfx_data *dev_data = get_dev_data(dev); + struct spi_context *ctx = &dev_data->ctx; + int error = 0; + + size_t chunk_len = spi_context_longest_current_buf(ctx); + + if (chunk_len > 0) { + const nrfx_spi_xfer_desc_t xfer_desc = { + .p_tx_buffer = ctx->tx_buf, + .tx_length = spi_context_tx_buf_on(ctx) ? chunk_len : 0, + .p_rx_buffer = ctx->rx_buf, + .rx_length = spi_context_rx_buf_on(ctx) ? chunk_len : 0, + }; + dev_data->chunk_len = chunk_len; + nrfx_err_t result = nrfx_spi_xfer(&get_dev_config(dev)->spi, + &xfer_desc, 0); + + if (result == NRFX_SUCCESS) { + return; + } + + error = -EIO; + } + + spi_context_cs_control(ctx, false); + + SYS_LOG_DBG("Transaction finished with status %d", error); + + spi_context_complete(ctx, error); + dev_data->busy = false; +} + +static int transceive(struct device *dev, + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + struct spi_nrfx_data *dev_data = get_dev_data(dev); + int error; + + error = configure(dev, spi_cfg); + if (error == 0) { + dev_data->busy = true; + + spi_context_buffers_setup(&dev_data->ctx, tx_bufs, rx_bufs, 1); + spi_context_cs_control(&dev_data->ctx, true); + + transfer_next_chunk(dev); + + error = spi_context_wait_for_completion(&dev_data->ctx); + } + + spi_context_release(&dev_data->ctx, error); + + return error; +} + +static int spi_nrfx_transceive(struct device *dev, + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + spi_context_lock(&get_dev_data(dev)->ctx, false, NULL); + return transceive(dev, spi_cfg, tx_bufs, rx_bufs); +} + +#ifdef CONFIG_SPI_ASYNC +static int spi_nrfx_transceive_async(struct device *dev, + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + struct k_poll_signal *async) +{ + spi_context_lock(&get_dev_data(dev)->ctx, true, async); + return transceive(dev, spi_cfg, tx_bufs, rx_bufs); +} +#endif /* CONFIG_SPI_ASYNC */ + +static int spi_nrfx_release(struct device *dev, + const struct spi_config *spi_cfg) +{ + struct spi_nrfx_data *dev_data = get_dev_data(dev); + + if (!spi_context_configured(&dev_data->ctx, spi_cfg)) { + return -EINVAL; + } + + if (dev_data->busy) { + return -EBUSY; + } + + spi_context_unlock_unconditionally(&dev_data->ctx); + + return 0; +} + +static const struct spi_driver_api spi_nrfx_driver_api = { + .transceive = spi_nrfx_transceive, +#ifdef CONFIG_SPI_ASYNC + .transceive_async = spi_nrfx_transceive_async, +#endif + .release = spi_nrfx_release, +}; + + +static void event_handler(const nrfx_spi_evt_t *p_event, void *p_context) +{ + struct device *dev = p_context; + struct spi_nrfx_data *dev_data = get_dev_data(dev); + + if (p_event->type == NRFX_SPI_EVENT_DONE) { + spi_context_update_tx(&dev_data->ctx, 1, dev_data->chunk_len); + spi_context_update_rx(&dev_data->ctx, 1, dev_data->chunk_len); + + transfer_next_chunk(dev); + } +} + +static int init_spi(struct device *dev, const nrfx_spi_config_t *config) +{ + /* This sets only default values of frequency, mode and bit order. + * The proper ones are set in configure() when a transfer is started. + */ + nrfx_err_t result = nrfx_spi_init(&get_dev_config(dev)->spi, + config, + event_handler, + dev); + if (result != NRFX_SUCCESS) { + SYS_LOG_ERR("Failed to initialize device: %s", + dev->config->name); + return -EBUSY; + } + + spi_context_unlock_unconditionally(&get_dev_data(dev)->ctx); + + return 0; +} + +static void spi_isr(void *irq_handler) +{ + ((nrfx_irq_handler_t)irq_handler)(); +} + +/* In Nordic SoCs the IRQ number assigned to a peripheral is equal to the ID + * of the block of 0x1000 bytes in the peripheral address space assigned to + * this peripheral. See the chapter "Peripheral interface" (sections "Peripheral + * ID" and "Interrupts") in the product specification of a given SoC. + */ +#define NRF_SPI_IRQ_NUMBER(idx) (uint8_t)((uint32_t)NRF_SPI##idx >> 12u) + +#define SPI_NRFX_SPI_DEVICE(idx) \ + static int spi_##idx##_init(struct device *dev) \ + { \ + IRQ_CONNECT(NRF_SPI_IRQ_NUMBER(idx), \ + CONFIG_SPI_##idx##_IRQ_PRI, \ + spi_isr, nrfx_spi_##idx##_irq_handler, 0); \ + const nrfx_spi_config_t config = { \ + .sck_pin = CONFIG_SPI_##idx##_NRF_SCK_PIN, \ + .mosi_pin = CONFIG_SPI_##idx##_NRF_MOSI_PIN, \ + .miso_pin = CONFIG_SPI_##idx##_NRF_MISO_PIN, \ + .ss_pin = NRFX_SPI_PIN_NOT_USED, \ + .orc = CONFIG_SPI_##idx##_NRF_ORC, \ + .frequency = NRF_SPI_FREQ_4M, \ + .mode = NRF_SPI_MODE_0, \ + .bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST, \ + }; \ + return init_spi(dev, &config); \ + } \ + static struct spi_nrfx_data spi_##idx##_data = { \ + SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx), \ + SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \ + .busy = false, \ + }; \ + static const struct spi_nrfx_config spi_##idx##_config = { \ + .spi = NRFX_SPI_INSTANCE(idx), \ + }; \ + DEVICE_AND_API_INIT(spi_##idx, CONFIG_SPI_##idx##_NAME, \ + spi_##idx##_init, \ + &spi_##idx##_data, \ + &spi_##idx##_config, \ + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ + &spi_nrfx_driver_api) + +#ifdef CONFIG_SPI_0_NRF_SPI +SPI_NRFX_SPI_DEVICE(0); +#endif + +#ifdef CONFIG_SPI_1_NRF_SPI +SPI_NRFX_SPI_DEVICE(1); +#endif + +#ifdef CONFIG_SPI_2_NRF_SPI +SPI_NRFX_SPI_DEVICE(2); +#endif diff --git a/drivers/spi/spi_qmsi.c b/drivers/spi/spi_qmsi.c deleted file mode 100644 index 123f1e21b239..000000000000 --- a/drivers/spi/spi_qmsi.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "qm_spi.h" -#include "clk.h" -#include "qm_isr.h" -#include "soc.h" - -struct pending_transfer { - struct device *dev; - qm_spi_async_transfer_t xfer; -}; - -static struct pending_transfer pending_transfers[QM_SPI_NUM]; - -struct spi_qmsi_config { - qm_spi_t spi; - char *cs_port; - u32_t cs_pin; -}; - -struct spi_qmsi_runtime { - struct device *gpio_cs; - struct k_sem device_sync_sem; - qm_spi_config_t cfg; - int rc; - bool loopback; - struct k_sem sem; -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT - u32_t device_power_state; - qm_spi_context_t spi_ctx; -#endif -}; - -static inline qm_spi_bmode_t config_to_bmode(u8_t mode) -{ - switch (mode) { - case SPI_MODE_CPHA: - return QM_SPI_BMODE_1; - case SPI_MODE_CPOL: - return QM_SPI_BMODE_2; - case SPI_MODE_CPOL | SPI_MODE_CPHA: - return QM_SPI_BMODE_3; - default: - return QM_SPI_BMODE_0; - } -} - -static void spi_control_cs(struct device *dev, bool active) -{ - struct spi_qmsi_runtime *context = dev->driver_data; - const struct spi_qmsi_config *config = dev->config->config_info; - struct device *gpio = context->gpio_cs; - - if (!gpio) { - return; - } - - gpio_pin_write(gpio, config->cs_pin, !active); -} - -static int spi_qmsi_configure(struct device *dev, - struct spi_config *config) -{ - struct spi_qmsi_runtime *context = dev->driver_data; - qm_spi_config_t *cfg = &context->cfg; - - cfg->frame_size = SPI_WORD_SIZE_GET(config->config) - 1; - cfg->bus_mode = config_to_bmode(SPI_MODE(config->config)); - /* As loopback is implemented inside the controller, - * the bus mode doesn't matter. - */ - context->loopback = SPI_MODE(config->config) & SPI_MODE_LOOP; - cfg->clk_divider = config->max_sys_freq; - - /* Will set the configuration before the transfer starts */ - return 0; -} - -static void transfer_complete(void *data, int error, qm_spi_status_t status, - u16_t len) -{ - const struct spi_qmsi_config *spi_config = - ((struct device *)data)->config->config_info; - qm_spi_t spi = spi_config->spi; - struct pending_transfer *pending = &pending_transfers[spi]; - struct device *dev = pending->dev; - struct spi_qmsi_runtime *context; - - if (!dev) { - return; - } - - context = dev->driver_data; - - spi_control_cs(dev, false); - - pending->dev = NULL; - context->rc = error; - k_sem_give(&context->device_sync_sem); -} - -static int spi_qmsi_slave_select(struct device *dev, u32_t slave) -{ - const struct spi_qmsi_config *spi_config = dev->config->config_info; - qm_spi_t spi = spi_config->spi; - - return qm_spi_slave_select(spi, 1 << (slave - 1)) ? -EIO : 0; -} - -static inline u8_t frame_size_to_dfs(qm_spi_frame_size_t frame_size) -{ - if (frame_size <= QM_SPI_FRAME_SIZE_8_BIT) { - return 1; - } - - if (frame_size <= QM_SPI_FRAME_SIZE_16_BIT) { - return 2; - } - - if (frame_size <= QM_SPI_FRAME_SIZE_32_BIT) { - return 4; - } - - /* This should never happen, it will crash later on. */ - return 0; -} - -static int spi_qmsi_transceive(struct device *dev, - const void *tx_buf, u32_t tx_buf_len, - void *rx_buf, u32_t rx_buf_len) -{ - const struct spi_qmsi_config *spi_config = dev->config->config_info; - qm_spi_t spi = spi_config->spi; - struct spi_qmsi_runtime *context = dev->driver_data; - qm_spi_config_t *cfg = &context->cfg; - u8_t dfs = frame_size_to_dfs(cfg->frame_size); - qm_spi_async_transfer_t *xfer; - int rc; - - k_sem_take(&context->sem, K_FOREVER); - if (pending_transfers[spi].dev) { - k_sem_give(&context->sem); - return -EBUSY; - } - pending_transfers[spi].dev = dev; - k_sem_give(&context->sem); - - device_busy_set(dev); - - xfer = &pending_transfers[spi].xfer; - - xfer->rx = rx_buf; - xfer->rx_len = rx_buf_len / dfs; - /* This cast is necessary to drop the "const" modifier, since QMSI xfer - * does not take a const pointer. - */ - xfer->tx = (u8_t *)tx_buf; - xfer->tx_len = tx_buf_len / dfs; - xfer->callback_data = dev; - xfer->callback = transfer_complete; - - if (tx_buf_len == 0) { - cfg->transfer_mode = QM_SPI_TMOD_RX; - } else if (rx_buf_len == 0) { - cfg->transfer_mode = QM_SPI_TMOD_TX; - } else { - /* FIXME: QMSI expects rx_buf_len and tx_buf_len to - * have the same size. - */ - cfg->transfer_mode = QM_SPI_TMOD_TX_RX; - } - - if (context->loopback) { - QM_SPI[spi]->ctrlr0 |= BIT(11); - } - - rc = qm_spi_set_config(spi, cfg); - if (rc != 0) { - device_busy_clear(dev); - return -EINVAL; - } - - spi_control_cs(dev, true); - - rc = qm_spi_irq_transfer(spi, xfer); - if (rc != 0) { - spi_control_cs(dev, false); - device_busy_clear(dev); - return -EIO; - } - k_sem_take(&context->device_sync_sem, K_FOREVER); - - device_busy_clear(dev); - - return context->rc ? -EIO : 0; -} - -static const struct spi_driver_api spi_qmsi_api = { - .configure = spi_qmsi_configure, - .slave_select = spi_qmsi_slave_select, - .transceive = spi_qmsi_transceive, -}; - -static struct device *gpio_cs_init(const struct spi_qmsi_config *config) -{ - struct device *gpio; - - if (!config->cs_port) { - return NULL; - } - - gpio = device_get_binding(config->cs_port); - if (!gpio) { - return NULL; - } - - if (gpio_pin_configure(gpio, config->cs_pin, GPIO_DIR_OUT) != 0) { - return NULL; - } - - if (gpio_pin_write(gpio, config->cs_pin, 1) != 0) { - return NULL; - } - - return gpio; -} -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT -static void spi_master_set_power_state(struct device *dev, u32_t power_state) -{ - struct spi_qmsi_runtime *context = dev->driver_data; - - context->device_power_state = power_state; -} - -static u32_t spi_master_get_power_state(struct device *dev) -{ - struct spi_qmsi_runtime *context = dev->driver_data; - - return context->device_power_state; -} -#else -#define spi_master_set_power_state(...) -#endif - -static int spi_qmsi_init(struct device *dev) -{ - const struct spi_qmsi_config *spi_config = dev->config->config_info; - struct spi_qmsi_runtime *context = dev->driver_data; - - switch (spi_config->spi) { - case QM_SPI_MST_0: - IRQ_CONNECT(IRQ_GET_NUMBER(QM_IRQ_SPI_MASTER_0_INT), - CONFIG_SPI_0_IRQ_PRI, qm_spi_master_0_isr, - 0, IOAPIC_LEVEL | IOAPIC_HIGH); - irq_enable(IRQ_GET_NUMBER(QM_IRQ_SPI_MASTER_0_INT)); - clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_SPI_M0_REGISTER); - QM_IR_UNMASK_INTERRUPTS( - QM_INTERRUPT_ROUTER->spi_master_0_int_mask); - break; - -#ifdef CONFIG_SPI_1 - case QM_SPI_MST_1: - IRQ_CONNECT(IRQ_GET_NUMBER(QM_IRQ_SPI_MASTER_1_INT), - CONFIG_SPI_1_IRQ_PRI, qm_spi_master_1_isr, - 0, IOAPIC_LEVEL | IOAPIC_HIGH); - irq_enable(IRQ_GET_NUMBER(QM_IRQ_SPI_MASTER_1_INT)); - clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_SPI_M1_REGISTER); - QM_IR_UNMASK_INTERRUPTS( - QM_INTERRUPT_ROUTER->spi_master_1_int_mask); - break; -#endif /* CONFIG_SPI_1 */ - - default: - return -EIO; - } - - context->gpio_cs = gpio_cs_init(spi_config); - - k_sem_init(&context->device_sync_sem, 0, UINT_MAX); - k_sem_init(&context->sem, 1, UINT_MAX); - - spi_master_set_power_state(dev, DEVICE_PM_ACTIVE_STATE); - - dev->driver_api = &spi_qmsi_api; - return 0; -} - -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT -static int spi_master_suspend_device(struct device *dev) -{ - if (device_busy_check(dev)) { - return -EBUSY; - } - - const struct spi_qmsi_config *config = dev->config->config_info; - struct spi_qmsi_runtime *drv_data = dev->driver_data; - - qm_spi_save_context(config->spi, &drv_data->spi_ctx); - - spi_master_set_power_state(dev, DEVICE_PM_SUSPEND_STATE); - - return 0; -} - -static int spi_master_resume_device_from_suspend(struct device *dev) -{ - const struct spi_qmsi_config *config = dev->config->config_info; - struct spi_qmsi_runtime *drv_data = dev->driver_data; - - qm_spi_restore_context(config->spi, &drv_data->spi_ctx); - - spi_master_set_power_state(dev, DEVICE_PM_ACTIVE_STATE); - - return 0; -} - -/* -* Implements the driver control management functionality -* the *context may include IN data or/and OUT data -*/ -static int spi_master_qmsi_device_ctrl(struct device *port, - u32_t ctrl_command, void *context) -{ - if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { - if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return spi_master_suspend_device(port); - } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return spi_master_resume_device_from_suspend(port); - } - } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { - *((u32_t *)context) = spi_master_get_power_state(port); - return 0; - } - return 0; -} -#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ - -#ifdef CONFIG_SPI_0 -static const struct spi_qmsi_config spi_qmsi_mst_0_config = { - .spi = QM_SPI_MST_0, -#ifdef CONFIG_SPI_CS_GPIO - .cs_port = CONFIG_SPI_0_CS_GPIO_PORT, - .cs_pin = CONFIG_SPI_0_CS_GPIO_PIN, -#endif -}; - -static struct spi_qmsi_runtime spi_qmsi_mst_0_runtime; - -DEVICE_DEFINE(spi_master_0, CONFIG_SPI_0_NAME, spi_qmsi_init, - spi_master_qmsi_device_ctrl, &spi_qmsi_mst_0_runtime, - &spi_qmsi_mst_0_config, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, - NULL); -#endif /* CONFIG_SPI_0 */ - -#ifdef CONFIG_SPI_1 -static const struct spi_qmsi_config spi_qmsi_mst_1_config = { - .spi = QM_SPI_MST_1, -#ifdef CONFIG_SPI_CS_GPIO - .cs_port = CONFIG_SPI_1_CS_GPIO_PORT, - .cs_pin = CONFIG_SPI_1_CS_GPIO_PIN, -#endif -}; - -static struct spi_qmsi_runtime spi_qmsi_mst_1_runtime; - -DEVICE_DEFINE(spi_master_1, CONFIG_SPI_1_NAME, spi_qmsi_init, - spi_master_qmsi_device_ctrl, &spi_qmsi_mst_1_runtime, - &spi_qmsi_mst_1_config, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, - NULL); -#endif /* CONFIG_SPI_1 */ diff --git a/drivers/spi/spi_qmsi_ss.c b/drivers/spi/spi_qmsi_ss.c deleted file mode 100644 index 4e6445598f52..000000000000 --- a/drivers/spi/spi_qmsi_ss.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#include -#include -#include - -#include "qm_ss_spi.h" -#include "qm_ss_isr.h" -#include "ss_clk.h" - -struct ss_pending_transfer { - struct device *dev; - qm_ss_spi_async_transfer_t xfer; -}; - -static struct ss_pending_transfer pending_transfers[2]; - -struct ss_spi_qmsi_config { - qm_ss_spi_t spi; -#ifdef CONFIG_SPI_SS_CS_GPIO - char *cs_port; - u32_t cs_pin; -#endif -}; - -struct ss_spi_qmsi_runtime { -#ifdef CONFIG_SPI_SS_CS_GPIO - struct device *gpio_cs; -#endif - struct k_sem device_sync_sem; - struct k_sem sem; - qm_ss_spi_config_t cfg; - int rc; - bool loopback; -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT - u32_t device_power_state; - qm_ss_spi_context_t spi_ctx; -#endif -}; - -static inline qm_ss_spi_bmode_t config_to_bmode(u8_t mode) -{ - switch (mode) { - case SPI_MODE_CPHA: - return QM_SS_SPI_BMODE_1; - case SPI_MODE_CPOL: - return QM_SS_SPI_BMODE_2; - case SPI_MODE_CPOL | SPI_MODE_CPHA: - return QM_SS_SPI_BMODE_3; - default: - return QM_SS_SPI_BMODE_0; - } -} - -#ifdef CONFIG_SPI_SS_CS_GPIO -static void spi_control_cs(struct device *dev, bool active) -{ - struct ss_spi_qmsi_runtime *context = dev->driver_data; - const struct ss_spi_qmsi_config *config = dev->config->config_info; - struct device *gpio = context->gpio_cs; - - if (!gpio) - return; - - gpio_pin_write(gpio, config->cs_pin, !active); -} -#endif - -static int ss_spi_qmsi_configure(struct device *dev, - struct spi_config *config) -{ - struct ss_spi_qmsi_runtime *context = dev->driver_data; - qm_ss_spi_config_t *cfg = &context->cfg; - - cfg->frame_size = SPI_WORD_SIZE_GET(config->config) - 1; - cfg->bus_mode = config_to_bmode(SPI_MODE(config->config)); - /* As loopback is implemented inside the controller, - * the bus mode doesn't matter. - */ - context->loopback = SPI_MODE(config->config) & SPI_MODE_LOOP; - cfg->clk_divider = config->max_sys_freq; - - /* Will set the configuration before the transfer starts */ - return 0; -} - -static void spi_qmsi_callback(void *data, int error, qm_ss_spi_status_t status, - u16_t len) -{ - const struct ss_spi_qmsi_config *spi_config = - ((struct device *)data)->config->config_info; - qm_ss_spi_t spi_id = spi_config->spi; - struct ss_pending_transfer *pending = &pending_transfers[spi_id]; - struct device *dev = pending->dev; - struct ss_spi_qmsi_runtime *context; - - if (!dev) - return; - - context = dev->driver_data; - -#ifdef CONFIG_SPI_SS_CS_GPIO - spi_control_cs(dev, false); -#endif - - pending->dev = NULL; - context->rc = error; - k_sem_give(&context->device_sync_sem); -} - -static int ss_spi_qmsi_slave_select(struct device *dev, u32_t slave) -{ - const struct ss_spi_qmsi_config *spi_config = dev->config->config_info; - qm_ss_spi_t spi_id = spi_config->spi; - - return qm_ss_spi_slave_select(spi_id, 1 << (slave - 1)) ? -EIO : 0; -} - -static inline u8_t frame_size_to_dfs(qm_ss_spi_frame_size_t frame_size) -{ - if (frame_size <= QM_SS_SPI_FRAME_SIZE_8_BIT) { - return 1; - } - - if (frame_size <= QM_SS_SPI_FRAME_SIZE_16_BIT) { - return 2; - } - - /* This should never happen, it will crash later on. */ - return 0; -} - -static int ss_spi_qmsi_transceive(struct device *dev, - const void *tx_buf, u32_t tx_buf_len, - void *rx_buf, u32_t rx_buf_len) -{ - const struct ss_spi_qmsi_config *spi_config = dev->config->config_info; - qm_ss_spi_t spi_id = spi_config->spi; - struct ss_spi_qmsi_runtime *context = dev->driver_data; - qm_ss_spi_config_t *cfg = &context->cfg; - u8_t dfs = frame_size_to_dfs(cfg->frame_size); - qm_ss_spi_async_transfer_t *xfer; - int rc; - - k_sem_take(&context->sem, K_FOREVER); - if (pending_transfers[spi_id].dev) { - k_sem_give(&context->sem); - return -EBUSY; - } - pending_transfers[spi_id].dev = dev; - k_sem_give(&context->sem); - - device_busy_set(dev); - - xfer = &pending_transfers[spi_id].xfer; - - xfer->rx = rx_buf; - xfer->rx_len = rx_buf_len / dfs; - xfer->tx = (u8_t *)tx_buf; - xfer->tx_len = tx_buf_len / dfs; - xfer->callback_data = dev; - xfer->callback = spi_qmsi_callback; - - if (tx_buf_len == 0) { - cfg->transfer_mode = QM_SS_SPI_TMOD_RX; - } else if (rx_buf_len == 0) { - cfg->transfer_mode = QM_SS_SPI_TMOD_TX; - } else { - cfg->transfer_mode = QM_SS_SPI_TMOD_TX_RX; - } - - if (context->loopback) { - u32_t ctrl; - - if (spi_id == 0) { - ctrl = __builtin_arc_lr(QM_SS_SPI_0_BASE + - QM_SS_SPI_CTRL); - ctrl |= BIT(11); - __builtin_arc_sr(ctrl, QM_SS_SPI_0_BASE + - QM_SS_SPI_CTRL); - } else { - ctrl = __builtin_arc_lr(QM_SS_SPI_1_BASE + - QM_SS_SPI_CTRL); - ctrl |= BIT(11); - __builtin_arc_sr(ctrl, QM_SS_SPI_1_BASE + - QM_SS_SPI_CTRL); - } - } - - rc = qm_ss_spi_set_config(spi_id, cfg); - if (rc != 0) { - device_busy_clear(dev); - return -EINVAL; - } - -#ifdef CONFIG_SPI_SS_CS_GPIO - spi_control_cs(dev, true); -#endif - - rc = qm_ss_spi_irq_transfer(spi_id, xfer); - if (rc != 0) { -#ifdef CONFIG_SPI_SS_CS_GPIO - spi_control_cs(dev, false); -#endif - device_busy_clear(dev); - return -EIO; - } - - k_sem_take(&context->device_sync_sem, K_FOREVER); - - device_busy_clear(dev); - return context->rc ? -EIO : 0; -} - -static const struct spi_driver_api ss_spi_qmsi_api = { - .configure = ss_spi_qmsi_configure, - .slave_select = ss_spi_qmsi_slave_select, - .transceive = ss_spi_qmsi_transceive, -}; - -#ifdef CONFIG_SPI_SS_CS_GPIO -static struct device *gpio_cs_init(const struct ss_spi_qmsi_config *config) -{ - struct device *gpio; - - if (!config->cs_port) - return NULL; - - gpio = device_get_binding(config->cs_port); - if (!gpio) - return NULL; - - gpio_pin_configure(gpio, config->cs_pin, GPIO_DIR_OUT); - gpio_pin_write(gpio, config->cs_pin, 1); - - return gpio; -} -#endif - -static int ss_spi_qmsi_init(struct device *dev); - - -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT -static void ss_spi_master_set_power_state(struct device *dev, - u32_t power_state) -{ - struct ss_spi_qmsi_runtime *context = dev->driver_data; - - context->device_power_state = power_state; -} - -static u32_t ss_spi_master_get_power_state(struct device *dev) -{ - struct ss_spi_qmsi_runtime *context = dev->driver_data; - - return context->device_power_state; -} - -static int ss_spi_master_suspend_device(struct device *dev) -{ - if (device_busy_check(dev)) { - return -EBUSY; - } - - const struct ss_spi_qmsi_config *config = dev->config->config_info; - struct ss_spi_qmsi_runtime *drv_data = dev->driver_data; - - qm_ss_spi_save_context(config->spi, &drv_data->spi_ctx); - - ss_spi_master_set_power_state(dev, DEVICE_PM_SUSPEND_STATE); - - return 0; -} - -static int ss_spi_master_resume_device_from_suspend(struct device *dev) -{ - const struct ss_spi_qmsi_config *config = dev->config->config_info; - struct ss_spi_qmsi_runtime *drv_data = dev->driver_data; - - qm_ss_spi_restore_context(config->spi, &drv_data->spi_ctx); - - ss_spi_master_set_power_state(dev, DEVICE_PM_ACTIVE_STATE); - - return 0; -} - -/* -* Implements the driver control management functionality -* the *context may include IN data or/and OUT data -*/ -static int ss_spi_master_qmsi_device_ctrl(struct device *port, - u32_t ctrl_command, void *context) -{ - if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { - if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return ss_spi_master_suspend_device(port); - } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return ss_spi_master_resume_device_from_suspend(port); - } - } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { - *((u32_t *)context) = ss_spi_master_get_power_state(port); - } - return 0; -} -#else -#define ss_spi_master_set_power_state(...) -#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ - -#ifdef CONFIG_SPI_SS_0 -static const struct ss_spi_qmsi_config spi_qmsi_mst_0_config = { - .spi = QM_SS_SPI_0, -#ifdef CONFIG_SPI_SS_CS_GPIO - .cs_port = CONFIG_SPI_SS_0_CS_GPIO_PORT, - .cs_pin = CONFIG_SPI_SS_0_CS_GPIO_PIN, -#endif -}; - -static struct ss_spi_qmsi_runtime spi_qmsi_mst_0_runtime; - -DEVICE_DEFINE(ss_spi_master_0, CONFIG_SPI_SS_0_NAME, ss_spi_qmsi_init, - ss_spi_master_qmsi_device_ctrl, &spi_qmsi_mst_0_runtime, - &spi_qmsi_mst_0_config, POST_KERNEL, CONFIG_SPI_SS_INIT_PRIORITY, - NULL); -#endif /* CONFIG_SPI_SS_0 */ - -#ifdef CONFIG_SPI_SS_1 -static const struct ss_spi_qmsi_config spi_qmsi_mst_1_config = { - .spi = QM_SS_SPI_1, -#ifdef CONFIG_SPI_SS_CS_GPIO - .cs_port = CONFIG_SPI_SS_1_CS_GPIO_PORT, - .cs_pin = CONFIG_SPI_SS_1_CS_GPIO_PIN, -#endif -}; - -static struct ss_spi_qmsi_runtime spi_qmsi_mst_1_runtime; - -DEVICE_DEFINE(ss_spi_master_1, CONFIG_SPI_SS_1_NAME, ss_spi_qmsi_init, - ss_spi_master_qmsi_device_ctrl, &spi_qmsi_mst_1_runtime, - &spi_qmsi_mst_1_config, POST_KERNEL, CONFIG_SPI_SS_INIT_PRIORITY, - NULL); -#endif /* CONFIG_SPI_SS_1 */ - -static void ss_spi_err_isr(void *arg) -{ - struct device *dev = arg; - const struct ss_spi_qmsi_config *spi_config = dev->config->config_info; - - if (spi_config->spi == QM_SS_SPI_0) { - qm_ss_spi_0_error_isr(NULL); - } else { - qm_ss_spi_1_error_isr(NULL); - } -} - -static void ss_spi_rx_isr(void *arg) -{ - struct device *dev = arg; - const struct ss_spi_qmsi_config *spi_config = dev->config->config_info; - - if (spi_config->spi == QM_SS_SPI_0) { - qm_ss_spi_0_rx_avail_isr(NULL); - } else { - qm_ss_spi_1_rx_avail_isr(NULL); - } -} - -static void ss_spi_tx_isr(void *arg) -{ - struct device *dev = arg; - const struct ss_spi_qmsi_config *spi_config = dev->config->config_info; - - if (spi_config->spi == QM_SS_SPI_0) { - qm_ss_spi_0_tx_req_isr(NULL); - } else { - qm_ss_spi_1_tx_req_isr(NULL); - } -} - -static int ss_spi_qmsi_init(struct device *dev) -{ - const struct ss_spi_qmsi_config *spi_config = dev->config->config_info; - struct ss_spi_qmsi_runtime *context = dev->driver_data; - u32_t *scss_intmask = NULL; - - switch (spi_config->spi) { -#ifdef CONFIG_SPI_SS_0 - case QM_SS_SPI_0: - IRQ_CONNECT(IRQ_SPI0_ERR_INT, CONFIG_SPI_SS_0_IRQ_PRI, - ss_spi_err_isr, DEVICE_GET(ss_spi_master_0), 0); - irq_enable(IRQ_SPI0_ERR_INT); - - IRQ_CONNECT(IRQ_SPI0_RX_AVAIL, CONFIG_SPI_SS_0_IRQ_PRI, - ss_spi_rx_isr, DEVICE_GET(ss_spi_master_0), 0); - irq_enable(IRQ_SPI0_RX_AVAIL); - - IRQ_CONNECT(IRQ_SPI0_TX_REQ, CONFIG_SPI_SS_0_IRQ_PRI, - ss_spi_tx_isr, DEVICE_GET(ss_spi_master_0), 0); - irq_enable(IRQ_SPI0_TX_REQ); - - ss_clk_spi_enable(0); - - /* Route SPI interrupts to Sensor Subsystem */ - scss_intmask = (u32_t *)&QM_INTERRUPT_ROUTER->ss_spi_0_int; - *scss_intmask &= ~BIT(8); - scss_intmask++; - *scss_intmask &= ~BIT(8); - scss_intmask++; - *scss_intmask &= ~BIT(8); - break; -#endif /* CONFIG_SPI_SS_0 */ - -#ifdef CONFIG_SPI_SS_1 - case QM_SS_SPI_1: - IRQ_CONNECT(IRQ_SPI1_ERR_INT, CONFIG_SPI_SS_1_IRQ_PRI, - ss_spi_err_isr, DEVICE_GET(ss_spi_master_1), 0); - irq_enable(IRQ_SPI1_ERR_INT); - - IRQ_CONNECT(IRQ_SPI1_RX_AVAIL, CONFIG_SPI_SS_1_IRQ_PRI, - ss_spi_rx_isr, DEVICE_GET(ss_spi_master_1), 0); - irq_enable(IRQ_SPI1_RX_AVAIL); - - IRQ_CONNECT(IRQ_SPI1_TX_REQ, CONFIG_SPI_SS_1_IRQ_PRI, - ss_spi_tx_isr, DEVICE_GET(ss_spi_master_1), 0); - irq_enable(IRQ_SPI1_TX_REQ); - - ss_clk_spi_enable(1); - - /* Route SPI interrupts to Sensor Subsystem */ - scss_intmask = (u32_t *)&QM_INTERRUPT_ROUTER->ss_spi_1_int; - *scss_intmask &= ~BIT(8); - scss_intmask++; - *scss_intmask &= ~BIT(8); - scss_intmask++; - *scss_intmask &= ~BIT(8); - break; -#endif /* CONFIG_SPI_SS_1 */ - - default: - return -EIO; - } - -#ifdef CONFIG_SPI_SS_CS_GPIO - context->gpio_cs = gpio_cs_init(spi_config); -#endif - k_sem_init(&context->device_sync_sem, 0, UINT_MAX); - k_sem_init(&context->sem, 1, UINT_MAX); - - ss_spi_master_set_power_state(dev, DEVICE_PM_ACTIVE_STATE); - - dev->driver_api = &ss_spi_qmsi_api; - - return 0; -} diff --git a/drivers/spi/spi_sam0.c b/drivers/spi/spi_sam0.c index 5e58e5efe18f..dacda0b6e6b7 100644 --- a/drivers/spi/spi_sam0.c +++ b/drivers/spi/spi_sam0.c @@ -14,10 +14,6 @@ #include #include -#if defined(CONFIG_SPI_LEGACY_API) -#error "This driver does not support the SPI legacy API." -#endif - /* Device constant configuration parameters */ struct spi_sam0_config { SercomSpi *regs; @@ -46,9 +42,10 @@ static void wait_synchronization(SercomSpi *regs) #endif } -static int spi_sam0_configure(struct spi_config *config) +static int spi_sam0_configure(struct device *dev, + const struct spi_config *config) { - const struct spi_sam0_config *cfg = config->dev->config->config_info; + const struct spi_sam0_config *cfg = dev->config->config_info; SercomSpi *regs = cfg->regs; SERCOM_SPI_CTRLA_Type ctrla = {.reg = 0}; SERCOM_SPI_CTRLB_Type ctrlb = {.reg = 0}; @@ -176,7 +173,7 @@ static void spi_sam0_fast_tx(SercomSpi *regs, const struct spi_buf *tx_buf) } /* Fast path that reads into a buf */ -static void spi_sam0_fast_rx(SercomSpi *regs, struct spi_buf *rx_buf) +static void spi_sam0_fast_rx(SercomSpi *regs, const struct spi_buf *rx_buf) { u8_t *rx = rx_buf->buf; int len = rx_buf->len; @@ -213,8 +210,9 @@ static void spi_sam0_fast_rx(SercomSpi *regs, struct spi_buf *rx_buf) } /* Fast path that writes and reads bufs of the same length */ -static void spi_sam0_fast_txrx(SercomSpi *regs, const struct spi_buf *tx_buf, - struct spi_buf *rx_buf) +static void spi_sam0_fast_txrx(SercomSpi *regs, + const struct spi_buf *tx_buf, + const struct spi_buf *rx_buf) { const u8_t *tx = tx_buf->buf; const u8_t *txend = tx_buf->buf + tx_buf->len; @@ -264,34 +262,51 @@ static void spi_sam0_fast_txrx(SercomSpi *regs, const struct spi_buf *tx_buf, } /* Fast path where every overlapping tx and rx buffer is the same length */ -static void spi_sam0_fast_transceive(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, struct spi_buf *rx_bufs, - size_t rx_count) +static void spi_sam0_fast_transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) { - const struct spi_sam0_config *cfg = config->dev->config->config_info; + const struct spi_sam0_config *cfg = dev->config->config_info; + size_t tx_count = 0; + size_t rx_count = 0; SercomSpi *regs = cfg->regs; + const struct spi_buf *tx; + const struct spi_buf *rx; + + if (tx_bufs) { + tx = tx_bufs->buffers; + tx_count = tx_bufs->count; + } + + if (rx_bufs) { + rx = rx_bufs->buffers; + rx_count = rx_bufs->count; + } else { + rx = NULL; + } while (tx_count != 0 && rx_count != 0) { - if (tx_bufs->buf == NULL) { - spi_sam0_fast_rx(regs, rx_bufs); - } else if (rx_bufs->buf == NULL) { - spi_sam0_fast_tx(regs, tx_bufs); + if (tx->buf == NULL) { + spi_sam0_fast_rx(regs, rx); + } else if (rx->buf == NULL) { + spi_sam0_fast_tx(regs, tx); } else { - spi_sam0_fast_txrx(regs, tx_bufs, rx_bufs); + spi_sam0_fast_txrx(regs, tx, rx); } - tx_bufs++; + + tx++; tx_count--; - rx_bufs++; + rx++; rx_count--; } for (; tx_count != 0; tx_count--) { - spi_sam0_fast_tx(regs, tx_bufs++); + spi_sam0_fast_tx(regs, tx++); } for (; rx_count != 0; rx_count--) { - spi_sam0_fast_rx(regs, rx_bufs++); + spi_sam0_fast_rx(regs, rx++); } } @@ -302,36 +317,55 @@ static void spi_sam0_fast_transceive(struct spi_config *config, * - Zero or more trailing RX only bufs * - Zero or more trailing TX only bufs */ -static bool spi_sam0_is_regular(const struct spi_buf *tx_bufs, - size_t tx_count, struct spi_buf *rx_bufs, - size_t rx_count) +static bool spi_sam0_is_regular(const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) { + const struct spi_buf *tx = NULL; + const struct spi_buf *rx = NULL; + size_t tx_count = 0; + size_t rx_count = 0; + + if (tx_bufs) { + tx = tx_bufs->buffers; + tx_count = tx_bufs->count; + } + + if (rx_bufs) { + rx = rx_bufs->buffers; + rx_count = rx_bufs->count; + } + + if (!tx || !rx) { + return false; + } + while (tx_count != 0 && rx_count != 0) { - if (tx_bufs->len != rx_bufs->len) { + if (tx->len != rx->len) { return false; } - tx_bufs++; + tx++; tx_count--; - rx_bufs++; + rx++; rx_count--; } return true; } -static int spi_sam0_transceive(struct spi_config *config, - const struct spi_buf *tx_bufs, size_t tx_count, - struct spi_buf *rx_bufs, size_t rx_count) +static int spi_sam0_transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) { - const struct spi_sam0_config *cfg = config->dev->config->config_info; - struct spi_sam0_data *data = config->dev->driver_data; + const struct spi_sam0_config *cfg = dev->config->config_info; + struct spi_sam0_data *data = dev->driver_data; SercomSpi *regs = cfg->regs; int err; spi_context_lock(&data->ctx, false, NULL); - err = spi_sam0_configure(config); + err = spi_sam0_configure(dev, config); if (err != 0) { goto done; } @@ -345,12 +379,10 @@ static int spi_sam0_transceive(struct spi_config *config, * casing is 4x faster than the spi_context() routines * and allows the transmit and receive to be interleaved. */ - if (spi_sam0_is_regular(tx_bufs, tx_count, rx_bufs, rx_count)) { - spi_sam0_fast_transceive(config, tx_bufs, tx_count, rx_bufs, - rx_count); + if (spi_sam0_is_regular(tx_bufs, rx_bufs)) { + spi_sam0_fast_transceive(dev, config, tx_bufs, rx_bufs); } else { - spi_context_buffers_setup(&data->ctx, tx_bufs, tx_count, - rx_bufs, rx_count, 1); + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); do { spi_sam0_shift_master(regs, data); @@ -364,20 +396,21 @@ static int spi_sam0_transceive(struct spi_config *config, return err; } -#ifdef CONFIG_POLL -static int spi_sam0_transceive_async(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, struct spi_buf *rx_bufs, - size_t rx_count, +#ifdef CONFIG_SPI_ASYNC +static int spi_sam0_transceive_async(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, struct k_poll_signal *async) { return -ENOTSUP; } -#endif +#endif /* CONFIG_SPI_ASYNC */ -static int spi_sam0_release(struct spi_config *config) +static int spi_sam0_release(struct device *dev, + const struct spi_config *config) { - struct spi_sam0_data *data = config->dev->driver_data; + struct spi_sam0_data *data = dev->driver_data; spi_context_unlock_unconditionally(&data->ctx); @@ -412,7 +445,7 @@ static int spi_sam0_init(struct device *dev) static const struct spi_driver_api spi_sam0_driver_api = { .transceive = spi_sam0_transceive, -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC .transceive_async = spi_sam0_transceive_async, #endif .release = spi_sam0_release, diff --git a/drivers/spi/spim_nrf52_legacy.c b/drivers/spi/spim_nrf52_legacy.c deleted file mode 100644 index 26874a9da2bf..000000000000 --- a/drivers/spi/spim_nrf52_legacy.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corp. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * #define CONFIG_ASSERT - * #define __ASSERT_ON 1 - */ - -#include -#include -#include -#include -#include -#include - -#define SYS_LOG_DOMAIN "spim" -#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL -#include - -/* @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 { - u8_t sck; - u8_t mosi; - u8_t miso; -#define SS_UNUSED 255 - /* Pin number of up to 4 slave devices */ - u8_t ss[4]; - } psel; - u8_t orc; -}; - -struct spim_nrf52_data { - struct k_sem sem; - struct device *gpio_port; - u8_t slave; - u8_t stopped:1; - u8_t txd:1; - u8_t rxd:1; -#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_INFO) - u32_t tx_cnt; - u32_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; - u32_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; - break; - 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_Pos) : - (SPIM_CONFIG_ORDER_MsbFirst << SPIM_CONFIG_ORDER_Pos); - spim->CONFIG |= (flags & SPI_MODE_CPOL) ? - (SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos) : - (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos); - spim->CONFIG |= (flags & SPI_MODE_CPHA) ? - (SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos) : - (SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos); - - spim->INTENSET = NRF52_SPIM_INT_END; - - spim_nrf52_print_cfg_registers(dev); - - return 0; -} - -static int spim_nrf52_slave_select(struct device *dev, u32_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, u32_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, - u32_t tx_buf_len, void *rx_buf, - u32_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 = (u32_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 = (u32_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 | GPIO_PUD_PULL_UP); - __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_SPIM1_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 */ diff --git a/drivers/spi/spis_nrf5_legacy.c b/drivers/spi/spis_nrf5_legacy.c deleted file mode 100644 index edf825874f71..000000000000 --- a/drivers/spi/spis_nrf5_legacy.c +++ /dev/null @@ -1,456 +0,0 @@ -/* spis_nrf5.c - SPI slave driver for Nordic nRF5x SoCs */ -/* - * Copyright (c) 2016, 2017 Linaro Limited. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -typedef void (*spis_nrf5_config_t)(void); - -struct spis_nrf5_config { - NRF_SPIS_Type *regs; /* Registers */ - spis_nrf5_config_t config_func; /* IRQ config func pointer */ - u8_t sck_pin; /* SCK GPIO pin number */ - u8_t mosi_pin; /* MOSI GPIO pin number */ - u8_t miso_pin; /* MISO GPIO pin number */ - u8_t csn_pin; /* CSN GPIO pin number */ - u8_t def; /* Default character */ -}; - -struct spis_nrf5_data { - u8_t error; - struct k_sem device_sync_sem; /* synchronisation semaphore */ -}; - -#define DEV_CFG(dev) \ - ((const struct spis_nrf5_config * const)(dev)->config->config_info) -#define DEV_DATA(dev) \ - ((struct spis_nrf5_data * const)(dev)->driver_data) -#define SPI_REGS(dev) \ - ((DEV_CFG(dev))->regs) - -/* Register fields */ - -#define NRF5_SPIS_SHORTCUT_END_ACQUIRE \ - (SPIS_SHORTS_END_ACQUIRE_Enabled << SPIS_SHORTS_END_ACQUIRE_Pos) - -#define NRF5_SPIS_ORDER_MSB \ - (SPIS_CONFIG_ORDER_MsbFirst << SPIS_CONFIG_ORDER_Pos) -#define NRF5_SPIS_ORDER_LSB \ - (SPIS_CONFIG_ORDER_LsbFirst << SPIS_CONFIG_ORDER_Pos) - -#define NRF5_SPIS_CPHA_LEADING \ - (SPIS_CONFIG_CPHA_Leading << SPIS_CONFIG_CPHA_Pos) -#define NRF5_SPIS_CPHA_TRAILING \ - (SPIS_CONFIG_CPHA_Trailing << SPIS_CONFIG_CPHA_Pos) - -#define NRF5_SPIS_CPOL_HIGH \ - (SPIS_CONFIG_CPOL_ActiveHigh << SPIS_CONFIG_CPOL_Pos) -#define NRF5_SPIS_CPOL_LOW \ - (SPIS_CONFIG_CPOL_ActiveLow << SPIS_CONFIG_CPOL_Pos) - -#define NRF5_SPIS_ENABLED \ - (SPIS_ENABLE_ENABLE_Enabled << SPIS_ENABLE_ENABLE_Pos) - -#define NRF5_SPIS_CSN_DISABLED_CFG 0xff /* CS disabled value from Kconfig */ -#if defined(CONFIG_SOC_SERIES_NRF51X) -#define NRF5_SPIS_CSN_DISABLED (~0U) /* CS disabled register value */ -#elif defined(CONFIG_SOC_SERIES_NRF52X) -#define NRF5_SPIS_CSN_DISABLED (1U << 31) /* CS disabled register value */ -#endif - -static inline bool is_buf_in_ram(const void *buf) -{ - return ((((uintptr_t) buf) & 0xE0000000) == 0x20000000); -} - -static void spis_nrf5_print_cfg_registers(struct device *dev) -{ - __unused NRF_SPIS_Type *regs = SPI_REGS(dev); - __unused u32_t sck, miso, mosi, csn; - __unused u32_t rxd_ptr, rxd_max, rxd_amount; - __unused u32_t txd_ptr, txd_max, txd_amount; - -#if defined(CONFIG_SOC_SERIES_NRF51X) - sck = regs->PSELSCK; - miso = regs->PSELMISO; - mosi = regs->PSELMOSI; - csn = regs->PSELCSN; - rxd_ptr = regs->RXDPTR; - rxd_max = regs->MAXRX; - rxd_amount = regs->AMOUNTRX; - txd_ptr = regs->TXDPTR; - txd_max = regs->MAXTX; - txd_amount = regs->AMOUNTTX; -#elif defined(CONFIG_SOC_SERIES_NRF52X) - sck = regs->PSEL.SCK; - miso = regs->PSEL.MISO; - mosi = regs->PSEL.MOSI; - csn = regs->PSEL.CSN; - rxd_ptr = regs->RXD.PTR; - rxd_max = regs->RXD.MAXCNT; - rxd_amount = regs->RXD.AMOUNT; - txd_ptr = regs->TXD.PTR; - txd_max = regs->TXD.MAXCNT; - txd_amount = regs->TXD.AMOUNT; -#endif /* defined(CONFIG_SOC_SERIES_NRF51X) */ - - SYS_LOG_DBG("\n" - "SHORTS: %x, IRQ: %x, SEMSTAT: %x\n" - "CONFIG: %x, STATUS: %x, ENABLE: %x\n" - "SCKPIN: %x, MISOPIN: %x, MOSIPIN: %x, CSNPIN: %x\n" - "RXD (PTR: %x, MAX: %x, AMOUNT: %x)\n" - "TXD (PTR: %x, MAX: %x, AMOUNT: %x)", - regs->SHORTS, regs->INTENSET, regs->SEMSTAT, - regs->CONFIG, regs->STATUS, regs->ENABLE, - sck, miso, mosi, csn, - rxd_ptr, rxd_max, rxd_amount, - txd_ptr, txd_max, txd_amount); -} - -/** - * @brief Configure the SPI host controller for operating against slaves - * @param dev Pointer to the device structure for the driver instance - * @param config Pointer to the application provided configuration - * - * @return 0 if successful, another DEV_* code otherwise. - */ -static int spis_nrf5_configure(struct device *dev, struct spi_config *config) -{ - NRF_SPIS_Type *spi_regs = SPI_REGS(dev); - u32_t flags; - - /* make sure module is disabled */ - spi_regs->ENABLE = 0; - - /* TODO: Muck with IRQ priority if needed */ - - /* Clear any pending events */ - spi_regs->EVENTS_ACQUIRED = 0; - spi_regs->EVENTS_ENDRX = 0; - spi_regs->EVENTS_END = 0; - spi_regs->INTENCLR = 0xFFFFFFFF; /* do we need to clear INT ?*/ - spi_regs->SHORTS = NRF5_SPIS_SHORTCUT_END_ACQUIRE; - spi_regs->INTENSET |= (SPIS_INTENSET_ACQUIRED_Msk | - SPIS_INTENSET_END_Msk); - - /* default transmit and over-read characters */ - spi_regs->DEF = DEV_CFG(dev)->def; - spi_regs->ORC = 0x000000AA; - - /* user configuration */ - flags = config->config; - if (flags & SPI_TRANSFER_LSB) { - spi_regs->CONFIG = NRF5_SPIS_ORDER_LSB; - } else { - spi_regs->CONFIG = NRF5_SPIS_ORDER_MSB; - } - if (flags & SPI_MODE_CPHA) { - spi_regs->CONFIG |= NRF5_SPIS_CPHA_TRAILING; - } else { - spi_regs->CONFIG |= NRF5_SPIS_CPHA_LEADING; - } - if (flags & SPI_MODE_CPOL) { - spi_regs->CONFIG |= NRF5_SPIS_CPOL_LOW; - } else { - spi_regs->CONFIG |= NRF5_SPIS_CPOL_HIGH; - } - - /* Enable the SPIS - peripherals sharing same ID will be disabled */ - spi_regs->ENABLE = NRF5_SPIS_ENABLED; - - spis_nrf5_print_cfg_registers(dev); - - SYS_LOG_DBG("SPI Slave Driver configured"); - - return 0; -} - -/** - * @brief Read and/or write a defined amount of data through an SPI driver - * - * @param dev Pointer to the device structure for the driver instance - * @param tx_buf Memory buffer that data should be transferred from - * @param tx_buf_len Size of the memory buffer available for reading from - * @param rx_buf Memory buffer that data should be transferred to - * @param rx_buf_len Size of the memory buffer available for writing to - * - * @return 0 if successful, another DEV_* code otherwise. - */ -static int spis_nrf5_transceive(struct device *dev, const void *tx_buf, - u32_t tx_buf_len, void *rx_buf, u32_t rx_buf_len) -{ - NRF_SPIS_Type *spi_regs = SPI_REGS(dev); - struct spis_nrf5_data *priv_data = DEV_DATA(dev); - - __ASSERT(!((tx_buf_len && !tx_buf) || (rx_buf_len && !rx_buf)), - "spis_nrf5_transceive: ERROR - NULL buffers"); - - /* Buffer needs to be in RAM for EasyDMA to work */ - if (!tx_buf || !is_buf_in_ram(tx_buf)) { - SYS_LOG_ERR("Invalid TX buf %p", tx_buf); - return -EINVAL; - } - if (!rx_buf || !is_buf_in_ram(rx_buf)) { - SYS_LOG_ERR("Invalid RX buf %p", rx_buf); - return -EINVAL; - } - - priv_data->error = 0; - - if (spi_regs->SEMSTAT == 1) { -#if defined(CONFIG_SOC_SERIES_NRF51X) - spi_regs->TXDPTR = (u32_t) tx_buf; - spi_regs->RXDPTR = (u32_t) rx_buf; - spi_regs->MAXTX = tx_buf_len; - spi_regs->MAXRX = rx_buf_len; -#elif defined(CONFIG_SOC_SERIES_NRF52X) - spi_regs->TXD.PTR = (u32_t) tx_buf; - spi_regs->RXD.PTR = (u32_t) rx_buf; - spi_regs->TXD.MAXCNT = tx_buf_len; - spi_regs->RXD.MAXCNT = rx_buf_len; -#endif - spi_regs->TASKS_RELEASE = 1; - } else { - SYS_LOG_ERR("Can't get SEM; unfinished transfer?"); - return -EIO; - } - - /* wait for transfer to complete */ - k_sem_take(&priv_data->device_sync_sem, K_FOREVER); - - if (priv_data->error) { - priv_data->error = 0; - return -EIO; - } - - return 0; -} - -/** - * @brief Complete SPI module data transfer operations. - * @param dev Pointer to the device structure for the driver instance - * @param error Error condition (0 = no error, otherwise an error occurred) - * @return None. - */ -static void spis_nrf5_complete(struct device *dev, u32_t error) -{ - __unused NRF_SPIS_Type *spi_regs = SPI_REGS(dev); - __unused u32_t txd_amount, rxd_amount; - struct spis_nrf5_data *priv_data = DEV_DATA(dev); - -#if defined(CONFIG_SOC_SERIES_NRF51X) - txd_amount = spi_regs->AMOUNTTX; - rxd_amount = spi_regs->AMOUNTRX; -#elif defined(CONFIG_SOC_SERIES_NRF52X) - txd_amount = spi_regs->RXD.AMOUNT; - rxd_amount = spi_regs->TXD.AMOUNT; -#endif - - SYS_LOG_DBG("bytes transferred: TX: %u, RX: %u [err %u (%s)]", - txd_amount, rxd_amount, - error, error == 0 ? "OK" : "ERR"); - - priv_data->error = error ? 1 : 0; - - k_sem_give(&priv_data->device_sync_sem); -} - -/** - * @brief SPI module interrupt handler. - * @param arg Pointer to the device structure for the driver instance - * @return None. - */ -static void spis_nrf5_isr(void *arg) -{ - struct device *dev = arg; - NRF_SPIS_Type *spi_regs = SPI_REGS(dev); - u32_t error; - u32_t tmp; - - /* We get an interrupt for the following reasons: - * 1. Semaphore ACQUIRED: - * Semaphore is assigned to the CPU again (always happens - * after END if the END_ACQUIRE SHORTS is set) - * 2. End of Granted SPI transaction: - * Used to unblocked the caller, finishing the transaction - */ - - /* NOTE: - * Section 15.8.1 of nrf52 manual suggests reading back the register - * to cause a 4-cycle delay to prevent the interrupt from - * re-occurring - */ - - if (spi_regs->EVENTS_END) { - spi_regs->EVENTS_END = 0; - /* force register flush (per spec) */ - tmp = spi_regs->EVENTS_END; - - /* Read and clear error flags. */ - error = spi_regs->STATUS; - spi_regs->STATUS = error; - - spis_nrf5_complete(dev, error); - } - if (spi_regs->EVENTS_ACQUIRED) { - spi_regs->EVENTS_ACQUIRED = 0; - /* force registesr flush (per spec) */ - tmp = spi_regs->EVENTS_ACQUIRED; - } -} - -static const struct spi_driver_api nrf5_spis_api = { - .transceive = spis_nrf5_transceive, - .configure = spis_nrf5_configure, - .slave_select = NULL, -}; - -#if defined(CONFIG_SOC_SERIES_NRF51X) -static void spis_configure_psel(NRF_SPIS_Type *spi_regs, - const struct spis_nrf5_config *cfg) -{ - spi_regs->PSELMOSI = cfg->mosi_pin; - spi_regs->PSELMISO = cfg->miso_pin; - spi_regs->PSELSCK = cfg->sck_pin; - if (cfg->csn_pin == NRF5_SPIS_CSN_DISABLED_CFG) { - spi_regs->PSELCSN = NRF5_SPIS_CSN_DISABLED; - } else { - spi_regs->PSELCSN = cfg->csn_pin; - } -} -#elif defined(CONFIG_SOC_SERIES_NRF52X) -static void spis_configure_psel(NRF_SPIS_Type *spi_regs, - const struct spis_nrf5_config *cfg) -{ - spi_regs->PSEL.MOSI = cfg->mosi_pin; - spi_regs->PSEL.MISO = cfg->miso_pin; - spi_regs->PSEL.SCK = cfg->sck_pin; - if (cfg->csn_pin == NRF5_SPIS_CSN_DISABLED_CFG) { - spi_regs->PSEL.CSN = NRF5_SPIS_CSN_DISABLED; - } else { - spi_regs->PSEL.CSN = cfg->csn_pin; - } -} -#else -#error "Unsupported NRF5 SoC" -#endif - -static int spis_nrf5_init(struct device *dev) -{ - NRF_SPIS_Type *spi_regs = SPI_REGS(dev); - struct spis_nrf5_data *priv_data = DEV_DATA(dev); - const struct spis_nrf5_config *cfg = DEV_CFG(dev); - struct device *gpio_dev; - int ret; - - SYS_LOG_DBG("SPI Slave driver init: %p", dev); - - /* Enable constant latency for faster SPIS response */ - NRF_POWER->TASKS_CONSTLAT = 1; - - spi_regs->ENABLE = 0; - - gpio_dev = device_get_binding(CONFIG_GPIO_NRF5_P0_DEV_NAME); - - ret = gpio_pin_configure(gpio_dev, cfg->miso_pin, - GPIO_DIR_IN | GPIO_PUD_NORMAL); - __ASSERT_NO_MSG(!ret); - - ret = gpio_pin_configure(gpio_dev, cfg->mosi_pin, - GPIO_DIR_IN | GPIO_PUD_NORMAL); - __ASSERT_NO_MSG(!ret); - - ret = gpio_pin_configure(gpio_dev, cfg->sck_pin, - GPIO_DIR_IN | GPIO_PUD_NORMAL); - __ASSERT_NO_MSG(!ret); - - if (cfg->csn_pin != 0xff) { - ret = gpio_pin_configure(gpio_dev, cfg->csn_pin, - GPIO_DIR_IN | GPIO_PUD_PULL_UP); - __ASSERT_NO_MSG(!ret); - } - - spis_configure_psel(spi_regs, cfg); - - cfg->config_func(); - - k_sem_init(&priv_data->device_sync_sem, 0, 1); - - SYS_LOG_DBG("SPI Slave driver initialized on device: %p", dev); - - return 0; -} - -/* system bindings */ -#ifdef CONFIG_SPIS0_NRF52 - -static void spis_config_irq_0(void); - -static struct spis_nrf5_data spis_nrf5_data_0; - -static const struct spis_nrf5_config spis_nrf5_config_0 = { - .regs = NRF_SPIS0, - .config_func = spis_config_irq_0, - .sck_pin = CONFIG_SPIS0_NRF52_GPIO_SCK_PIN, - .mosi_pin = CONFIG_SPIS0_NRF52_GPIO_MOSI_PIN, - .miso_pin = CONFIG_SPIS0_NRF52_GPIO_MISO_PIN, - .csn_pin = CONFIG_SPIS0_NRF52_GPIO_CSN_PIN, - .def = CONFIG_SPIS0_NRF52_DEF, -}; - -DEVICE_AND_API_INIT(spis_nrf5_port_0, CONFIG_SPI_0_NAME, spis_nrf5_init, - &spis_nrf5_data_0, &spis_nrf5_config_0, PRE_KERNEL_1, - CONFIG_SPI_INIT_PRIORITY, &nrf5_spis_api); - -static void spis_config_irq_0(void) -{ - IRQ_CONNECT(NRF5_IRQ_SPI0_TWI0_IRQn, CONFIG_SPI_0_IRQ_PRI, - spis_nrf5_isr, DEVICE_GET(spis_nrf5_port_0), 0); - irq_enable(NRF5_IRQ_SPI0_TWI0_IRQn); -} - -#endif /* CONFIG_SPIS0_NRF52 */ - -#ifdef CONFIG_SPIS1_NRF5 - -static void spis_config_irq_1(void); - -static struct spis_nrf5_data spis_nrf5_data_1; - -static const struct spis_nrf5_config spis_nrf5_config_1 = { - .regs = NRF_SPIS1, - .config_func = spis_config_irq_1, - .sck_pin = CONFIG_SPIS1_NRF5_GPIO_SCK_PIN, - .mosi_pin = CONFIG_SPIS1_NRF5_GPIO_MOSI_PIN, - .miso_pin = CONFIG_SPIS1_NRF5_GPIO_MISO_PIN, - .csn_pin = CONFIG_SPIS1_NRF5_GPIO_CSN_PIN, - .def = CONFIG_SPIS1_NRF5_DEF, -}; - -DEVICE_AND_API_INIT(spis_nrf5_port_1, CONFIG_SPI_1_NAME, spis_nrf5_init, - &spis_nrf5_data_1, &spis_nrf5_config_1, PRE_KERNEL_1, - CONFIG_SPI_INIT_PRIORITY, &nrf5_spis_api); - -static void spis_config_irq_1(void) -{ - IRQ_CONNECT(NRF5_IRQ_SPI1_TWI1_IRQn, CONFIG_SPI_1_IRQ_PRI, - spis_nrf5_isr, DEVICE_GET(spis_nrf5_port_1), 0); - irq_enable(NRF5_IRQ_SPI1_TWI1_IRQn); -} - -#endif /* CONFIG_SPIS1_NRF5 */ diff --git a/ext/hal/nordic/CMakeLists.txt b/ext/hal/nordic/CMakeLists.txt index 4871121787be..087c2381df30 100644 --- a/ext/hal/nordic/CMakeLists.txt +++ b/ext/hal/nordic/CMakeLists.txt @@ -19,6 +19,7 @@ if(CONFIG_HAS_NRFX) zephyr_sources_ifdef(CONFIG_NRFX_SAADC nrfx/drivers/src/nrfx_saadc.c) zephyr_sources_ifdef(CONFIG_NRFX_SPI nrfx/drivers/src/nrfx_spi.c) zephyr_sources_ifdef(CONFIG_NRFX_SPIM nrfx/drivers/src/nrfx_spim.c) + zephyr_sources_ifdef(CONFIG_NRFX_SPIS nrfx/drivers/src/nrfx_spis.c) zephyr_sources_ifdef(CONFIG_NRFX_TWI nrfx/drivers/src/nrfx_twi.c) zephyr_sources_ifdef(CONFIG_NRFX_TWIM nrfx/drivers/src/nrfx_twim.c) zephyr_sources_ifdef(CONFIG_NRFX_UART nrfx/drivers/src/nrfx_uart.c) diff --git a/ext/hal/nordic/Kconfig b/ext/hal/nordic/Kconfig index db3977c2d567..56fab3f7b003 100644 --- a/ext/hal/nordic/Kconfig +++ b/ext/hal/nordic/Kconfig @@ -9,3 +9,12 @@ config HAS_NORDIC_DRIVERS config HAS_NRFX bool + +config NRFX_SPI + bool + +config NRFX_SPIM + bool + +config NRFX_SPIS + bool diff --git a/ext/hal/nordic/nrfx_config_nrf51.h b/ext/hal/nordic/nrfx_config_nrf51.h index 1dc4ef92ae1a..cb65f6d894ca 100644 --- a/ext/hal/nordic/nrfx_config_nrf51.h +++ b/ext/hal/nordic/nrfx_config_nrf51.h @@ -877,14 +877,14 @@ // NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver //========================================================== -#ifndef NRFX_SPIS_ENABLED -#define NRFX_SPIS_ENABLED 0 +#ifdef CONFIG_NRFX_SPIS +#define NRFX_SPIS_ENABLED 1 #endif // NRFX_SPIS1_ENABLED - Enable SPIS1 instance -#ifndef NRFX_SPIS1_ENABLED -#define NRFX_SPIS1_ENABLED 0 +#ifdef CONFIG_SPI_1_NRF_SPIS +#define NRFX_SPIS1_ENABLED 1 #endif // NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority @@ -967,21 +967,21 @@ // NRFX_SPI_ENABLED - nrfx_spi - SPI peripheral driver //========================================================== -#ifndef NRFX_SPI_ENABLED -#define NRFX_SPI_ENABLED 0 +#ifdef CONFIG_NRFX_SPI +#define NRFX_SPI_ENABLED 1 #endif // NRFX_SPI0_ENABLED - Enable SPI0 instance -#ifndef NRFX_SPI0_ENABLED -#define NRFX_SPI0_ENABLED 0 +#ifdef CONFIG_SPI_0_NRF_SPI +#define NRFX_SPI0_ENABLED 1 #endif // NRFX_SPI1_ENABLED - Enable SPI1 instance -#ifndef NRFX_SPI1_ENABLED -#define NRFX_SPI1_ENABLED 0 +#ifdef CONFIG_SPI_1_NRF_SPI +#define NRFX_SPI1_ENABLED 1 #endif // NRFX_SPI_MISO_PULL_CFG - MISO pin pull configuration. diff --git a/ext/hal/nordic/nrfx_config_nrf52832.h b/ext/hal/nordic/nrfx_config_nrf52832.h index fe439c4fb684..2a09fee48df3 100644 --- a/ext/hal/nordic/nrfx_config_nrf52832.h +++ b/ext/hal/nordic/nrfx_config_nrf52832.h @@ -1605,28 +1605,28 @@ // NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver //========================================================== -#ifndef NRFX_SPIM_ENABLED -#define NRFX_SPIM_ENABLED 0 +#ifdef CONFIG_NRFX_SPIM +#define NRFX_SPIM_ENABLED 1 #endif // NRFX_SPIM0_ENABLED - Enable SPIM0 instance -#ifndef NRFX_SPIM0_ENABLED -#define NRFX_SPIM0_ENABLED 0 +#ifdef CONFIG_SPI_0_NRF_SPIM +#define NRFX_SPIM0_ENABLED 1 #endif // NRFX_SPIM1_ENABLED - Enable SPIM1 instance -#ifndef NRFX_SPIM1_ENABLED -#define NRFX_SPIM1_ENABLED 0 +#ifdef CONFIG_SPI_1_NRF_SPIM +#define NRFX_SPIM1_ENABLED 1 #endif // NRFX_SPIM2_ENABLED - Enable SPIM2 instance -#ifndef NRFX_SPIM2_ENABLED -#define NRFX_SPIM2_ENABLED 0 +#ifdef CONFIG_SPI_2_NRF_SPIM +#define NRFX_SPIM2_ENABLED 1 #endif // NRFX_SPIM_MISO_PULL_CFG - MISO pin pull configuration. @@ -1723,28 +1723,28 @@ // NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver //========================================================== -#ifndef NRFX_SPIS_ENABLED -#define NRFX_SPIS_ENABLED 0 +#ifdef CONFIG_NRFX_SPIS +#define NRFX_SPIS_ENABLED 1 #endif // NRFX_SPIS0_ENABLED - Enable SPIS0 instance -#ifndef NRFX_SPIS0_ENABLED -#define NRFX_SPIS0_ENABLED 0 +#ifdef CONFIG_SPI_0_NRF_SPIS +#define NRFX_SPIS0_ENABLED 1 #endif // NRFX_SPIS1_ENABLED - Enable SPIS1 instance -#ifndef NRFX_SPIS1_ENABLED -#define NRFX_SPIS1_ENABLED 0 +#ifdef CONFIG_SPI_1_NRF_SPIS +#define NRFX_SPIS1_ENABLED 1 #endif // NRFX_SPIS2_ENABLED - Enable SPIS2 instance -#ifndef NRFX_SPIS2_ENABLED -#define NRFX_SPIS2_ENABLED 0 +#ifdef CONFIG_SPI_2_NRF_SPIS +#define NRFX_SPIS2_ENABLED 1 #endif // NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority @@ -1845,28 +1845,28 @@ // NRFX_SPI_ENABLED - nrfx_spi - SPI peripheral driver //========================================================== -#ifndef NRFX_SPI_ENABLED -#define NRFX_SPI_ENABLED 0 +#ifdef CONFIG_NRFX_SPI +#define NRFX_SPI_ENABLED 1 #endif // NRFX_SPI0_ENABLED - Enable SPI0 instance -#ifndef NRFX_SPI0_ENABLED -#define NRFX_SPI0_ENABLED 0 +#ifdef CONFIG_SPI_0_NRF_SPI +#define NRFX_SPI0_ENABLED 1 #endif // NRFX_SPI1_ENABLED - Enable SPI1 instance -#ifndef NRFX_SPI1_ENABLED -#define NRFX_SPI1_ENABLED 0 +#ifdef CONFIG_SPI_1_NRF_SPI +#define NRFX_SPI1_ENABLED 1 #endif // NRFX_SPI2_ENABLED - Enable SPI2 instance -#ifndef NRFX_SPI2_ENABLED -#define NRFX_SPI2_ENABLED 0 +#ifdef CONFIG_SPI_2_NRF_SPI +#define NRFX_SPI2_ENABLED 1 #endif // NRFX_SPI_MISO_PULL_CFG - MISO pin pull configuration. diff --git a/ext/hal/nordic/nrfx_config_nrf52840.h b/ext/hal/nordic/nrfx_config_nrf52840.h index cdece46f71ca..9fcec04d9952 100644 --- a/ext/hal/nordic/nrfx_config_nrf52840.h +++ b/ext/hal/nordic/nrfx_config_nrf52840.h @@ -1712,35 +1712,35 @@ // NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver //========================================================== -#ifndef NRFX_SPIM_ENABLED -#define NRFX_SPIM_ENABLED 0 +#ifdef CONFIG_NRFX_SPIM +#define NRFX_SPIM_ENABLED 1 #endif // NRFX_SPIM0_ENABLED - Enable SPIM0 instance -#ifndef NRFX_SPIM0_ENABLED -#define NRFX_SPIM0_ENABLED 0 +#ifdef CONFIG_SPI_0_NRF_SPIM +#define NRFX_SPIM0_ENABLED 1 #endif // NRFX_SPIM1_ENABLED - Enable SPIM1 instance -#ifndef NRFX_SPIM1_ENABLED -#define NRFX_SPIM1_ENABLED 0 +#ifdef CONFIG_SPI_1_NRF_SPIM +#define NRFX_SPIM1_ENABLED 1 #endif // NRFX_SPIM2_ENABLED - Enable SPIM2 instance -#ifndef NRFX_SPIM2_ENABLED -#define NRFX_SPIM2_ENABLED 0 +#ifdef CONFIG_SPI_2_NRF_SPIM +#define NRFX_SPIM2_ENABLED 1 #endif // NRFX_SPIM3_ENABLED - Enable SPIM3 instance -#ifndef NRFX_SPIM3_ENABLED -#define NRFX_SPIM3_ENABLED 0 +#ifdef CONFIG_SPI_3_NRF_SPIM +#define NRFX_SPIM3_ENABLED 1 #endif // NRFX_SPIM_EXTENDED_ENABLED - Enable extended SPIM features @@ -1840,28 +1840,28 @@ // NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver //========================================================== -#ifndef NRFX_SPIS_ENABLED -#define NRFX_SPIS_ENABLED 0 +#ifdef CONFIG_NRFX_SPIS +#define NRFX_SPIS_ENABLED 1 #endif // NRFX_SPIS0_ENABLED - Enable SPIS0 instance -#ifndef NRFX_SPIS0_ENABLED -#define NRFX_SPIS0_ENABLED 0 +#ifdef CONFIG_SPI_0_NRF_SPIS +#define NRFX_SPIS0_ENABLED 1 #endif // NRFX_SPIS1_ENABLED - Enable SPIS1 instance -#ifndef NRFX_SPIS1_ENABLED -#define NRFX_SPIS1_ENABLED 0 +#ifdef CONFIG_SPI_1_NRF_SPIS +#define NRFX_SPIS1_ENABLED 1 #endif // NRFX_SPIS2_ENABLED - Enable SPIS2 instance -#ifndef NRFX_SPIS2_ENABLED -#define NRFX_SPIS2_ENABLED 0 +#ifdef CONFIG_SPI_2_NRF_SPIS +#define NRFX_SPIS2_ENABLED 1 #endif // NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority @@ -1948,28 +1948,28 @@ // NRFX_SPI_ENABLED - nrfx_spi - SPI peripheral driver //========================================================== -#ifndef NRFX_SPI_ENABLED -#define NRFX_SPI_ENABLED 0 +#ifdef CONFIG_NRFX_SPI +#define NRFX_SPI_ENABLED 1 #endif // NRFX_SPI0_ENABLED - Enable SPI0 instance -#ifndef NRFX_SPI0_ENABLED -#define NRFX_SPI0_ENABLED 0 +#ifdef CONFIG_SPI_0_NRF_SPI +#define NRFX_SPI0_ENABLED 1 #endif // NRFX_SPI1_ENABLED - Enable SPI1 instance -#ifndef NRFX_SPI1_ENABLED -#define NRFX_SPI1_ENABLED 0 +#ifdef CONFIG_SPI_1_NRF_SPI +#define NRFX_SPI1_ENABLED 1 #endif // NRFX_SPI2_ENABLED - Enable SPI2 instance -#ifndef NRFX_SPI2_ENABLED -#define NRFX_SPI2_ENABLED 0 +#ifdef CONFIG_SPI_2_NRF_SPI +#define NRFX_SPI2_ENABLED 1 #endif // NRFX_SPI_MISO_PULL_CFG - MISO pin pull configuration. diff --git a/include/drivers/spi/spi_intel.h b/include/drivers/spi/spi_intel.h deleted file mode 100644 index 10df7de1374a..000000000000 --- a/include/drivers/spi/spi_intel.h +++ /dev/null @@ -1,53 +0,0 @@ -/* spi_intel.h - Intel's SPI controller driver utilities */ - -/* - * Copyright (c) 2015 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __SPI_INTEL_H__ -#define __SPI_INTEL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* SPI Maximum supported system frequencies */ -#define SPI_MAX_CLK_FREQ_25MHZ ((0x800000 << 8)) -#define SPI_MAX_CLK_FREQ_20MHz ((0x666666 << 8) | 1) -#define SPI_MAX_CLK_FREQ_166667KHZ ((0x800000 << 8) | 2) -#define SPI_MAX_CLK_FREQ_13333KHZ ((0x666666 << 8) | 2) -#define SPI_MAX_CLK_FREQ_12500KHZ ((0x200000 << 8)) -#define SPI_MAX_CLK_FREQ_10MHZ ((0x800000 << 8) | 4) -#define SPI_MAX_CLK_FREQ_8MHZ ((0x666666 << 8) | 4) -#define SPI_MAX_CLK_FREQ_6250HZ ((0x400000 << 8) | 3) -#define SPI_MAX_CLK_FREQ_5MHZ ((0x400000 << 8) | 4) -#define SPI_MAX_CLK_FREQ_4MHZ ((0x666666 << 8) | 9) -#define SPI_MAX_CLK_FREQ_3125KHZ ((0x80000 << 8)) -#define SPI_MAX_CLK_FREQ_2500KHZ ((0x400000 << 8) | 9) -#define SPI_MAX_CLK_FREQ_2MHZ ((0x666666 << 8) | 19) -#define SPI_MAX_CLK_FREQ_1563KHZ ((0x40000 << 8)) -#define SPI_MAX_CLK_FREQ_1250KHZ ((0x200000 << 8) | 9) -#define SPI_MAX_CLK_FREQ_1MHZ ((0x400000 << 8) | 24) -#define SPI_MAX_CLK_FREQ_800KHZ ((0x666666 << 8) | 49) -#define SPI_MAX_CLK_FREQ_781KHZ ((0x20000 << 8)) -#define SPI_MAX_CLK_FREQ_625KHZ ((0x200000 << 8) | 19) -#define SPI_MAX_CLK_FREQ_500KHZ ((0x400000 << 8) | 49) -#define SPI_MAX_CLK_FREQ_400KHZ ((0x666666 << 8) | 99) -#define SPI_MAX_CLK_FREQ_390KHZ ((0x10000 << 8)) -#define SPI_MAX_CLK_FREQ_250KHZ ((0x400000 << 8) | 99) -#define SPI_MAX_CLK_FREQ_200KHZ ((0x666666 << 8) | 199) -#define SPI_MAX_CLK_FREQ_195KHZ ((0x8000 << 8)) -#define SPI_MAX_CLK_FREQ_125KHZ ((0x100000 << 8) | 49) -#define SPI_MAX_CLK_FREQ_100KHZ ((0x200000 << 8) | 124) -#define SPI_MAX_CLK_FREQ_50KHZ ((0x100000 << 8) | 124) -#define SPI_MAX_CLK_FREQ_20KHZ ((0x80000 << 8) | 124) -#define SPI_MAX_CLK_FREQ_10KHZ ((0x20000 << 8) | 77) -#define SPI_MAX_CLK_FREQ_5KHZ ((0x20000 << 8) | 154) -#define SPI_MAX_CLK_FREQ_1KHZ ((0x8000 << 8) | 194) -#ifdef __cplusplus -} -#endif - -#endif /* __SPI_INTEL_H__ */ diff --git a/include/spi.h b/include/spi.h index ea98342037dc..1ee88d92a242 100644 --- a/include/spi.h +++ b/include/spi.h @@ -9,16 +9,6 @@ * @brief Public API for SPI drivers and applications */ -#if defined(CONFIG_SPI_LEGACY_API) - -/* - * This is the default, and will be the way until the new API below - * will be enforced everywhere. - */ -#include - -#else - #ifndef __SPI_H__ #define __SPI_H__ @@ -96,12 +86,13 @@ extern "C" { /** * @brief SPI MISO lines * - * Some controllers support dual or quad MISO lines connected to slaves. + * Some controllers support dual, quad or octal MISO lines connected to slaves. * Default is single, which is the case most of the time. */ -#define SPI_LINES_SINGLE (0) -#define SPI_LINES_DUAL BIT(11) -#define SPI_LINES_QUAD BIT(12) +#define SPI_LINES_SINGLE (0 << 11) +#define SPI_LINES_DUAL (1 << 11) +#define SPI_LINES_QUAD (2 << 11) +#define SPI_LINES_OCTAL (3 << 11) #define SPI_LINES_MASK (0x3 << 11) @@ -116,11 +107,15 @@ extern "C" { * properly called. */ #define SPI_LOCK_ON BIT(14) -/* Select EEPROM read mode on master controller. - * If not supported by the controller, the driver will have to emulate - * the mode and thus should never return -EINVAL on that configuration) + +/* Active high logic on CS - Usually, and by default, CS logic is active + * low. However, some devices may require the reverse logic: active high. + * This bit will request the controller to use that logic. Note that not + * all controllers are able to handle that natively. In this case deferring + * the CS control to a gpio line through struct spi_cs_control would be + * the solution. */ -#define SPI_EEPROM_MODE BIT(15) +#define SPI_CS_ACTIVE_HIGH BIT(15) /** * @brief SPI Chip Select control structure @@ -152,25 +147,23 @@ struct spi_cs_control { * mode [ 1 : 3 ] - Polarity, phase and loop mode. * transfer [ 4 ] - LSB or MSB first. * word_size [ 5 : 10 ] - Size of a data frame in bits. - * lines [ 11 : 12 ] - MISO lines: Single/Dual/Quad. + * lines [ 11 : 12 ] - MISO lines: Single/Dual/Quad/Octal. * cs_hold [ 13 ] - Hold on the CS line if possible. * lock_on [ 14 ] - Keep resource locked for the caller. - * eeprom [ 15 ] - EEPROM mode. + * cs_active_high [ 15 ] - Active high CS logic. * @param slave is the slave number from 0 to host controller slave limit. * @param cs is a valid pointer on a struct spi_cs_control is CS line is * emulated through a gpio line, or NULL otherwise. * - * @note cs_hold, lock_on and eeprom_rx can be changed between consecutive - * transceive call. + * @note Only cs_hold and lock_on can be changed between consecutive + * transceive call. Rest of the attributes are not meant to be tweaked. */ struct spi_config { - struct device *dev; - u32_t frequency; u16_t operation; u16_t slave; - struct spi_cs_control *cs; + const struct spi_cs_control *cs; }; /** @@ -186,27 +179,36 @@ struct spi_buf { size_t len; }; +/** + * @brief SPI buffer array structure + * + * @param buffers is a valid pointer on an array of spi_buf, or NULL. + * @param count is the length of the array pointed by buffers. + */ +struct spi_buf_set { + const struct spi_buf *buffers; + size_t count; +}; + /** * @typedef spi_api_io * @brief Callback API for I/O * See spi_transceive() for argument descriptions */ -typedef int (*spi_api_io)(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count); +typedef int (*spi_api_io)(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs); /** * @typedef spi_api_io * @brief Callback API for asynchronous I/O * See spi_transceive_async() for argument descriptions */ -typedef int (*spi_api_io_async)(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count, +typedef int (*spi_api_io_async)(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, struct k_poll_signal *async); /** @@ -214,7 +216,8 @@ typedef int (*spi_api_io_async)(struct spi_config *config, * @brief Callback API for unlocking SPI device. * See spi_release() for argument descriptions */ -typedef int (*spi_api_release)(struct spi_config *config); +typedef int (*spi_api_release)(struct device *dev, + const struct spi_config *config); /** @@ -223,9 +226,9 @@ typedef int (*spi_api_release)(struct spi_config *config); */ struct spi_driver_api { spi_api_io transceive; -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC spi_api_io_async transceive_async; -#endif +#endif /* CONFIG_SPI_ASYNC */ spi_api_release release; }; @@ -234,31 +237,28 @@ struct spi_driver_api { * * Note: This function is synchronous. * + * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. * @param tx_bufs Buffer array where data to be sent originates from, * or NULL if none. - * @param tx_count Number of element in the tx_bufs array. * @param rx_bufs Buffer array where data to be read will be written to, * or NULL if none. - * @param rx_count Number of element in the rx_bufs array. * * @retval 0 If successful, negative errno code otherwise. */ -__syscall int spi_transceive(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count); - -static inline int _impl_spi_transceive(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count) +__syscall int spi_transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs); + +static inline int _impl_spi_transceive(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) { - const struct spi_driver_api *api = config->dev->driver_api; + const struct spi_driver_api *api = dev->driver_api; - return api->transceive(config, tx_bufs, tx_count, rx_bufs, rx_count); + return api->transceive(dev, config, tx_bufs, rx_bufs); } /** @@ -266,17 +266,19 @@ static inline int _impl_spi_transceive(struct spi_config *config, * * Note: This function is synchronous. * + * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. * @param rx_bufs Buffer array where data to be read will be written to. - * @param rx_count Number of element in the rx_bufs array. * * @retval 0 If successful, negative errno code otherwise. + * + * @note This function is an helper function calling spi_transceive. */ -static inline int spi_read(struct spi_config *config, - struct spi_buf *rx_bufs, - size_t rx_count) +static inline int spi_read(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *rx_bufs) { - return spi_transceive(config, NULL, 0, rx_bufs, rx_count); + return spi_transceive(dev, config, NULL, rx_bufs); } /** @@ -284,32 +286,33 @@ static inline int spi_read(struct spi_config *config, * * Note: This function is synchronous. * + * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. * @param tx_bufs Buffer array where data to be sent originates from. - * @param tx_count Number of element in the tx_bufs array. * * @retval 0 If successful, negative errno code otherwise. + * + * @note This function is an helper function calling spi_transceive. */ -static inline int spi_write(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count) +static inline int spi_write(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs) { - return spi_transceive(config, tx_bufs, tx_count, NULL, 0); + return spi_transceive(dev, config, tx_bufs, NULL); } -#ifdef CONFIG_POLL +#ifdef CONFIG_SPI_ASYNC /** * @brief Read/write the specified amount of data from the SPI driver. * * Note: This function is asynchronous. * + * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. * @param tx_bufs Buffer array where data to be sent originates from, * or NULL if none. - * @param tx_count Number of element in the tx_bufs array. * @param rx_bufs Buffer array where data to be read will be written to, * or NULL if none. - * @param rx_count Number of element in the rx_bufs array. * @param async A pointer to a valid and ready to be signaled * struct k_poll_signal. (Note: if NULL this function will not * notify the end of the transaction, and whether it went @@ -317,17 +320,15 @@ static inline int spi_write(struct spi_config *config, * * @retval 0 If successful, negative errno code otherwise. */ -static inline int spi_transceive_async(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, - struct spi_buf *rx_bufs, - size_t rx_count, +static inline int spi_transceive_async(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, struct k_poll_signal *async) { - const struct spi_driver_api *api = config->dev->driver_api; + const struct spi_driver_api *api = dev->driver_api; - return api->transceive_async(config, tx_bufs, tx_count, - rx_bufs, rx_count, async); + return api->transceive_async(dev, config, tx_bufs, rx_bufs, async); } /** @@ -335,25 +336,24 @@ static inline int spi_transceive_async(struct spi_config *config, * * Note: This function is asynchronous. * + * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. * @param rx_bufs Buffer array where data to be read will be written to. - * @param rx_count Number of element in the rx_bufs array. * @param async A pointer to a valid and ready to be signaled * struct k_poll_signal. (Note: if NULL this function will not * notify the end of the transaction, and whether it went * successfully or not). * * @retval 0 If successful, negative errno code otherwise. + * + * @note This function is an helper function calling spi_transceive_async. */ -static inline int spi_read_async(struct spi_config *config, - struct spi_buf *rx_bufs, - size_t rx_count, +static inline int spi_read_async(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *rx_bufs, struct k_poll_signal *async) { - const struct spi_driver_api *api = config->dev->driver_api; - - return api->transceive_async(config, NULL, 0, - rx_bufs, rx_count, async); + return spi_transceive_async(dev, config, NULL, rx_bufs, async); } /** @@ -361,27 +361,26 @@ static inline int spi_read_async(struct spi_config *config, * * Note: This function is asynchronous. * + * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. * @param tx_bufs Buffer array where data to be sent originates from. - * @param tx_count Number of element in the tx_bufs array. * @param async A pointer to a valid and ready to be signaled * struct k_poll_signal. (Note: if NULL this function will not * notify the end of the transaction, and whether it went * successfully or not). * * @retval 0 If successful, negative errno code otherwise. + * + * @note This function is an helper function calling spi_transceive_async. */ -static inline int spi_write_async(struct spi_config *config, - const struct spi_buf *tx_bufs, - size_t tx_count, +static inline int spi_write_async(struct device *dev, + const struct spi_config *config, + const struct spi_buf_set *tx_bufs, struct k_poll_signal *async) { - const struct spi_driver_api *api = config->dev->driver_api; - - return api->transceive_async(config, tx_bufs, tx_count, - NULL, 0, async); + return spi_transceive_async(dev, config, tx_bufs, NULL, async); } -#endif /* CONFIG_POLL */ +#endif /* CONFIG_SPI_ASYNC */ /** * @brief Release the SPI device locked on by the current config @@ -393,15 +392,18 @@ static inline int spi_write_async(struct spi_config *config, * This can be used if the caller needs to keep its hand on the SPI * device for consecutive transactions. * + * @param dev Pointer to the device structure for the driver instance * @param config Pointer to a valid spi_config structure instance. */ -__syscall int spi_release(struct spi_config *config); +__syscall int spi_release(struct device *dev, + const struct spi_config *config); -static inline int _impl_spi_release(struct spi_config *config) +static inline int _impl_spi_release(struct device *dev, + const struct spi_config *config) { - const struct spi_driver_api *api = config->dev->driver_api; + const struct spi_driver_api *api = dev->driver_api; - return api->release(config); + return api->release(dev, config); } #ifdef __cplusplus @@ -415,4 +417,3 @@ static inline int _impl_spi_release(struct spi_config *config) #include #endif /* __SPI_H__ */ -#endif /* CONFIG_SPI_LEGACY_API */ diff --git a/include/spi_legacy.h b/include/spi_legacy.h deleted file mode 100644 index 94fe8963b03d..000000000000 --- a/include/spi_legacy.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2015 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Public legacy API for SPI drivers and applications - */ - -#ifndef __SPI_LEGACY_H__ -#define __SPI_LEGACY_H__ - -/** - * @brief SPI Legacy interface - * @defgroup spi_interface_legacy SPI Interface - * @ingroup io_interfaces - * @{ - */ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief SPI Polarity & Phase Modes - */ -#define SPI_MODE_CPOL 0x1 -#define SPI_MODE_CPHA 0x2 -#define SPI_MODE_LOOP 0x4 - -#define SPI_MODE_MASK (0x7) -#define SPI_MODE(_in_) ((_in_) & SPI_MODE_MASK) - -/** - * @brief SPI Transfer modes (host controller dependent) - */ -#define SPI_TRANSFER_MSB (0 << 3) -#define SPI_TRANSFER_LSB (1 << 3) - -#define SPI_TRANSFER_MASK (0x8) - -#define SPI_WORD_SIZE_MASK (0xFF << 4) -#define SPI_WORD_SIZE_GET(_in_) (((_in_) & SPI_WORD_SIZE_MASK) >> 4) -#define SPI_WORD(_in_) ((_in_) << 4) - -/** - * @brief SPI configuration structure. - * - * config is a bit field with the following parts: - * mode [ 0 : 2 ] - Polarity, phase and loop mode. - * transfer_mode [ 3 ] - LSB or MSB first transfer mode. - * word_size [ 4 : 11 ] - Size of a data frame in bits. - * RESERVED [ 12 : 31 ] - Undefined or device-specific usage. - * - * max_sys_freq is the clock divider supported by the the host - * spi controller. - */ -struct spi_config { - u32_t config; - u32_t max_sys_freq; -}; - -/** - * @typedef spi_api_configure - * @brief Callback API upon configuring the const controller - * See spi_configure() for argument description - */ -typedef int (*spi_api_configure)(struct device *dev, - struct spi_config *config); -/** - * @typedef spi_api_slave_select - * @brief Callback API upon selecting a slave - * See spi_slave_select() for argument description - */ -typedef int (*spi_api_slave_select)(struct device *dev, u32_t slave); -/** - * @typedef spi_api_io - * @brief Callback API for I/O - * See spi_read() and spi_write() for argument descriptions - */ -typedef int (*spi_api_io)(struct device *dev, - const void *tx_buf, u32_t tx_buf_len, - void *rx_buf, u32_t rx_buf_len); - -struct spi_driver_api { - spi_api_configure configure; - spi_api_slave_select slave_select; - spi_api_io transceive; -}; - -/** - * @brief Configure a host controller for operating against slaves. - * @param dev Pointer to the device structure for the driver instance. - * @param config Pointer to the configuration provided by the application. - * - * @retval 0 If successful. - * @retval Negative errno code if failure. - */ -static inline int spi_configure(struct device *dev, - struct spi_config *config) -{ - const struct spi_driver_api *api = dev->driver_api; - - return api->configure(dev, config); -} - -/** - * @brief Select a slave to deal with. - * - * This routine is meaningful only if the controller supports per-slave - * addressing: One SS line per-slave. If not, this routine has no effect - * and daisy-chaining should be considered to deal with multiple slaves - * on the same line. - * - * @param dev Pointer to the device structure for the driver instance - * @param slave An integer identifying the slave. It starts from 1 which - * corresponds to cs0. - * - * @retval 0 If successful. - * @retval Negative errno code if failure. - */ -static inline int spi_slave_select(struct device *dev, u32_t slave) -{ - const struct spi_driver_api *api = dev->driver_api; - - if (!api->slave_select) { - return 0; - } - - return api->slave_select(dev, slave); -} - -/** - * @brief Read the specified amount of data from the SPI driver. - * @param dev Pointer to the device structure for the driver instance. - * @param buf Memory buffer where data will be transferred. - * @param len Size of the memory buffer available for writing. - * - * @retval 0 If successful. - * @retval Negative errno code if failure. - */ -static inline int spi_read(struct device *dev, void *buf, u32_t len) -{ - const struct spi_driver_api *api = dev->driver_api; - - return api->transceive(dev, NULL, 0, buf, len); -} - -/** - * @brief Write the specified amount of data from the SPI driver. - * @param dev Pointer to the device structure for the driver instance. - * @param buf Memory buffer from where data is transferred. - * @param len Size of the memory buffer available for reading. - * - * @retval 0 If successful. - * @retval Negative errno code if failure. - */ -static inline int spi_write(struct device *dev, const void *buf, u32_t len) -{ - const struct spi_driver_api *api = dev->driver_api; - - return api->transceive(dev, buf, len, NULL, 0); -} - -/** - * @brief Read and write the specified amount of data from the SPI driver. - * - * This routine is meant for full-duplex transmission. - * Only equal length is supported(tx_buf_len must be equal to rx_buf_len). - * - * @param dev Pointer to the device structure for the driver instance. - * @param tx_buf Memory buffer where data originates - * @param tx_buf_len Size of the memory buffer available for reading. - * @param rx_buf Memory buffer where data is transferred. - * @param rx_buf_len Size of the memory buffer available for writing. - * - * @retval 0 If successful. - * @retval Negative errno code if failure. - */ -static inline int spi_transceive(struct device *dev, - const void *tx_buf, u32_t tx_buf_len, - void *rx_buf, u32_t rx_buf_len) -{ - const struct spi_driver_api *api = dev->driver_api; - - return api->transceive(dev, tx_buf, tx_buf_len, rx_buf, rx_buf_len); -} - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __SPI_LEGACY_H__ */ diff --git a/samples/bluetooth/hci_spi/src/main.c b/samples/bluetooth/hci_spi/src/main.c index 2533fc1d6e87..6d491638eede 100644 --- a/samples/bluetooth/hci_spi/src/main.c +++ b/samples/bluetooth/hci_spi/src/main.c @@ -55,7 +55,18 @@ #define SPI_MAX_MSG_LEN 255 static u8_t rxmsg[SPI_MAX_MSG_LEN]; +static struct spi_buf rx; +const static struct spi_buf_set rx_bufs = { + .buffers = &rx, + .count = 1, +}; + static u8_t txmsg[SPI_MAX_MSG_LEN]; +static struct spi_buf tx; +const static struct spi_buf_set tx_bufs = { + .buffers = &tx, + .count = 1, +}; /* HCI buffer pools */ #define CMD_BUF_SIZE BT_BUF_RX_SIZE @@ -83,6 +94,9 @@ NET_BUF_POOL_DEFINE(acl_tx_pool, TX_BUF_COUNT, BT_BUF_ACL_SIZE, BT_BUF_USER_DATA_MIN, NULL); static struct device *spi_hci_dev; +static struct spi_config spi_cfg = { + .operation = SPI_WORD_SET(8), +}; static struct device *gpio_dev; static BT_STACK_NOINIT(bt_tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); static struct k_thread bt_tx_thread_data; @@ -92,11 +106,12 @@ static K_SEM_DEFINE(sem_spi_tx, 0, 1); static inline int spi_send(struct net_buf *buf) { - u8_t header_master[5] = { 0 }; - u8_t header_slave[5] = { READY_NOW, SANITY_CHECK, - 0x00, 0x00, 0x00 }; int ret; + txmsg[0] = READY_NOW; + txmsg[1] = SANITY_CHECK; + txmsg[2] = 0x00; + SYS_LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); @@ -118,22 +133,30 @@ static inline int spi_send(struct net_buf *buf) net_buf_unref(buf); return -EINVAL; } - header_slave[STATUS_HEADER_TOREAD] = buf->len; + + txmsg[STATUS_HEADER_TOREAD] = buf->len; + txmsg[4] = 0x00; + + tx.buf = txmsg; + tx.len = 5; + rx.buf = rxmsg; + rx.len = 5; gpio_pin_write(gpio_dev, GPIO_IRQ_PIN, 1); /* Coordinate transfer lock with the spi rx thread */ k_sem_take(&sem_spi_tx, K_FOREVER); do { - ret = spi_transceive(spi_hci_dev, header_slave, 5, - header_master, 5); + ret = spi_transceive(spi_hci_dev, &spi_cfg, &tx_bufs, &rx_bufs); if (ret < 0) { SYS_LOG_ERR("SPI transceive error: %d", ret); } - } while (header_master[STATUS_HEADER_READY] != SPI_READ); + } while (rxmsg[STATUS_HEADER_READY] != SPI_READ); + + tx.buf = buf->data; + tx.len = buf->len; - ret = spi_transceive(spi_hci_dev, buf->data, buf->len, - &rxmsg, buf->len); + ret = spi_write(spi_hci_dev, &spi_cfg, &tx_bufs); if (ret < 0) { SYS_LOG_ERR("SPI transceive error: %d", ret); } @@ -159,12 +182,17 @@ static void bt_tx_thread(void *p1, void *p2, void *p3) ARG_UNUSED(p2); ARG_UNUSED(p3); - memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN); + memset(txmsg, 0xFF, SPI_MAX_MSG_LEN); while (1) { + tx.buf = header_slave; + tx.len = 5; + rx.buf = header_master; + rx.len = 5; + do { - ret = spi_transceive(spi_hci_dev, header_slave, 5, - header_master, 5); + ret = spi_transceive(spi_hci_dev, &spi_cfg, + &tx_bufs, &rx_bufs); if (ret < 0) { SYS_LOG_ERR("SPI transceive error: %d", ret); } @@ -178,9 +206,14 @@ static void bt_tx_thread(void *p1, void *p2, void *p3) continue; } + tx.buf = txmsg; + tx.len = SPI_MAX_MSG_LEN; + rx.buf = rxmsg; + rx.len = SPI_MAX_MSG_LEN; + /* Receiving data from the SPI Host */ - ret = spi_transceive(spi_hci_dev, &txmsg, SPI_MAX_MSG_LEN, - &rxmsg, SPI_MAX_MSG_LEN); + ret = spi_transceive(spi_hci_dev, &spi_cfg, + &tx_bufs, &rx_bufs); if (ret < 0) { SYS_LOG_ERR("SPI transceive error: %d", ret); continue; @@ -240,10 +273,6 @@ static void bt_tx_thread(void *p1, void *p2, void *p3) static int hci_spi_init(struct device *unused) { - static struct spi_config btspi_config = { - .config = SPI_WORD(8), - }; - ARG_UNUSED(unused); SYS_LOG_DBG(""); @@ -253,10 +282,6 @@ static int hci_spi_init(struct device *unused) return -EINVAL; } - if (spi_configure(spi_hci_dev, &btspi_config) < 0) { - return -EINVAL; - } - gpio_dev = device_get_binding(GPIO_IRQ_DEV_NAME); if (!gpio_dev) { return -EINVAL; diff --git a/samples/drivers/led_lpd8806/prj.conf b/samples/drivers/led_lpd8806/prj.conf index 6583913a8164..8a63b87ada33 100644 --- a/samples/drivers/led_lpd8806/prj.conf +++ b/samples/drivers/led_lpd8806/prj.conf @@ -5,7 +5,6 @@ CONFIG_BOOT_BANNER=y CONFIG_POLL=y CONFIG_SPI=y -# CONFIG_SPI_LEGACY_API is not set CONFIG_LED_STRIP=y CONFIG_LPD880X_STRIP=y diff --git a/samples/drivers/led_ws2812/boards/96b_carbon.conf b/samples/drivers/led_ws2812/boards/96b_carbon.conf index 11feaf6e00c8..5b13dad19034 100644 --- a/samples/drivers/led_ws2812/boards/96b_carbon.conf +++ b/samples/drivers/led_ws2812/boards/96b_carbon.conf @@ -1,6 +1,5 @@ CONFIG_POLL=y CONFIG_SPI=y -# CONFIG_SPI_LEGACY_API is not set CONFIG_WS2812_STRIP=y CONFIG_WS2812_STRIP_SPI_DEV_NAME="ws2812_spi" diff --git a/samples/drivers/spi_fujitsu_fram/src/main.c b/samples/drivers/spi_fujitsu_fram/src/main.c index 3404ba047484..b2ec5c152e08 100644 --- a/samples/drivers/spi_fujitsu_fram/src/main.c +++ b/samples/drivers/spi_fujitsu_fram/src/main.c @@ -15,67 +15,102 @@ */ #define MB85RS64V_MANUFACTURER_ID_CMD 0x9f +#define MB85RS64V_WRITE_ENABLE_CMD 0x06 +#define MB85RS64V_READ_CMD 0x03 +#define MB85RS64V_WRITE_CMD 0x02 #define MAX_USER_DATA_LENGTH 1024 -static u8_t spi_buffer[MAX_USER_DATA_LENGTH + 3]; static u8_t data[MAX_USER_DATA_LENGTH], cmp_data[MAX_USER_DATA_LENGTH]; -static int mb85rs64v_read_id(struct device *dev) +static int mb85rs64v_access(struct device *spi, struct spi_config *spi_cfg, + u8_t cmd, u16_t addr, void *data, size_t len) { - int err; + u8_t access[3]; + struct spi_buf bufs[] = { + { + .buf = access, + }, + { + .buf = data, + .len = len + } + }; + struct spi_buf_set tx = { + .buffers = bufs + }; + + access[0] = cmd; + + if (cmd == MB85RS64V_WRITE_CMD || cmd == MB85RS64V_READ_CMD) { + access[1] = (addr >> 8) & 0xFF; + access[2] = addr & 0xFF; - spi_buffer[0] = MB85RS64V_MANUFACTURER_ID_CMD; + bufs[0].len = 3; + tx.count = 2; + + if (cmd == MB85RS64V_READ_CMD) { + struct spi_buf_set rx = { + .buffers = bufs, + .count = 2 + }; + + return spi_transceive(spi, spi_cfg, &tx, &rx); + } + } else { + tx.count = 1; + } + + return spi_write(spi, spi_cfg, &tx); +} + + +static int mb85rs64v_read_id(struct device *spi, struct spi_config *spi_cfg) +{ + u8_t id[4]; + int err; - err = spi_transceive(dev, spi_buffer, 5, spi_buffer, 5); + err = mb85rs64v_access(spi, spi_cfg, + MB85RS64V_MANUFACTURER_ID_CMD, 0, &id, 4); if (err) { printk("Error during ID read\n"); return -EIO; } - if (spi_buffer[1] != 0x04) { + if (id[0] != 0x04) { return -EIO; } - if (spi_buffer[2] != 0x7f) { + if (id[1] != 0x7f) { return -EIO; } - if (spi_buffer[3] != 0x03) { + if (id[2] != 0x03) { return -EIO; } - if (spi_buffer[4] != 0x02) { + if (id[3] != 0x02) { return -EIO; } return 0; } -static int write_bytes(struct device *dev, u16_t addr, - u8_t *data, u32_t num_bytes) +static int write_bytes(struct device *spi, struct spi_config *spi_cfg, + u16_t addr, u8_t *data, u32_t num_bytes) { int err; - /* write protect disable cmd */ - spi_buffer[0] = 0x06; - /* disable write protect */ - err = spi_write(dev, spi_buffer, 1); + err = mb85rs64v_access(spi, spi_cfg, + MB85RS64V_WRITE_ENABLE_CMD, 0, NULL, 0); if (err) { printk("unable to disable write protect\n"); return -EIO; } /* write cmd */ - spi_buffer[0] = 0x02; - spi_buffer[1] = (addr >> 8) & 0xFF; - spi_buffer[2] = addr & 0xFF; - - for (u32_t i = 0; i < num_bytes; i++) { - spi_buffer[i + 3] = data[i]; - } - - err = spi_write(dev, spi_buffer, num_bytes + 3); + err = mb85rs64v_access(spi, spi_cfg, + MB85RS64V_WRITE_CMD, addr, data, num_bytes); if (err) { printk("Error during SPI write\n"); return -EIO; @@ -84,59 +119,41 @@ static int write_bytes(struct device *dev, u16_t addr, return 0; } -static int read_bytes(struct device *dev, u16_t addr, - u8_t *data, u32_t num_bytes) +static int read_bytes(struct device *spi, struct spi_config *spi_cfg, + u16_t addr, u8_t *data, u32_t num_bytes) { int err; /* read cmd */ - spi_buffer[0] = 0x03; - spi_buffer[1] = (addr >> 8) & 0xFF; - spi_buffer[2] = addr & 0xFF; - - err = spi_transceive(dev, spi_buffer, num_bytes + 3, spi_buffer, - num_bytes + 3); + err = mb85rs64v_access(spi, spi_cfg, + MB85RS64V_READ_CMD, addr, data, num_bytes); if (err) { printk("Error during SPI read\n"); return -EIO; } - for (u32_t i = 0; i < num_bytes; i++) { - data[i] = spi_buffer[i + 3]; - } - return 0; } void main(void) { - struct spi_config config = { 0 }; - struct device *spi_mst_1 = device_get_binding(CONFIG_SPI_1_NAME); + struct device *spi; + struct spi_config spi_cfg; int err; printk("fujitsu FRAM example application\n"); - if (!spi_mst_1) { + spi = device_get_binding(CONFIG_SPI_1_NAME); + if (!spi) { printk("Could not find SPI driver\n"); return; } - config.config = SPI_WORD(8); - config.max_sys_freq = 256; + spi_cfg.operation = SPI_WORD_SET(8); + spi_cfg.frequency = 256000; - err = spi_configure(spi_mst_1, &config); - if (err) { - printk("SPI configuration failed\n"); - return; - } - - err = spi_slave_select(spi_mst_1, 2); - if (err) { - printk("SPI slave select failed\n"); - return; - } - err = mb85rs64v_read_id(spi_mst_1); + err = mb85rs64v_read_id(spi, &spi_cfg); if (err) { printk("Could not verify FRAM ID\n"); return; @@ -144,7 +161,7 @@ void main(void) /* Do one-byte read/write */ data[0] = 0xAE; - err = write_bytes(spi_mst_1, 0x00, data, 1); + err = write_bytes(spi, &spi_cfg, 0x00, data, 1); if (err) { printk("Error writing to FRAM! errro code (%d)\n", err); return; @@ -153,7 +170,7 @@ void main(void) } data[0] = 0x86; - err = write_bytes(spi_mst_1, 0x01, data, 1); + err = write_bytes(spi, &spi_cfg, 0x01, data, 1); if (err) { printk("Error writing to FRAM! error code (%d)\n", err); return; @@ -162,7 +179,7 @@ void main(void) } data[0] = 0x00; - err = read_bytes(spi_mst_1, 0x00, data, 1); + err = read_bytes(spi, &spi_cfg, 0x00, data, 1); if (err) { printk("Error reading from FRAM! error code (%d)\n", err); return; @@ -171,7 +188,7 @@ void main(void) } data[0] = 0x00; - err = read_bytes(spi_mst_1, 0x01, data, 1); + err = read_bytes(spi, &spi_cfg, 0x01, data, 1); if (err) { printk("Error reading from FRAM! error code (%d)\n", err); return; @@ -187,7 +204,7 @@ void main(void) } /* write them to the FRAM */ - err = write_bytes(spi_mst_1, 0x00, cmp_data, sizeof(cmp_data)); + err = write_bytes(spi, &spi_cfg, 0x00, cmp_data, sizeof(cmp_data)); if (err) { printk("Error writing to FRAM! error code (%d)\n", err); return; @@ -196,7 +213,7 @@ void main(void) (u32_t) sizeof(cmp_data)); } - err = read_bytes(spi_mst_1, 0x00, data, sizeof(data)); + err = read_bytes(spi, &spi_cfg, 0x00, data, sizeof(data)); if (err) { printk("Error reading from FRAM! error code (%d)\n", err); return; diff --git a/samples/sensor/bme280/sample.yaml b/samples/sensor/bme280/sample.yaml index 67ab7e5ae658..d6acb94e617b 100644 --- a/samples/sensor/bme280/sample.yaml +++ b/samples/sensor/bme280/sample.yaml @@ -9,5 +9,4 @@ tests: harness: sensor tags: samples sensor depends_on: spi - filter: CONFIG_SPI_LEGACY_API extra_args: "CONF_FILE=prj_spi.conf" diff --git a/samples/sensor/bmi160/sample.yaml b/samples/sensor/bmi160/sample.yaml index 6e0648f7323d..aec7454c6493 100644 --- a/samples/sensor/bmi160/sample.yaml +++ b/samples/sensor/bmi160/sample.yaml @@ -5,4 +5,3 @@ tests: harness: sensor tags: sensors depends_on: spi gpio - filter: CONFIG_SPI_LEGACY_API diff --git a/tests/drivers/spi/spi_basic_api/CMakeLists.txt b/tests/drivers/spi/spi_basic_api/CMakeLists.txt deleted file mode 100644 index 92a4288bc1d8..000000000000 --- a/tests/drivers/spi/spi_basic_api/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) -project(NONE) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/spi/spi_basic_api/prj.conf b/tests/drivers/spi/spi_basic_api/prj.conf deleted file mode 100644 index 336fa6acfcb7..000000000000 --- a/tests/drivers/spi/spi_basic_api/prj.conf +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_SPI=y -CONFIG_ZTEST=y diff --git a/tests/drivers/spi/spi_basic_api/src/main.c b/tests/drivers/spi/spi_basic_api/src/main.c deleted file mode 100644 index 736a52478ed6..000000000000 --- a/tests/drivers/spi/spi_basic_api/src/main.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @addtogroup t_driver_spi - * @{ - * @defgroup t_spi_basic test_spi_basic_operations - * @} - * - * Setup: Connect DUT MISO to DUT MOSI - * - * quark_se_c1000_devboard - x86 - * ---------------------- - * - * SPI_0_MISO - SPI_0_MOSI - * SPI_1_MISO - SPI_1_MOSI - * - * quark_se_c1000_ss_devboard - arc - * ---------------------- - * - * SPI_SS_0_MISO - SPI_SS_0_MOSI - * SPI_SS_1_MISO - SPI_SS_1_MOSI - * - * quark_d2000 - x86 - * ---------------------- - * - * SPI_M_MISO - SPI_M_MOSI - * - * arduino_101 - x86 - * ---------------------- - * - * SPI1_M_MISO - SPI1_M_MOSI - */ - -#include -#include - -void test_spi_cpol(void); -void test_spi_cpha(void); -void test_spi_cpol_cpha(void); - -void test_main(void) -{ - ztest_test_suite(spi_test, - ztest_unit_test(test_spi_cpol), - ztest_unit_test(test_spi_cpha), - ztest_unit_test(test_spi_cpol_cpha)); - ztest_run_test_suite(spi_test); -} diff --git a/tests/drivers/spi/spi_basic_api/src/test_spi.c b/tests/drivers/spi/spi_basic_api/src/test_spi.c deleted file mode 100644 index 3b06b76d0e32..000000000000 --- a/tests/drivers/spi/spi_basic_api/src/test_spi.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * @addtogroup t_spi_basic - * @{ - * @defgroup t_spi_basic_operations test_spi_basic_operation_mode - * @brief TestPurpose: verify SPI basic operations in different mode - * @} - */ - -#include -#include -#include - -#ifdef CONFIG_ARC -#define SPI_DEV_NAME CONFIG_SPI_SS_0_NAME -#else -#ifdef CONFIG_BOARD_ARDUINO_101 -#define SPI_DEV_NAME CONFIG_SPI_1_NAME -#else -#define SPI_DEV_NAME CONFIG_SPI_0_NAME -#endif -#endif - -#define SPI_SLAVE 1 -#define SPI_MAX_CLK_FREQ_250KHZ 128 - -static struct spi_config spi_conf = { - .config = SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD(8), - .max_sys_freq = SPI_MAX_CLK_FREQ_250KHZ, -}; - -static char *wbuf = "Hello world"; -static char rbuf[16] = {}; - -static int test_spi(u32_t mode) -{ - struct device *spi_dev = device_get_binding(SPI_DEV_NAME); - u32_t len = strlen(wbuf); - - if (!spi_dev) { - TC_PRINT("Cannot get SPI device\n"); - return TC_FAIL; - } - - spi_conf.config = mode | SPI_MODE_LOOP; - /* 1. verify spi_configure() */ - if (spi_configure(spi_dev, &spi_conf)) { - TC_PRINT("SPI config failed\n"); - return TC_FAIL; - } - - /* 2. verify spi_slave_select() */ - if (spi_slave_select(spi_dev, SPI_SLAVE)) { - TC_PRINT("SPI slave select failed\n"); - return TC_FAIL; - } - - /* 3. verify spi_write() */ - if (spi_write(spi_dev, wbuf, len) != 0) { - TC_PRINT("SPI write failed\n"); - return TC_FAIL; - } - - /* 4. verify spi_transceive() */ - TC_PRINT("SPI sent: %s\n", wbuf); - if (spi_transceive(spi_dev, wbuf, len, rbuf, len) != 0) { - TC_PRINT("SPI transceive failed\n"); - return TC_FAIL; - } - - TC_PRINT("SPI transceived: %s\n", rbuf); - - if (!strcmp(wbuf, rbuf)) { - return TC_PASS; - } else { - return TC_FAIL; - } -} - -void test_spi_cpol(void) -{ - TC_PRINT("Test SPI_MODE_CPOL\n"); - zassert_true(test_spi(SPI_WORD(8) | SPI_MODE_CPOL) == TC_PASS, NULL); -} - -void test_spi_cpha(void) -{ - TC_PRINT("Test SPI_MODE_CPHA\n"); - zassert_true(test_spi(SPI_WORD(8) | SPI_MODE_CPHA) == TC_PASS, NULL); -} - -void test_spi_cpol_cpha(void) -{ - TC_PRINT("Test SPI_MODE_CPOL | SPI_MODE_CPHA\n"); - zassert_true(test_spi(SPI_WORD(8) | SPI_MODE_CPOL | SPI_MODE_CPHA) - == TC_PASS, NULL); -} diff --git a/tests/drivers/spi/spi_basic_api/testcase.yaml b/tests/drivers/spi/spi_basic_api/testcase.yaml deleted file mode 100644 index 563e17d3704f..000000000000 --- a/tests/drivers/spi/spi_basic_api/testcase.yaml +++ /dev/null @@ -1,5 +0,0 @@ -tests: - test_spi: - platform_whitelist: quark_se_c1000_devboard quark_d2000_crb - galileo frdm_k64f - tags: apps diff --git a/tests/drivers/spi/spi_loopback/boards/frdm_k64f.conf b/tests/drivers/spi/spi_loopback/boards/frdm_k64f.conf new file mode 100644 index 000000000000..6dbfa010e7c9 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/frdm_k64f.conf @@ -0,0 +1,7 @@ +# +# Copyright (c) 2018, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SPI_LOOPBACK_DRV_NAME="SPI_0" diff --git a/tests/drivers/spi/spi_loopback/boards/nrf51_pca10028.conf b/tests/drivers/spi/spi_loopback/boards/nrf51_pca10028.conf new file mode 100644 index 000000000000..ec1df8268f57 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf51_pca10028.conf @@ -0,0 +1,12 @@ +CONFIG_SPI_NRFX=y +CONFIG_SPI_0=y +CONFIG_SPI_0_IRQ_PRI=1 +CONFIG_SPI_0_NRF_SPI=y +CONFIG_SPI_0_NRF_SCK_PIN=4 +CONFIG_SPI_0_NRF_MOSI_PIN=6 +CONFIG_SPI_0_NRF_MISO_PIN=5 + +CONFIG_SPI_LOOPBACK_DRV_NAME="SPI_0" +CONFIG_SPI_LOOPBACK_CS_GPIO=y +CONFIG_SPI_LOOPBACK_CS_CTRL_GPIO_DRV_NAME="GPIO_0" +CONFIG_SPI_LOOPBACK_CS_CTRL_GPIO_PIN=30 diff --git a/tests/drivers/spi/spi_loopback/boards/nrf52840_pca10056.conf b/tests/drivers/spi/spi_loopback/boards/nrf52840_pca10056.conf new file mode 100644 index 000000000000..d372b96d9185 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf52840_pca10056.conf @@ -0,0 +1,12 @@ +CONFIG_SPI_NRFX=y +CONFIG_SPI_2=y +CONFIG_SPI_2_IRQ_PRI=1 +CONFIG_SPI_2_NRF_SPI=y +CONFIG_SPI_2_NRF_SCK_PIN=29 +CONFIG_SPI_2_NRF_MOSI_PIN=31 +CONFIG_SPI_2_NRF_MISO_PIN=30 + +CONFIG_SPI_LOOPBACK_DRV_NAME="SPI_2" +CONFIG_SPI_LOOPBACK_CS_GPIO=y +CONFIG_SPI_LOOPBACK_CS_CTRL_GPIO_DRV_NAME="GPIO_0" +CONFIG_SPI_LOOPBACK_CS_CTRL_GPIO_PIN=26 diff --git a/tests/drivers/spi/spi_loopback/boards/nrf52_pca10040.conf b/tests/drivers/spi/spi_loopback/boards/nrf52_pca10040.conf new file mode 100644 index 000000000000..32ece01acc68 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf52_pca10040.conf @@ -0,0 +1,12 @@ +CONFIG_SPI_NRFX=y +CONFIG_SPI_1=y +CONFIG_SPI_1_IRQ_PRI=1 +CONFIG_SPI_1_NRF_SPI=y +CONFIG_SPI_1_NRF_SCK_PIN=29 +CONFIG_SPI_1_NRF_MOSI_PIN=31 +CONFIG_SPI_1_NRF_MISO_PIN=30 + +CONFIG_SPI_LOOPBACK_DRV_NAME="SPI_1" +CONFIG_SPI_LOOPBACK_CS_GPIO=y +CONFIG_SPI_LOOPBACK_CS_CTRL_GPIO_DRV_NAME="GPIO_0" +CONFIG_SPI_LOOPBACK_CS_CTRL_GPIO_PIN=26 diff --git a/tests/drivers/spi/spi_loopback/prj_base.conf b/tests/drivers/spi/spi_loopback/prj_base.conf index cbd1a7683555..d3955f338600 100644 --- a/tests/drivers/spi/spi_loopback/prj_base.conf +++ b/tests/drivers/spi/spi_loopback/prj_base.conf @@ -3,6 +3,6 @@ CONFIG_BOOT_BANNER=y CONFIG_BUILD_TIMESTAMP=y CONFIG_SYS_LOG=y CONFIG_SPI=y +CONFIG_SPI_ASYNC=y CONFIG_SYS_LOG_SPI_LEVEL=1 -CONFIG_SPI_LEGACY_API=n -CONFIG_POLL=y + diff --git a/tests/drivers/spi/spi_loopback/src/spi.c b/tests/drivers/spi/spi_loopback/src/spi.c index dc1359bec067..2bebae060317 100644 --- a/tests/drivers/spi/spi_loopback/src/spi.c +++ b/tests/drivers/spi/spi_loopback/src/spi.c @@ -51,7 +51,7 @@ static void to_display_format(const u8_t *src, size_t size, char *dst) } } -struct spi_config spi_slow = { +struct spi_config spi_cfg_slow = { .frequency = SLOW_FREQ, .operation = SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE, @@ -59,7 +59,7 @@ struct spi_config spi_slow = { .cs = SPI_CS, }; -struct spi_config spi_fast = { +struct spi_config spi_cfg_fast = { .frequency = FAST_FREQ, .operation = SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE, @@ -67,21 +67,20 @@ struct spi_config spi_fast = { .cs = SPI_CS, }; -static int cs_ctrl_gpio_config(struct spi_cs_control *cs) +#if defined(CONFIG_SPI_LOOPBACK_CS_GPIO) +static int cs_ctrl_gpio_config(void) { - if (cs) { - cs->gpio_dev = device_get_binding(CS_CTRL_GPIO_DRV_NAME); - if (!cs->gpio_dev) { - SYS_LOG_ERR("Cannot find %s!\n", - CS_CTRL_GPIO_DRV_NAME); - return -1; - } + spi_cs.gpio_dev = device_get_binding(CS_CTRL_GPIO_DRV_NAME); + if (!spi_cs.gpio_dev) { + SYS_LOG_ERR("Cannot find %s!", CS_CTRL_GPIO_DRV_NAME); + return -1; } return 0; } +#endif /* CONFIG_SPI_LOOPBACK_CS_GPIO */ -static int spi_complete_loop(struct spi_config *spi_conf) +static int spi_complete_loop(struct device *dev, struct spi_config *spi_conf) { const struct spi_buf tx_bufs[] = { { @@ -89,18 +88,26 @@ static int spi_complete_loop(struct spi_config *spi_conf) .len = BUF_SIZE, }, }; - struct spi_buf rx_bufs[] = { + const struct spi_buf rx_bufs[] = { { .buf = buffer_rx, .len = BUF_SIZE, }, }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs) + }; + int ret; SYS_LOG_INF("Start"); - ret = spi_transceive(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs), - rx_bufs, ARRAY_SIZE(rx_bufs)); + ret = spi_transceive(dev, spi_conf, &tx, &rx); if (ret) { SYS_LOG_ERR("Code %d", ret); return ret; @@ -121,7 +128,7 @@ static int spi_complete_loop(struct spi_config *spi_conf) return 0; } -static int spi_rx_half_start(struct spi_config *spi_conf) +static int spi_rx_half_start(struct device *dev, struct spi_config *spi_conf) { const struct spi_buf tx_bufs[] = { { @@ -129,20 +136,27 @@ static int spi_rx_half_start(struct spi_config *spi_conf) .len = BUF_SIZE, }, }; - struct spi_buf rx_bufs[] = { + const struct spi_buf rx_bufs[] = { { .buf = buffer_rx, .len = 8, }, }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs) + }; int ret; SYS_LOG_INF("Start"); memset(buffer_rx, 0, BUF_SIZE); - ret = spi_transceive(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs), - rx_bufs, ARRAY_SIZE(rx_bufs)); + ret = spi_transceive(dev, spi_conf, &tx, &rx); if (ret) { SYS_LOG_ERR("Code %d", ret); return -1; @@ -163,7 +177,7 @@ static int spi_rx_half_start(struct spi_config *spi_conf) return 0; } -static int spi_rx_half_end(struct spi_config *spi_conf) +static int spi_rx_half_end(struct device *dev, struct spi_config *spi_conf) { const struct spi_buf tx_bufs[] = { { @@ -171,7 +185,7 @@ static int spi_rx_half_end(struct spi_config *spi_conf) .len = BUF_SIZE, }, }; - struct spi_buf rx_bufs[] = { + const struct spi_buf rx_bufs[] = { { .buf = NULL, .len = 8, @@ -181,14 +195,21 @@ static int spi_rx_half_end(struct spi_config *spi_conf) .len = 8, }, }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs) + }; int ret; SYS_LOG_INF("Start"); memset(buffer_rx, 0, BUF_SIZE); - ret = spi_transceive(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs), - rx_bufs, ARRAY_SIZE(rx_bufs)); + ret = spi_transceive(dev, spi_conf, &tx, &rx); if (ret) { SYS_LOG_ERR("Code %d", ret); return -1; @@ -209,7 +230,7 @@ static int spi_rx_half_end(struct spi_config *spi_conf) return 0; } -static int spi_rx_every_4(struct spi_config *spi_conf) +static int spi_rx_every_4(struct device *dev, struct spi_config *spi_conf) { const struct spi_buf tx_bufs[] = { { @@ -217,7 +238,7 @@ static int spi_rx_every_4(struct spi_config *spi_conf) .len = BUF_SIZE, }, }; - struct spi_buf rx_bufs[] = { + const struct spi_buf rx_bufs[] = { { .buf = NULL, .len = 4, @@ -235,14 +256,21 @@ static int spi_rx_every_4(struct spi_config *spi_conf) .len = 4, }, }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs) + }; int ret; SYS_LOG_INF("Start"); memset(buffer_rx, 0, BUF_SIZE); - ret = spi_transceive(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs), - rx_bufs, ARRAY_SIZE(rx_bufs)); + ret = spi_transceive(dev, spi_conf, &tx, &rx); if (ret) { SYS_LOG_ERR("Code %d", ret); return -1; @@ -298,7 +326,7 @@ static void spi_async_call_cb(struct k_poll_event *async_evt, } } -static int spi_async_call(struct spi_config *spi_conf) +static int spi_async_call(struct device *dev, struct spi_config *spi_conf) { const struct spi_buf tx_bufs[] = { { @@ -306,18 +334,25 @@ static int spi_async_call(struct spi_config *spi_conf) .len = BUF_SIZE, }, }; - struct spi_buf rx_bufs[] = { + const struct spi_buf rx_bufs[] = { { .buf = buffer_rx, .len = BUF_SIZE, }, }; + const struct spi_buf_set tx = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs) + }; + const struct spi_buf_set rx = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs) + }; int ret; SYS_LOG_INF("Start"); - ret = spi_transceive_async(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs), - rx_bufs, ARRAY_SIZE(rx_bufs), &async_sig); + ret = spi_transceive_async(dev, spi_conf, &tx, &rx, &async_sig); if (ret == -ENOTSUP) { SYS_LOG_DBG("Not supported"); return 0; @@ -340,21 +375,23 @@ static int spi_async_call(struct spi_config *spi_conf) return 0; } -static int spi_resource_lock_test(struct spi_config *spi_conf_lock, - struct spi_config *spi_conf_try) +static int spi_resource_lock_test(struct device *lock_dev, + struct spi_config *spi_conf_lock, + struct device *try_dev, + struct spi_config *spi_conf_try) { spi_conf_lock->operation |= SPI_LOCK_ON; - if (spi_complete_loop(spi_conf_lock)) { + if (spi_complete_loop(lock_dev, spi_conf_lock)) { return -1; } - if (spi_release(spi_conf_lock)) { + if (spi_release(lock_dev, spi_conf_lock)) { SYS_LOG_ERR("Deadlock now?"); return -1; } - if (spi_complete_loop(spi_conf_try)) { + if (spi_complete_loop(try_dev, spi_conf_try)) { return -1; } @@ -365,44 +402,48 @@ void main(void) { struct k_thread async_thread; k_tid_t async_thread_id; + struct device *spi_slow; + struct device *spi_fast; SYS_LOG_INF("SPI test on buffers TX/RX %p/%p", buffer_tx, buffer_rx); - if (cs_ctrl_gpio_config(spi_slow.cs) || - cs_ctrl_gpio_config(spi_fast.cs)) { +#if defined(CONFIG_SPI_LOOPBACK_CS_GPIO) + if (cs_ctrl_gpio_config()) { return; } +#endif /* CONFIG_SPI_LOOPBACK_CS_GPIO */ - spi_slow.dev = device_get_binding(SPI_DRV_NAME); - if (!spi_slow.dev) { + spi_slow = device_get_binding(SPI_DRV_NAME); + if (!spi_slow) { SYS_LOG_ERR("Cannot find %s!\n", SPI_DRV_NAME); return; } - spi_fast.dev = spi_slow.dev; + spi_fast = spi_slow; async_thread_id = k_thread_create(&async_thread, spi_async_stack, 256, (k_thread_entry_t)spi_async_call_cb, &async_evt, &caller, NULL, K_PRIO_COOP(7), 0, 0); - if (spi_complete_loop(&spi_slow) || - spi_rx_half_start(&spi_slow) || - spi_rx_half_end(&spi_slow) || - spi_rx_every_4(&spi_slow) || - spi_async_call(&spi_slow)) { + if (spi_complete_loop(spi_slow, &spi_cfg_slow) || + spi_rx_half_start(spi_slow, &spi_cfg_slow) || + spi_rx_half_end(spi_slow, &spi_cfg_slow) || + spi_rx_every_4(spi_slow, &spi_cfg_slow) || + spi_async_call(spi_slow, &spi_cfg_slow)) { goto end; } - if (spi_complete_loop(&spi_fast) || - spi_rx_half_start(&spi_fast) || - spi_rx_half_end(&spi_fast) || - spi_rx_every_4(&spi_fast) || - spi_async_call(&spi_fast)) { + if (spi_complete_loop(spi_fast, &spi_cfg_fast) || + spi_rx_half_start(spi_fast, &spi_cfg_fast) || + spi_rx_half_end(spi_fast, &spi_cfg_fast) || + spi_rx_every_4(spi_fast, &spi_cfg_fast) || + spi_async_call(spi_fast, &spi_cfg_fast)) { goto end; } - if (spi_resource_lock_test(&spi_slow, &spi_fast)) { + if (spi_resource_lock_test(spi_slow, &spi_cfg_slow, + spi_fast, &spi_cfg_fast)) { goto end; } diff --git a/tests/drivers/spi/spi_loopback/testcase.yaml b/tests/drivers/spi/spi_loopback/testcase.yaml index e735be965337..09c4e7a483b2 100644 --- a/tests/drivers/spi/spi_loopback/testcase.yaml +++ b/tests/drivers/spi/spi_loopback/testcase.yaml @@ -3,4 +3,3 @@ tests: depends_on: spi tags: drivers spi harness: loopback - platform_exclude: quark_se_c1000_ss_devboard arduino_101_sss