This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 02db473e97b drivers/eeprom: Set the bus frequency
02db473e97b is described below

commit 02db473e97ba3199ee3be80f835b3db40abaec0b
Author: Antoine Juckler <[email protected]>
AuthorDate: Mon Dec 2 14:16:47 2024 +0900

    drivers/eeprom: Set the bus frequency
    
    Add EEPIOC_SETSPEED ioctl acting like the MTDIOC_SETSPEED ioctl. The
    default frequency is settable in the Kconfig.
    
    Add xx25xx SPI delay control configurations.
    
    Signed-off-by: Antoine Juckler <[email protected]>
---
 .../components/drivers/character/eeprom.rst        | 10 ++-
 drivers/eeprom/Kconfig                             | 42 ++++++++++-
 drivers/eeprom/i2c_xx24xx.c                        | 37 +++++----
 drivers/eeprom/spi_xx25xx.c                        | 88 +++++++++++++++-------
 include/nuttx/eeprom/eeprom.h                      | 21 ++++--
 5 files changed, 142 insertions(+), 56 deletions(-)

diff --git a/Documentation/components/drivers/character/eeprom.rst 
b/Documentation/components/drivers/character/eeprom.rst
index 25c2813bb2f..143a3fb3e72 100644
--- a/Documentation/components/drivers/character/eeprom.rst
+++ b/Documentation/components/drivers/character/eeprom.rst
@@ -155,7 +155,15 @@ IOCTL Commands
 The full list of ``ioctl()`` commands can be found in
 ``include/nuttx/eeprom/eeprom.h``.
 
--  ``EEPIOC_GEOMETRY``: Get the EEPROM geometry
+- ``EEPIOC_GEOMETRY``
+    *Argument:* ``struct eeprom_geometry_s *``
+
+    Get the EEPROM geometry
+
+- ``EEPIOC_SETSPEED``
+    *Argument:* ``uint32_t``
+
+    Set the SPI/I2C bus frequency
 
 File Systems
 ============
diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
index ac0de6fe317..e61bd6e0557 100644
--- a/drivers/eeprom/Kconfig
+++ b/drivers/eeprom/Kconfig
@@ -24,12 +24,45 @@ if SPI_EE_25XX
 config EE25XX_SPIMODE
        int "SPI mode (0-3)"
        default 0
-       depends on SPI_EE_25XX
 
 config EE25XX_FREQUENCY
        int "SPI EEPROM SCK frequency"
        default 10000000
-       depends on SPI_EE_25XX
+       ---help---
+               Default SPI bus frequency, it can be overwritten at runtime 
using the
+               EEPIOC_SETSPEED ioctl. See eeprom/eeprom.h.
+
+config EE25XX_START_DELAY
+       int "SPI start delay"
+       depends on SPI_DELAY_CONTROL
+       range 0 1000000
+       default 5000
+       ---help---
+               The delay between CS active and first CLK. In ns.
+
+config EE25XX_STOP_DELAY
+       int "SPI stop delay"
+       depends on SPI_DELAY_CONTROL
+       range 0 1000000
+       default 5000
+       ---help---
+               The delay between last CLK and CS inactive. In ns.
+
+config EE25XX_CS_DELAY
+       int "SPI CS delay"
+       depends on SPI_DELAY_CONTROL
+       range 0 1000000
+       default 5000
+       ---help---
+               The delay between CS inactive and CS active again. In ns.
+
+config EE25XX_IFDELAY
+       int "SPI interface delay"
+       depends on SPI_DELAY_CONTROL
+       range 0 1000000
+       default 5000
+       ---help---
+               The delay between frames. In ns.
 
 endif # SPI_EE_25XX
 
@@ -46,12 +79,13 @@ if I2C_EE_24XX
 config EE24XX_FREQUENCY
        int "I2C EEPROM frequency (100000 or 400000)"
        default 100000
-       depends on I2C_EE_24XX
+       ---help---
+               Default I2C bus frequency, it can be overwritten at runtime 
using the
+               EEPIOC_SETSPEED ioctl. See eeprom/eeprom.h.
 
 config AT24CS_UUID
        bool "Device driver support for Atmel AT24CSxx UUID"
        default n
-       depends on I2C_EE_24XX
        ---help---
                The Atmel AT24CSxx family have a 128-bit UUID which appears as
                another I2C slave whose address is offset from the EEPROM by +8.
