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