btashton commented on a change in pull request #2804:
URL: https://github.com/apache/incubator-nuttx/pull/2804#discussion_r571823376



##########
File path: arch/risc-v/src/bl602/bl602_spi.c
##########
@@ -0,0 +1,1232 @@
+/****************************************************************************
+ * arch/risc-v/src/bl602/bl602_spi.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/spi/spi.h>
+
+#include <arch/board/board.h>
+
+#include "bl602_glb.h"
+#include "bl602_gpio.h"
+#include "bl602_spi.h"
+#include "hardware/bl602_glb.h"
+#include "hardware/bl602_spi.h"
+#include "riscv_arch.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define SPI_FREQ_DEFAULT 400000
+#define BASIC_CLK        4000000
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* SPI frequency cal configuration */
+
+struct prescale_and_count_cal_ctx_s
+{
+  uint64_t desired_ticks;
+  uint64_t count_max;
+  uint64_t error;
+  uint64_t count;
+  uint32_t prescale;
+  uint8_t update;
+};
+
+/* SPI clock configuration */
+
+struct spi_clock_cfg_s
+{
+  uint8_t start_len;       /* Length of start condition */
+  uint8_t stop_len;        /* Length of stop condition */
+  uint8_t data_phase0_len; /* Length of data phase 0,affecting clock */
+  uint8_t data_phase1_len; /* Length of data phase 1,affecting clock */
+  uint8_t interval_len;    /* Length of interval between frame */
+};
+
+/* SPI configuration */
+
+struct spi_cfg_s
+{
+  uint8_t deglitch_enable;   /* Enable or disable de-glitch function */
+  uint8_t continuous_enable; /* Enable or disable master continuous transfer
+                              * mode,enable:SS will stay asserted if next data
+                              * is valid
+                              */
+  uint8_t byte_sequence;     /* The byte is sent first in SPI transfer ,0 is 
send
+                              * 0byte first; 1 is send 3byte first
+                              */
+  uint8_t bit_sequence;      /* The bit is sent first in SPI transfer ,0 is 
each byte
+                              * is sent out MSB first; 1 is each byte is sent 
out LSB
+                              * first
+                              */
+};
+
+/* SPI Device hardware configuration */
+
+struct bl602_spi_config_s
+{
+  uint32_t clk_freq;    /* SPI clock frequency */
+  enum spi_mode_e mode; /* SPI default mode */
+
+  bool use_dma; /* Use DMA */
+};
+
+struct bl602_spi_priv_s
+{
+  /* Externally visible part of the SPI interface */
+
+  struct spi_dev_s spi_dev;
+
+  /* Port configuration */
+
+  const struct bl602_spi_config_s *config;
+
+  int refs; /* Referernce count */
+
+  /* Held while chip is selected for mutual exclusion */
+
+  sem_t exclsem;
+
+  /* Interrupt wait semaphore */
+
+  sem_t sem_isr;
+
+  uint32_t frequency; /* Requested clock frequency */
+  uint32_t actual;    /* Actual clock frequency */
+
+  enum spi_mode_e mode; /* Actual SPI hardware mode */
+
+  /* Actual SPI send/receive bits once transmission */
+
+  uint8_t nbits;
+  uint8_t dma_chan;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int bl602_spi_lock(FAR struct spi_dev_s *dev, bool lock);
+
+static void bl602_spi_select(FAR struct spi_dev_s *dev, uint32_t devid,
+                             bool selected);
+
+static uint32_t bl602_spi_setfrequency(FAR struct spi_dev_s *dev,
+                                       uint32_t frequency);
+static void bl602_spi_setmode(FAR struct spi_dev_s *dev,
+                              enum spi_mode_e mode);
+static void bl602_spi_setbits(FAR struct spi_dev_s *dev, int nbits);
+#ifdef CONFIG_SPI_HWFEATURES
+static int bl602_spi_hwfeatures(FAR struct spi_dev_s *dev,
+                                spi_hwfeatures_t features);
+#endif
+static uint8_t bl602_spi_status(FAR struct spi_dev_s *dev,
+                                uint32_t devid);
+#ifdef CONFIG_SPI_CMDDATA
+static int bl602_spi_cmddata(FAR struct spi_dev_s *dev,
+                              uint32_t devid, bool cmd);
+#endif
+static uint32_t bl602_spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
+static void bl602_spi_exchange(FAR struct spi_dev_s *dev,
+                               FAR const void *txbuffer,
+                               FAR void *rxbuffer, size_t nwords);
+#ifndef CONFIG_SPI_EXCHANGE
+static void bl602_spi_sndblock(FAR struct spi_dev_s *dev,
+                               FAR const void *txbuffer, size_t nwords);
+static void bl602_spi_recvblock(FAR struct spi_dev_s *dev,
+                                FAR void *rxbuffer, size_t nwords);
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+static int bl602_spi_trigger(FAR struct spi_dev_s *dev);
+#endif
+static void bl602_spi_init(FAR struct spi_dev_s *dev);
+static void bl602_spi_deinit(FAR struct spi_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_BL602_SPI0
+static const struct bl602_spi_config_s bl602_spi_config =
+{
+    .clk_freq = SPI_FREQ_DEFAULT,
+    .mode = SPIDEV_MODE0,
+    .use_dma = false,
+};
+
+static const struct spi_ops_s bl602_spi_ops =
+{
+    .lock = bl602_spi_lock,
+    .select = bl602_spi_select,
+    .setfrequency = bl602_spi_setfrequency,
+#ifdef CONFIG_SPI_CS_DELAY_CONTROL
+    .setdelay = bl602_spi_setdelay,
+#endif
+    .setmode = bl602_spi_setmode,
+    .setbits = bl602_spi_setbits,
+#ifdef CONFIG_SPI_HWFEATURES
+    .hwfeatures = bl602_spi_hwfeatures,
+#endif
+    .status = bl602_spi_status,
+#ifdef CONFIG_SPI_CMDDATA
+    .cmddata = bl602_spi_cmddata,
+#endif
+    .send = bl602_spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+    .exchange = bl602_spi_exchange,
+#else
+    .sndblock = bl602_spi_sndblock,
+    .recvblock = bl602_spi_recvblock,
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+    .trigger = bl602_spi_trigger,
+#endif
+    .registercallback = NULL,
+};
+
+static struct bl602_spi_priv_s bl602_spi_priv =
+{
+  .spi_dev =
+              {
+                .ops = &bl602_spi_ops
+              },
+  .config = &bl602_spi_config
+};
+
+#endif  /* CONFIG_BL602_SPI0 */
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bl602_check_with_new_prescale
+ *
+ * Description:
+ *   Check if the option prescale
+ *
+ ****************************************************************************/
+
+static void
+bl602_check_with_new_prescale(struct prescale_and_count_cal_ctx_s *p_ctx,
+                                    uint32_t prescale_new)
+{
+  uint64_t count = p_ctx->desired_ticks / prescale_new;
+  uint64_t error;
+
+  if (count > p_ctx->count_max)
+    {
+      count = p_ctx->count_max;
+    }
+
+  error = p_ctx->desired_ticks - count * prescale_new;
+
+  if (p_ctx->error > error)
+    {
+      p_ctx->error = error;
+      p_ctx->count = count;
+      p_ctx->prescale = prescale_new;
+      p_ctx->update = 1;
+    }
+}
+
+/****************************************************************************
+ * Name: bl602_prescale_and_count_cal
+ *
+ * Description:
+ *   prescale and count cal
+ *
+ ****************************************************************************/
+
+static int
+bl602_prescale_and_count_cal(uint32_t counter_width,
+                            uint32_t prescale_max, size_t ticks,
+                            uint32_t *p_prescale, size_t *p_count)
+{
+  struct prescale_and_count_cal_ctx_s ctx;
+
+  uint32_t prescale_min;
+  uint32_t prescale;
+
+  size_t count_max;
+
+  count_max = ((uint64_t)1ull << counter_width) - 1;
+
+  if (ticks <= count_max)
+    {
+      *p_prescale = 1;
+      *p_count = ticks;
+
+      return 0;
+    }
+
+  prescale_min = ticks / count_max;
+
+  ctx.count_max = count_max;
+  ctx.desired_ticks = ticks;
+  ctx.error = ticks;
+  ctx.count = count_max;
+  ctx.prescale = 1;
+  ctx.update = 0;
+
+  if (prescale_max < prescale_min)
+    {
+      return -1;
+    }
+
+  for (prescale = prescale_min; prescale <= prescale_max; prescale++)
+    {
+      bl602_check_with_new_prescale(&ctx, prescale);
+      if (ctx.error == 0)
+        {
+          break;
+        }
+    }
+
+  if (ctx.update)
+    {
+      *p_prescale = ctx.prescale;
+      *p_count = ctx.count;
+
+      return 0;
+    }
+
+  return -1;
+}
+
+/****************************************************************************
+ * Name: bl602_set_spi_clk
+ *
+ * Description:
+ *   set SPI clock
+ *
+ ****************************************************************************/
+
+static void bl602_set_spi_clk(uint8_t enable, uint8_t div)
+{
+  modifyreg32(BL602_CLK_CFG3, CLK_CFG3_SPI_CLK_DIV_MASK, div);
+
+  if (enable)
+    {
+      modifyreg32(BL602_CLK_CFG3, 0, CLK_CFG3_SPI_CLK_EN);
+    }
+  else
+    {
+      modifyreg32(BL602_CLK_CFG3, CLK_CFG3_SPI_CLK_EN, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: bl602_clockconfig
+ *
+ * Description:
+ *   SPI clock config
+ *
+ ****************************************************************************/
+
+static void bl602_clockconfig(struct spi_clock_cfg_s *clockcfg)
+{
+  /* Configure length of data phase1/0 and start/stop condition */
+
+  modifyreg32(BL602_SPI_PRD_0, SPI_PRD_0_CR_S_MASK,
+              (clockcfg->start_len - 1));
+  modifyreg32(BL602_SPI_PRD_0, SPI_PRD_0_CR_P_MASK,
+              (clockcfg->stop_len - 1) << SPI_PRD_0_CR_P_SHIFT);
+  modifyreg32(BL602_SPI_PRD_0, SPI_PRD_0_CR_D_PH_0_MASK,
+              (clockcfg->data_phase0_len - 1) << SPI_PRD_0_CR_D_PH_0_SHIFT);
+  modifyreg32(BL602_SPI_PRD_0, SPI_PRD_0_CR_D_PH_1_MASK,
+              (clockcfg->data_phase1_len - 1) << SPI_PRD_0_CR_D_PH_1_SHIFT);
+
+  /* Configure length of interval between frame */
+
+  modifyreg32(BL602_SPI_PRD_1, SPI_PRD_1_CR_I_MASK,
+              clockcfg->interval_len - 1);
+}
+
+/****************************************************************************
+ * Name: bl602_spi_lock
+ *
+ * Description:
+ *   Lock or unlock the SPI device
+ *
+ * Input Parameters:
+ *   priv   - Private SPI device structure
+ *   lock   - true: Lock spi bus, false: unlock SPI bus
+ *
+ * Returned Value:
+ *   The result of lock or unlock the SPI device
+ *
+ ****************************************************************************/
+
+static int bl602_spi_lock(FAR struct spi_dev_s *dev, bool lock)
+{
+  int ret;
+  FAR struct bl602_spi_priv_s *priv = (FAR struct bl602_spi_priv_s *)dev;
+
+  if (lock)
+    {
+      ret = nxsem_wait_uninterruptible(&priv->exclsem);
+    }
+  else
+    {
+      ret = nxsem_post(&priv->exclsem);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: bl602_spi_select
+ *
+ * Description:
+ *   Enable/disable the SPI chip select.  The implementation of this method
+ *   must include handshaking:  If a device is selected, it must hold off
+ *   all other attempts to select the device until the device is deselected.
+ *
+ *   If disable bl602_SPI_SWCS, driver will use hardware CS so that when
+ *   once transmission is started, hardware select the device and when this
+ *   transmission is done, hardware deselect the device automatically. And
+ *   the function will do nothing.
+ *
+ * Input Parameters:
+ *   priv     - Private SPI device structure
+ *   devid    - Identifies the device to select
+ *   selected - true: slave selected, false: slave de-selected
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void bl602_spi_select(FAR struct spi_dev_s *dev, uint32_t devid,
+                             bool selected)
+{
+  /* we used hardware CS */
+
+  spiinfo("devid: %lu, CS: %s\n", devid, selected ? "select" : "free");
+}
+
+/****************************************************************************
+ * Name: bl602_spi_setfrequency
+ *
+ * Description:
+ *   Set the SPI frequency.
+ *
+ * Input Parameters:
+ *   dev -       Device-specific state data
+ *   frequency - The SPI frequency requested
+ *
+ * Returned Value:
+ *   Returns the actual frequency selected
+ *
+ ****************************************************************************/
+
+static uint32_t bl602_spi_setfrequency(FAR struct spi_dev_s *dev,
+                                       uint32_t frequency)
+{
+  FAR struct bl602_spi_priv_s *priv = (FAR struct bl602_spi_priv_s *)dev;
+  struct spi_clock_cfg_s clockcfg;
+  size_t count;
+  uint32_t clk_div;
+  uint8_t ticks;
+
+  if (priv->frequency == frequency)
+    {
+      /* We are already at this frequency. Return the actual. */
+
+      return priv->actual;
+    }
+
+  ticks = BASIC_CLK / frequency;
+
+  if (bl602_prescale_and_count_cal(8, 0xff, ticks, &clk_div, &count) != 0)
+    {
+      spiinfo("--------spi div clk error!!!!--------\r\n");

Review comment:
       Lets remove the `----` in these debug messages.  They also just need the 
`\n` the CR will be handled by the lower layer if needed (check the other 
messages here as well for this).




----------------------------------------------------------------
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:
[email protected]


Reply via email to