diff --git a/drivers/eeprom/i2c_xx24xx.c b/drivers/eeprom/i2c_xx24xx.c
index 92d40dd2a27..b9804c46877 100644
--- a/drivers/eeprom/i2c_xx24xx.c
+++ b/drivers/eeprom/i2c_xx24xx.c
@@ -96,10 +96,6 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-#ifndef CONFIG_EE24XX_FREQUENCY
-#  define CONFIG_EE24XX_FREQUENCY 100000
-#endif
-
 #define UUID_SIZE   16
 
 /****************************************************************************
@@ -124,23 +120,23 @@ struct ee24xx_dev_s
 {
   /* Bus management */
 
-  FAR struct i2c_master_s *i2c;      /* I2C device where the EEPROM is 
attached */
-  uint32_t                 freq;     /* I2C bus speed */
-  uint8_t                  addr;     /* 7-bit unshifted I2C device address */
+  FAR struct i2c_master_s *i2c;  /* I2C device where the EEPROM is attached */
+  uint32_t                 freq; /* I2C bus speed                           */
+  uint8_t                  addr; /* 7-bit unshifted I2C device address      */
 
   /* Driver management */
 
-  mutex_t                  lock;     /* file write access serialization */
-  uint8_t                  refs;     /* Nr of times the device has been opened 
*/
-  bool                     readonly; /* Flags */
+  mutex_t lock;     /* file write access serialization                      */
+  uint8_t refs;     /* Nr of times the device has been opened               */
+  bool    readonly; /* Flags                                                */
 
   /* Expanded from geometry */
 
-  uint32_t                 size;       /* total bytes in device */
-  uint16_t                 pgsize;     /* write block size, in bytes */
-  uint16_t                 addrlen;    /* number of bytes in data addresses */
-  uint16_t                 haddrbits;  /* Number of bits in high address part 
*/
-  uint16_t                 haddrshift; /* bit-shift of high address part */
+  uint32_t size;       /* total bytes in device                             */
+  uint16_t pgsize;     /* write block size, in bytes                        */
+  uint16_t addrlen;    /* number of bytes in data addresses                 */
+  uint16_t haddrbits;  /* Number of bits in high address part               */
+  uint16_t haddrshift; /* bit-shift of high address part                    */
 };
 
 /****************************************************************************
@@ -807,6 +803,17 @@ static int ee24xx_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
         }
         break;
 
+      case EEPIOC_SETSPEED:
+        {
+          ret = nxmutex_lock(&eedev->lock);
+          if (ret == OK)
+          {
+            eedev->freq = (uint32_t)arg;
+            nxmutex_unlock(&eedev->lock);
+          }
+        }
+        break;
+
       default:
         ret = -ENOTTY;
     }
diff --git a/drivers/eeprom/spi_xx25xx.c b/drivers/eeprom/spi_xx25xx.c
index a85ed492db8..52a2e413b7a 100644
--- a/drivers/eeprom/spi_xx25xx.c
+++ b/drivers/eeprom/spi_xx25xx.c
@@ -120,10 +120,6 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-#ifndef CONFIG_EE25XX_SPIMODE
-#  define CONFIG_EE25XX_SPIMODE 0
-#endif
-
 /* EEPROM commands
  * High bit of low nibble used for A8 in 25xx040/at25040 products
  */
