You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2021/03/01 21:22:47 UTC
[GitHub] [mynewt-core] wes3 commented on a change in pull request #2450: add da1469x SPI bus driver
wes3 commented on a change in pull request #2450:
URL: https://github.com/apache/mynewt-core/pull/2450#discussion_r584994346
##########
File path: hw/bus/drivers/spi_da1469x/src/spi_da1469x.c
##########
@@ -0,0 +1,665 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <mcu/da1469x_pd.h>
+#include "defs/error.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/bus_driver.h"
+#include "bus/drivers/spi_common.h"
+#include "mcu/mcu.h"
+#include "mcu/da1469x_dma.h"
+
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+#include "stats/stats.h"
+#endif
+
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+STATS_SECT_START(spi_da1469x_stats_section)
+ STATS_SECT_ENTRY(read_bytes)
+ STATS_SECT_ENTRY(written_bytes)
+ STATS_SECT_ENTRY(dma_transferred_bytes)
+STATS_SECT_END
+
+STATS_NAME_START(spi_da1469x_stats_section)
+ STATS_NAME(spi_da1469x_stats_section, read_bytes)
+ STATS_NAME(spi_da1469x_stats_section, written_bytes)
+ STATS_NAME(spi_da1469x_stats_section, dma_transferred_bytes)
+STATS_NAME_END(spi_da1469x_stats_section)
+#endif
+
+#define SPI_COUNT 2
+/* Minimum transfer size when DMA should be used, for shorter transfers
+ * interrupts are used
+ */
+#define MIN_DMA_SIZE 8
+
+static uint32_t dma_dummy_dst;
+
+static const struct da1469x_dma_config spi_write_rx_dma_cfg = {
+ .priority = 0,
+ .burst_mode = MCU_DMA_BURST_MODE_DISABLED,
+ .bus_width = MCU_DMA_BUS_WIDTH_1B,
+ .dst_inc = false,
+ .src_inc = false,
+};
+
+static const struct da1469x_dma_config spi_write_tx_dma_cfg = {
+ .priority = 0,
+ .burst_mode = MCU_DMA_BURST_MODE_DISABLED,
+ .bus_width = MCU_DMA_BUS_WIDTH_1B,
+ .dst_inc = false,
+ .src_inc = true,
+};
+
+static const struct da1469x_dma_config spi_read_rx_dma_cfg = {
+ .priority = 0,
+ .burst_mode = MCU_DMA_BURST_MODE_DISABLED,
+ .bus_width = MCU_DMA_BUS_WIDTH_1B,
+ .dst_inc = true,
+ .src_inc = false,
+};
+
+static const struct da1469x_dma_config spi_read_tx_dma_cfg = {
+ .priority = 0,
+ .burst_mode = MCU_DMA_BURST_MODE_DISABLED,
+ .bus_width = MCU_DMA_BUS_WIDTH_1B,
+ .dst_inc = false,
+ .src_inc = false,
+};
+
+static void spi_da1469x_spi0_isr(void);
+static void spi_da1469x_spi1_isr(void);
+
+struct da1469x_spi_hw {
+ SPI_Type *regs;
+ uint8_t sck_func;
+ uint8_t mosi_func;
+ uint8_t miso_func;
+ IRQn_Type irqn;
+ /* DMA peripheral index */
+ uint8_t dma_periph;
+ /* Bit number for clock selection in CLK_COM_REG */
+ uint8_t clk_src_bit;
+ /* Bit number for clock enable in CLK_COM_REG */
+ uint8_t clk_ena_bit;
+ void (* isr)(void);
+};
+
+static const struct da1469x_spi_hw da1469x_spi = {
+ .regs = (void *)SPI_BASE,
+ .sck_func = MCU_GPIO_FUNC_SPI_CLK,
+ .mosi_func = MCU_GPIO_FUNC_SPI_DO,
+ .miso_func = MCU_GPIO_FUNC_SPI_DI,
+ .irqn = SPI_IRQn,
+ .dma_periph = MCU_DMA_PERIPH_SPI,
+ .clk_src_bit = CRG_COM_CLK_COM_REG_SPI_CLK_SEL_Pos,
+ .clk_ena_bit = CRG_COM_CLK_COM_REG_SPI_ENABLE_Pos,
+ .isr = spi_da1469x_spi0_isr,
+};
+
+static const struct da1469x_spi_hw da1469x_spi2 = {
+ .regs = (void *)SPI2_BASE,
+ .sck_func = MCU_GPIO_FUNC_SPI2_CLK,
+ .mosi_func = MCU_GPIO_FUNC_SPI2_DO,
+ .miso_func = MCU_GPIO_FUNC_SPI2_DI,
+ .irqn = SPI2_IRQn,
+ .dma_periph = MCU_DMA_PERIPH_SPI2,
+ .clk_src_bit = CRG_COM_CLK_COM_REG_SPI2_CLK_SEL_Pos,
+ .clk_ena_bit = CRG_COM_CLK_COM_REG_SPI2_ENABLE_Pos,
+ .isr = spi_da1469x_spi1_isr,
+};
+
+struct da1469x_transfer {
+ /* Transmit or receive buffer */
+ uint8_t *data;
+ /* Transfer length */
+ uint16_t len;
+ /* Number of bytes written to output FIFO */
+ uint16_t wlen;
+ /* Number of bytes read from input FIFO */
+ uint16_t rlen;
+
+ uint8_t nostop : 1;
+ /* Current transfer is for write */
+ uint8_t write : 1;
+ /* DMA is used for current transfer */
+ uint8_t dma : 1;
+ /* Transfer started */
+ uint8_t started : 1;
+};
+
+struct spi_da1469x_driver_data {
+ struct bus_spi_dev *dev;
+ const struct da1469x_spi_hw *hw;
+ /* Semaphore used for end of transfer completion notification */
+ struct os_sem sem;
+ struct da1469x_dma_regs *dma_chans[2];
+ struct da1469x_transfer transfer;
+
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+ STATS_SECT_DECL(spi_da1469x_stats_section) stats;
+#endif
+};
+
+static struct spi_da1469x_driver_data spi_dev_data_0;
+static struct spi_da1469x_driver_data spi_dev_data_1;
+
+static inline struct spi_da1469x_driver_data *
+driver_data(struct bus_spi_dev *dev)
+{
+ if (MYNEWT_VAL(SPI_0_MASTER) && dev->cfg.spi_num == 0) {
+ return &spi_dev_data_0;
+ } else if (MYNEWT_VAL(SPI_1_MASTER) && dev->cfg.spi_num == 1) {
+ return &spi_dev_data_1;
+ } else {
+ assert(0);
+ return NULL;
+ }
+}
+
+static void
+spi_da1469x_int_clear(SPI_Type *regs)
+{
+ regs->SPI_CLEAR_INT_REG = 0;
+}
+
+static void
+spi_da1469x_int_enable(SPI_Type *regs)
+{
+ regs->SPI_CTRL_REG |= SPI_SPI_CTRL_REG_SPI_MINT_Msk;
+}
+
+static void
+spi_da1469x_int_disable(SPI_Type *regs)
+{
+ regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_MINT_Msk;
+}
+
+static int
+spi_da1469x_dma_done_cb(void *arg)
+{
+ struct spi_da1469x_driver_data *dd = (struct spi_da1469x_driver_data *)arg;
+ struct da1469x_transfer *transfer;
+ int transferred;
+
+ transfer = &dd->transfer;
+ if (transfer->started) {
+ transfer->started = 0;
+ transferred = (int)(dd->dma_chans[0]->DMA_IDX_REG + 1);
+
+ transfer->wlen += transferred;
+ transfer->rlen += transferred;
+
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+ if (transfer->write) {
+ STATS_INCN(dd->stats, written_bytes, transferred);
+ } else {
+ STATS_INCN(dd->stats, read_bytes, transferred);
+ }
+ STATS_INCN(dd->stats, dma_transferred_bytes, transferred);
+#endif
+
+ os_sem_release(&dd->sem);
+ }
+
+ return 0;
+}
+
+static void
+spi_da1469x_isr(SPI_Type *regs, struct spi_da1469x_driver_data *dd)
+{
+ struct da1469x_transfer *transfer = &dd->transfer;
+ uint8_t rx_byte;
+
+ while ((transfer->wlen < transfer->len) &&
+ !(regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_TXH_Msk)) {
+ if (transfer->write) {
+ regs->SPI_RX_TX_REG = transfer->data[transfer->wlen];
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+ STATS_INC(dd->stats, written_bytes);
+#endif
+ } else {
+ regs->SPI_RX_TX_REG = 0xFF;
+ }
+ transfer->wlen++;
+ }
+
+ if (transfer->wlen == transfer->len) {
+ regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_TX_FIFO_NOTFULL_MASK_Msk;
+ }
+
+ while (0 != (regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_INT_BIT_Msk)) {
+ rx_byte = regs->SPI_RX_TX_REG;
+ if (transfer->rlen < transfer->len) {
+ if (!transfer->write) {
+ transfer->data[transfer->rlen] = rx_byte;
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+ STATS_INC(dd->stats, read_bytes);
+#endif
+ }
+ transfer->rlen++;
+ }
+ regs->SPI_CLEAR_INT_REG = 1;
+ }
+
+ if (transfer->started && transfer->rlen == transfer->len) {
+ spi_da1469x_int_disable(regs);
+ transfer->started = 0;
+ assert(os_sem_get_count(&dd->sem) == 0);
+ os_sem_release(&dd->sem);
+ }
+}
+
+static void
+spi_da1469x_spi0_isr(void)
+{
+ os_trace_isr_enter();
+
+ spi_da1469x_isr((SPI_Type *)SPI, &spi_dev_data_0);
+
+ os_trace_isr_exit();
+}
+
+static void
+spi_da1469x_spi1_isr(void)
+{
+ os_trace_isr_enter();
+
+ spi_da1469x_isr((SPI_Type *)SPI2, &spi_dev_data_1);
+
+ os_trace_isr_exit();
+}
+
+static int
+spi_da1469x_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+ struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+ struct bus_spi_node_cfg *cfg = arg;
+ (void)bdev;
+
+ BUS_DEBUG_POISON_NODE(node);
+
+ node->pin_cs = cfg->pin_cs;
+ node->freq = cfg->freq;
+ node->quirks = cfg->quirks;
+ node->data_order = cfg->data_order;
+ node->mode = cfg->mode;
+
+ if (node->pin_cs >= 0) {
+ hal_gpio_init_out(node->pin_cs, 1);
+ }
+
+ return 0;
+}
+
+static int
+spi_da1469x_disable(struct bus_dev *bdev)
+{
+ struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+ struct spi_da1469x_driver_data *dd;
+ SPI_Type *regs;
+
+ BUS_DEBUG_VERIFY_DEV(dev);
+
+ dd = driver_data(dev);
+ regs = dd->hw->regs;
+
+ /* Turn off SPI. */
+ regs->SPI_CTRL_REG &= ~(1U << SPI_SPI_CTRL_REG_SPI_ON_Pos);
+
+ if (dd->dma_chans[0] != NULL) {
+ da1469x_dma_release_channel(dd->dma_chans[0]);
+ dd->dma_chans[0] = NULL;
+ dd->dma_chans[1] = NULL;
+ }
+
+ /*
+ * Domain COM can be powered off, register content can be lost prepare
+ * to set it from scratch.
+ */
+ bdev->configured_for = NULL;
+
+ da1469x_pd_release(MCU_PD_DOMAIN_COM);
+
+ return 0;
+}
+
+static int
+spi_da1469x_enable(struct bus_dev *bdev)
+{
+ struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+ const struct da1469x_spi_hw *spi_hw;
+ struct spi_da1469x_driver_data *dd;
+ SPI_Type *regs;
+
+ BUS_DEBUG_VERIFY_DEV(dev);
+
+ dd = driver_data(dev);
+ spi_hw = dd->hw;
+ regs = spi_hw->regs;
+
+ da1469x_pd_acquire(MCU_PD_DOMAIN_COM);
+
+ /* Enable clock */
+ CRG_COM->SET_CLK_COM_REG = (1U << spi_hw->clk_ena_bit);
+
+ regs->SPI_CTRL_REG |= (1U << SPI_SPI_CTRL_REG_SPI_ON_Pos);
+ spi_da1469x_int_clear(spi_hw->regs);
+
+ da1469x_dma_acquire_periph(-1, spi_hw->dma_periph, dd->dma_chans);
+
+ if (dd->dma_chans[0] != NULL) {
+ dd->dma_chans[0]->DMA_A_START_REG = (uint32_t)®s->SPI_RX_TX_REG;
+ dd->dma_chans[1]->DMA_B_START_REG = (uint32_t)®s->SPI_RX_TX_REG;
+ }
+
+ return 0;
+}
+
+static int
+spi_da1469x_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+ struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+ struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+ struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+ struct spi_da1469x_driver_data *dd;
+ SPI_Type *regs;
+ uint32_t ctrl_reg;
+ int rc = 0;
+
+ BUS_DEBUG_VERIFY_DEV(dev);
+ BUS_DEBUG_VERIFY_NODE(node);
+
+ dd = driver_data(dev);
+ regs = dd->hw->regs;
+
+ ctrl_reg = regs->SPI_CTRL_REG;
+ if (ctrl_reg & SPI_SPI_CTRL_REG_SPI_ON_Msk) {
+ regs->SPI_CTRL_REG = ctrl_reg ^ (SPI_SPI_CTRL_REG_SPI_ON_Msk);
+ }
+
+ if (current_node && (current_node->freq == node->freq) && current_node->mode == node->mode) {
+ goto end;
+ }
+
+ ctrl_reg &= ~(SPI_SPI_CTRL_REG_SPI_TX_FIFO_NOTFULL_MASK_Msk |
+ SPI_SPI_CTRL_REG_SPI_DMA_TXREQ_MODE_Msk |
+ SPI_SPI_CTRL_REG_SPI_9BIT_VAL_Msk |
+ SPI_SPI_CTRL_REG_SPI_PRIORITY_Msk |
+ SPI_SPI_CTRL_REG_SPI_FIFO_MODE_Msk |
+ SPI_SPI_CTRL_REG_SPI_EN_CTRL_Msk |
+ SPI_SPI_CTRL_REG_SPI_MINT_Msk |
+ SPI_SPI_CTRL_REG_SPI_FORCE_DO_Msk |
+ SPI_SPI_CTRL_REG_SPI_WORD_Msk |
+ SPI_SPI_CTRL_REG_SPI_RST_Msk |
+ SPI_SPI_CTRL_REG_SPI_SMN_Msk |
+ SPI_SPI_CTRL_REG_SPI_DO_Msk |
+ SPI_SPI_CTRL_REG_SPI_CLK_Msk |
+ SPI_SPI_CTRL_REG_SPI_POL_Msk |
+ SPI_SPI_CTRL_REG_SPI_PHA_Msk);
+
+ if (node->freq < 4000) {
+ /* Slowest possibly clock, divider 14, 2.28MHz */
+ ctrl_reg |= (3U << SPI_SPI_CTRL_REG_SPI_CLK_Pos);
+ } else if (node->freq < 8000) {
+ ctrl_reg |= (0U << SPI_SPI_CTRL_REG_SPI_CLK_Pos);
+ } else if (node->freq < 16000) {
+ ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_CLK_Pos);
+ } else {
+ ctrl_reg |= (2U << SPI_SPI_CTRL_REG_SPI_CLK_Pos);
+ }
+
+ switch (node->mode) {
+ case BUS_SPI_MODE_0:
+ /* Bits already zeroed */
+ break;
+ case BUS_SPI_MODE_1:
+ ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_PHA_Pos);
+ break;
+ case BUS_SPI_MODE_2:
+ ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_POL_Pos);
+ break;
+ case BUS_SPI_MODE_3:
+ ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_PHA_Pos) |
+ (1U << SPI_SPI_CTRL_REG_SPI_POL_Pos);
+ break;
+ default:
+ assert(0);
+ }
+
+ regs->SPI_CTRL_REG = ctrl_reg;
+ /* At this point interrupt is cleared, FIFO is enabled, controller is disabled */
+end:
+ return rc;
+}
+
+static int
+spi_da1469x_read(struct bus_dev *bdev, struct bus_node *bnode,
+ uint8_t *buf, uint16_t length, os_time_t timeout,
+ uint16_t flags)
+{
+ static uint16_t mosi_data = 0xFFFF;
Review comment:
Another minor comment: I have never been a fan of declaring static locals as I feel it hides the global data usage. I noticed in the write function there is a global variable for dma_dummy_dst but in this function you made it local and they both seem to sort of serve the same purpose (if you know what I mean). One other question: is there any reason you set this to 0xFFFF? I presume the actual value is meaningless and can be anything. If this was a global in .bss it would be zero and then no need to initialize :-)
##########
File path: hw/bus/drivers/spi_da1469x/src/spi_da1469x.c
##########
@@ -0,0 +1,665 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <mcu/da1469x_pd.h>
+#include "defs/error.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/bus_driver.h"
+#include "bus/drivers/spi_common.h"
+#include "mcu/mcu.h"
+#include "mcu/da1469x_dma.h"
+
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+#include "stats/stats.h"
+#endif
+
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+STATS_SECT_START(spi_da1469x_stats_section)
+ STATS_SECT_ENTRY(read_bytes)
+ STATS_SECT_ENTRY(written_bytes)
+ STATS_SECT_ENTRY(dma_transferred_bytes)
+STATS_SECT_END
+
+STATS_NAME_START(spi_da1469x_stats_section)
+ STATS_NAME(spi_da1469x_stats_section, read_bytes)
+ STATS_NAME(spi_da1469x_stats_section, written_bytes)
+ STATS_NAME(spi_da1469x_stats_section, dma_transferred_bytes)
+STATS_NAME_END(spi_da1469x_stats_section)
+#endif
+
+#define SPI_COUNT 2
+/* Minimum transfer size when DMA should be used, for shorter transfers
+ * interrupts are used
+ */
+#define MIN_DMA_SIZE 8
+
+static uint32_t dma_dummy_dst;
+
+static const struct da1469x_dma_config spi_write_rx_dma_cfg = {
+ .priority = 0,
+ .burst_mode = MCU_DMA_BURST_MODE_DISABLED,
+ .bus_width = MCU_DMA_BUS_WIDTH_1B,
+ .dst_inc = false,
+ .src_inc = false,
+};
+
+static const struct da1469x_dma_config spi_write_tx_dma_cfg = {
+ .priority = 0,
+ .burst_mode = MCU_DMA_BURST_MODE_DISABLED,
+ .bus_width = MCU_DMA_BUS_WIDTH_1B,
+ .dst_inc = false,
+ .src_inc = true,
+};
+
+static const struct da1469x_dma_config spi_read_rx_dma_cfg = {
+ .priority = 0,
+ .burst_mode = MCU_DMA_BURST_MODE_DISABLED,
+ .bus_width = MCU_DMA_BUS_WIDTH_1B,
+ .dst_inc = true,
+ .src_inc = false,
+};
+
+static const struct da1469x_dma_config spi_read_tx_dma_cfg = {
+ .priority = 0,
+ .burst_mode = MCU_DMA_BURST_MODE_DISABLED,
+ .bus_width = MCU_DMA_BUS_WIDTH_1B,
+ .dst_inc = false,
+ .src_inc = false,
+};
+
+static void spi_da1469x_spi0_isr(void);
+static void spi_da1469x_spi1_isr(void);
+
+struct da1469x_spi_hw {
+ SPI_Type *regs;
+ uint8_t sck_func;
+ uint8_t mosi_func;
+ uint8_t miso_func;
+ IRQn_Type irqn;
+ /* DMA peripheral index */
+ uint8_t dma_periph;
+ /* Bit number for clock selection in CLK_COM_REG */
+ uint8_t clk_src_bit;
+ /* Bit number for clock enable in CLK_COM_REG */
+ uint8_t clk_ena_bit;
+ void (* isr)(void);
+};
+
+static const struct da1469x_spi_hw da1469x_spi = {
+ .regs = (void *)SPI_BASE,
+ .sck_func = MCU_GPIO_FUNC_SPI_CLK,
+ .mosi_func = MCU_GPIO_FUNC_SPI_DO,
+ .miso_func = MCU_GPIO_FUNC_SPI_DI,
+ .irqn = SPI_IRQn,
+ .dma_periph = MCU_DMA_PERIPH_SPI,
+ .clk_src_bit = CRG_COM_CLK_COM_REG_SPI_CLK_SEL_Pos,
+ .clk_ena_bit = CRG_COM_CLK_COM_REG_SPI_ENABLE_Pos,
+ .isr = spi_da1469x_spi0_isr,
+};
+
+static const struct da1469x_spi_hw da1469x_spi2 = {
+ .regs = (void *)SPI2_BASE,
+ .sck_func = MCU_GPIO_FUNC_SPI2_CLK,
+ .mosi_func = MCU_GPIO_FUNC_SPI2_DO,
+ .miso_func = MCU_GPIO_FUNC_SPI2_DI,
+ .irqn = SPI2_IRQn,
+ .dma_periph = MCU_DMA_PERIPH_SPI2,
+ .clk_src_bit = CRG_COM_CLK_COM_REG_SPI2_CLK_SEL_Pos,
+ .clk_ena_bit = CRG_COM_CLK_COM_REG_SPI2_ENABLE_Pos,
+ .isr = spi_da1469x_spi1_isr,
+};
+
+struct da1469x_transfer {
+ /* Transmit or receive buffer */
+ uint8_t *data;
+ /* Transfer length */
+ uint16_t len;
+ /* Number of bytes written to output FIFO */
+ uint16_t wlen;
+ /* Number of bytes read from input FIFO */
+ uint16_t rlen;
+
+ uint8_t nostop : 1;
+ /* Current transfer is for write */
+ uint8_t write : 1;
+ /* DMA is used for current transfer */
+ uint8_t dma : 1;
+ /* Transfer started */
+ uint8_t started : 1;
+};
+
+struct spi_da1469x_driver_data {
+ struct bus_spi_dev *dev;
+ const struct da1469x_spi_hw *hw;
+ /* Semaphore used for end of transfer completion notification */
+ struct os_sem sem;
+ struct da1469x_dma_regs *dma_chans[2];
+ struct da1469x_transfer transfer;
+
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+ STATS_SECT_DECL(spi_da1469x_stats_section) stats;
+#endif
+};
+
+static struct spi_da1469x_driver_data spi_dev_data_0;
+static struct spi_da1469x_driver_data spi_dev_data_1;
+
+static inline struct spi_da1469x_driver_data *
+driver_data(struct bus_spi_dev *dev)
+{
+ if (MYNEWT_VAL(SPI_0_MASTER) && dev->cfg.spi_num == 0) {
+ return &spi_dev_data_0;
+ } else if (MYNEWT_VAL(SPI_1_MASTER) && dev->cfg.spi_num == 1) {
+ return &spi_dev_data_1;
+ } else {
+ assert(0);
+ return NULL;
+ }
+}
+
+static void
+spi_da1469x_int_clear(SPI_Type *regs)
+{
+ regs->SPI_CLEAR_INT_REG = 0;
+}
+
+static void
+spi_da1469x_int_enable(SPI_Type *regs)
+{
+ regs->SPI_CTRL_REG |= SPI_SPI_CTRL_REG_SPI_MINT_Msk;
+}
+
+static void
+spi_da1469x_int_disable(SPI_Type *regs)
+{
+ regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_MINT_Msk;
+}
+
+static int
+spi_da1469x_dma_done_cb(void *arg)
+{
+ struct spi_da1469x_driver_data *dd = (struct spi_da1469x_driver_data *)arg;
+ struct da1469x_transfer *transfer;
+ int transferred;
+
+ transfer = &dd->transfer;
+ if (transfer->started) {
+ transfer->started = 0;
+ transferred = (int)(dd->dma_chans[0]->DMA_IDX_REG + 1);
+
+ transfer->wlen += transferred;
+ transfer->rlen += transferred;
+
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+ if (transfer->write) {
+ STATS_INCN(dd->stats, written_bytes, transferred);
+ } else {
+ STATS_INCN(dd->stats, read_bytes, transferred);
+ }
+ STATS_INCN(dd->stats, dma_transferred_bytes, transferred);
+#endif
+
+ os_sem_release(&dd->sem);
+ }
+
+ return 0;
+}
+
+static void
+spi_da1469x_isr(SPI_Type *regs, struct spi_da1469x_driver_data *dd)
+{
+ struct da1469x_transfer *transfer = &dd->transfer;
+ uint8_t rx_byte;
+
+ while ((transfer->wlen < transfer->len) &&
+ !(regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_TXH_Msk)) {
+ if (transfer->write) {
+ regs->SPI_RX_TX_REG = transfer->data[transfer->wlen];
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+ STATS_INC(dd->stats, written_bytes);
+#endif
+ } else {
+ regs->SPI_RX_TX_REG = 0xFF;
+ }
+ transfer->wlen++;
+ }
+
+ if (transfer->wlen == transfer->len) {
+ regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_TX_FIFO_NOTFULL_MASK_Msk;
+ }
+
+ while (0 != (regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_INT_BIT_Msk)) {
+ rx_byte = regs->SPI_RX_TX_REG;
+ if (transfer->rlen < transfer->len) {
+ if (!transfer->write) {
+ transfer->data[transfer->rlen] = rx_byte;
+#if MYNEWT_VAL(SPI_DA1469X_STAT)
+ STATS_INC(dd->stats, read_bytes);
+#endif
+ }
+ transfer->rlen++;
+ }
+ regs->SPI_CLEAR_INT_REG = 1;
+ }
+
+ if (transfer->started && transfer->rlen == transfer->len) {
+ spi_da1469x_int_disable(regs);
+ transfer->started = 0;
+ assert(os_sem_get_count(&dd->sem) == 0);
+ os_sem_release(&dd->sem);
+ }
+}
+
+static void
+spi_da1469x_spi0_isr(void)
+{
+ os_trace_isr_enter();
+
+ spi_da1469x_isr((SPI_Type *)SPI, &spi_dev_data_0);
+
+ os_trace_isr_exit();
+}
+
+static void
+spi_da1469x_spi1_isr(void)
+{
+ os_trace_isr_enter();
+
+ spi_da1469x_isr((SPI_Type *)SPI2, &spi_dev_data_1);
+
+ os_trace_isr_exit();
+}
+
+static int
+spi_da1469x_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+ struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+ struct bus_spi_node_cfg *cfg = arg;
+ (void)bdev;
+
+ BUS_DEBUG_POISON_NODE(node);
+
+ node->pin_cs = cfg->pin_cs;
+ node->freq = cfg->freq;
+ node->quirks = cfg->quirks;
+ node->data_order = cfg->data_order;
+ node->mode = cfg->mode;
+
+ if (node->pin_cs >= 0) {
+ hal_gpio_init_out(node->pin_cs, 1);
+ }
+
+ return 0;
+}
+
+static int
+spi_da1469x_disable(struct bus_dev *bdev)
+{
+ struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+ struct spi_da1469x_driver_data *dd;
+ SPI_Type *regs;
+
+ BUS_DEBUG_VERIFY_DEV(dev);
+
+ dd = driver_data(dev);
+ regs = dd->hw->regs;
+
+ /* Turn off SPI. */
+ regs->SPI_CTRL_REG &= ~(1U << SPI_SPI_CTRL_REG_SPI_ON_Pos);
+
+ if (dd->dma_chans[0] != NULL) {
+ da1469x_dma_release_channel(dd->dma_chans[0]);
+ dd->dma_chans[0] = NULL;
+ dd->dma_chans[1] = NULL;
+ }
+
+ /*
+ * Domain COM can be powered off, register content can be lost prepare
+ * to set it from scratch.
+ */
+ bdev->configured_for = NULL;
+
+ da1469x_pd_release(MCU_PD_DOMAIN_COM);
+
+ return 0;
+}
+
+static int
+spi_da1469x_enable(struct bus_dev *bdev)
+{
+ struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+ const struct da1469x_spi_hw *spi_hw;
+ struct spi_da1469x_driver_data *dd;
+ SPI_Type *regs;
+
+ BUS_DEBUG_VERIFY_DEV(dev);
+
+ dd = driver_data(dev);
+ spi_hw = dd->hw;
+ regs = spi_hw->regs;
+
+ da1469x_pd_acquire(MCU_PD_DOMAIN_COM);
+
+ /* Enable clock */
+ CRG_COM->SET_CLK_COM_REG = (1U << spi_hw->clk_ena_bit);
+
+ regs->SPI_CTRL_REG |= (1U << SPI_SPI_CTRL_REG_SPI_ON_Pos);
+ spi_da1469x_int_clear(spi_hw->regs);
+
+ da1469x_dma_acquire_periph(-1, spi_hw->dma_periph, dd->dma_chans);
+
+ if (dd->dma_chans[0] != NULL) {
+ dd->dma_chans[0]->DMA_A_START_REG = (uint32_t)®s->SPI_RX_TX_REG;
+ dd->dma_chans[1]->DMA_B_START_REG = (uint32_t)®s->SPI_RX_TX_REG;
+ }
+
+ return 0;
+}
+
+static int
+spi_da1469x_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+ struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+ struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+ struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+ struct spi_da1469x_driver_data *dd;
+ SPI_Type *regs;
+ uint32_t ctrl_reg;
+ int rc = 0;
Review comment:
A minor nitpick: why even declare rc and set it to 0? This function only seems to return 0 (unless I missed it) so why not just have it return 0?
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org