@@ -176,15 +172,18 @@ struct ee25xx_geom_s
 
 struct ee25xx_dev_s
 {
-  struct spi_dev_s *spi;     /* SPI device where the EEPROM is attached */
-  uint16_t         devid;    /* SPI device ID to manage CS lines in board */
-  uint32_t         size;     /* in bytes, expanded from geometry */
-  uint16_t         pgsize;   /* write block size, in bytes, expanded from 
geometry */
-  uint32_t         secsize;  /* write sector size, in bytes, expanded from 
geometry */
-  uint16_t         addrlen;  /* number of BITS in data addresses */
-  mutex_t          lock;     /* file access serialization */
-  uint8_t          refs;     /* The number of times the device has been opened 
*/
-  uint8_t          readonly; /* Flags */
+  FAR struct spi_dev_s *spi;   /* SPI device where the EEPROM is attached   */
+  uint16_t              devid; /* SPI device ID to manage CS lines in board */
+  uint32_t              freq;  /* SPI bus frequency in Hz                   */
+
+  uint32_t size;     /* in bytes, expanded from geometry                    */
+  uint16_t pgsize;   /* write block size, in bytes, expanded from geometry  */
+  uint32_t secsize;  /* write sector size, in bytes, expanded from geometry */
+  uint16_t addrlen;  /* number of BITS in data addresses                    */
+
+  mutex_t lock;     /* file access serialization                            */
+  uint8_t refs;     /* The number of times the device has been opened       */
+  uint8_t readonly; /* Flags                                                */
 };
 
 /****************************************************************************
@@ -297,9 +296,16 @@ static const struct file_operations g_ee25xx_fops =
 
 /****************************************************************************
  * Name: ee25xx_lock
+ *
+ * Description:
+ *   Lock the SPI bus associated with the driver, set its mode and frequency
+ *
+ * Input Parameters
+ *   priv - Device structure
+ *
  ****************************************************************************/
 
-static void ee25xx_lock(FAR struct spi_dev_s *dev)
+static void ee25xx_lock(FAR struct ee25xx_dev_s *priv)
 {
   /* On SPI buses where there are multiple devices, it will be necessary to
    * lock SPI to have exclusive access to the buses for a sequence of
@@ -310,7 +316,7 @@ static void ee25xx_lock(FAR struct spi_dev_s *dev)
    * bus is unlocked.
    */
 
-  SPI_LOCK(dev, true);
+  SPI_LOCK(priv->spi, true);
 
   /* After locking the SPI bus, the we also need call the setfrequency,
    * setbits, and setmode methods to make sure that the SPI is properly
@@ -318,19 +324,31 @@ static void ee25xx_lock(FAR struct spi_dev_s *dev)
    * have been left in an incompatible state.
    */
 
-  SPI_SETMODE(dev, CONFIG_EE25XX_SPIMODE);
-  SPI_SETBITS(dev, 8);
-  SPI_HWFEATURES(dev, 0);
-  SPI_SETFREQUENCY(dev, CONFIG_EE25XX_FREQUENCY);
+  SPI_SETMODE(priv->spi, CONFIG_EE25XX_SPIMODE);
+  SPI_SETBITS(priv->spi, 8);
+  SPI_HWFEATURES(priv->spi, 0);
+  SPI_SETFREQUENCY(priv->spi, priv->freq);
+#ifdef CONFIG_SPI_DELAY_CONTROL
+  SPI_SETDELAY(priv->spi, CONFIG_EE25XX_START_DELAY,
+               CONFIG_EE25XX_STOP_DELAY, CONFIG_EE25XX_CS_DELAY,
+               CONFIG_EE25XX_IFDELAY);
+#endif
 }
 
 /****************************************************************************
  * Name: ee25xx_unlock
+ *
+ * Description:
+ *   Unlock the SPI bus associated with the driver
+ *
+ * Input Parameters:
+ *   priv - Device structure
+ *
  ****************************************************************************/
 
-static inline void ee25xx_unlock(FAR struct spi_dev_s *dev)
+static inline void ee25xx_unlock(FAR struct ee25xx_dev_s *priv)
 {
-  SPI_LOCK(dev, false);
+  SPI_LOCK(priv->spi, false);
 }
 
 /****************************************************************************
@@ -390,7 +408,7 @@ static void ee25xx_waitwritecomplete(struct ee25xx_dev_s 
*priv)
     {
       /* Select this FLASH part */
 
-      ee25xx_lock(priv->spi);
+      ee25xx_lock(priv);
       SPI_SELECT(priv->spi, SPIDEV_EEPROM(priv->devid), true);
 
       /* Send "Read Status Register (RDSR)" command */
@@ -406,7 +424,7 @@ static void ee25xx_waitwritecomplete(struct ee25xx_dev_s 
*priv)
       /* Deselect the FLASH */
 
       SPI_SELECT(priv->spi, SPIDEV_EEPROM(priv->devid), false);
-      ee25xx_unlock(priv->spi);
+      ee25xx_unlock(priv);
 
       /* Given that writing could take up to a few milliseconds,
        * the following short delay in the "busy" case will allow
@@ -432,13 +450,13 @@ static void ee25xx_waitwritecomplete(struct ee25xx_dev_s 
*priv)
 
 static void ee25xx_writeenable(FAR struct ee25xx_dev_s *eedev, int enable)
 {
-  ee25xx_lock(eedev->spi);
+  ee25xx_lock(eedev);
   SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), true);
 
   SPI_SEND(eedev->spi, enable ? EE25XX_CMD_WREN : EE25XX_CMD_WRDIS);
 
   SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), false);
-  ee25xx_unlock(eedev->spi);
+  ee25xx_unlock(eedev);
 }
 
 /****************************************************************************
@@ -453,14 +471,14 @@ static void ee25xx_writepage(FAR struct ee25xx_dev_s 
*eedev,
                              FAR const char *data,
                              size_t len)
 {
-  ee25xx_lock(eedev->spi);
+  ee25xx_lock(eedev);
   SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), true);
 
   ee25xx_sendcmd(eedev->spi, EE25XX_CMD_WRITE, eedev->addrlen, devaddr);
   SPI_SNDBLOCK(eedev->spi, data, len);
 
   SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), false);
-  ee25xx_unlock(eedev->spi);
+  ee25xx_unlock(eedev);
 }
 
 /****************************************************************************
@@ -645,7 +663,7 @@ static ssize_t ee25xx_read(FAR struct file *filep, FAR char 
*buffer,
       len = eedev->size - filep->f_pos;
     }
 
-  ee25xx_lock(eedev->spi);
+  ee25xx_lock(eedev);
   SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), true);
 
   /* STM32F4Disco: There is a 25 us delay here */
@@ -659,7 +677,7 @@ static ssize_t ee25xx_read(FAR struct file *filep, FAR char 
*buffer,
   /* STM32F4Disco: There is a 20 us delay here */
 
   SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), false);
-  ee25xx_unlock(eedev->spi);
+  ee25xx_unlock(eedev);
 
   /* Update the file position */
 
@@ -803,6 +821,17 @@ static int ee25xx_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
         }
         break;
 
+      case EEPIOC_SETSPEED:
+        {
+          ret = nxmutex_lock(&eedev->lock);
+          if (ret == OK)
+          {
+            eedev->freq = (uint32_t)arg;
+            nxmutex_unlock(&eedev->lock);
+          }
+        }
+        break;
+
       default:
         ret = -ENOTTY;
     }
@@ -858,6 +887,7 @@ int ee25xx_initialize(FAR struct spi_dev_s *dev, uint16_t 
spi_devid,
 
   eedev->spi      = dev;
   eedev->devid    = spi_devid;
+  eedev->freq     = CONFIG_EE25XX_FREQUENCY;
   eedev->size     =           128 << g_ee25xx_devices[devtype].bytes;
   eedev->pgsize   =             8 << g_ee25xx_devices[devtype].pagesize;
   eedev->secsize  = eedev->pgsize << g_ee25xx_devices[devtype].secsize;
diff --git a/include/nuttx/eeprom/eeprom.h b/include/nuttx/eeprom/eeprom.h
index b64a93aa776..018d50761db 100644
--- a/include/nuttx/eeprom/eeprom.h
+++ b/include/nuttx/eeprom/eeprom.h
@@ -47,13 +47,20 @@
 /* EEPROM IOCTL Commands 
************************************************************/
 
 #define EEPIOC_GEOMETRY     _EEPIOC(0x000)  /* Similar to BIOC_GEOMETRY:
-                                             * Return the geometry of the 
EEPROM
-                                             * device.
-                                             * IN:  Pointer to writable 
instance  of
-                                             *      struct eeprom_geometry_s 
in which
-                                             *      to return the geometry.
-                                             * OUT: Data return in 
user-provided
-                                             *      buffer. */
+                                             * Return the geometry of the
+                                             * EEPROM device.
+                                             * IN:  Pointer to writable
+                                             *      instance  of struct
+                                             *      eeprom_geometry_s to be
+                                             *      populated
+                                             * OUT: Data return in user-
+                                             *      provided buffer.        */
+
+#define EEPIOC_SETSPEED     _EEPIOC(0x001)  /* Overwrite the SPI/I2C bus speed
+                                             * IN:  Bus speed in Hz
+                                             * OUT: None (ioctl return value
+                                             *      provides success/failure
+                                             *      indication).            */
 
 
/************************************************************************************
  * Type Definitions

Reply via email to