Skip to content

Commit 4f3689a

Browse files
committed
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 <6445757+ajuckler@users.noreply.github.com>
1 parent a221df7 commit 4f3689a

5 files changed

Lines changed: 144 additions & 61 deletions

File tree

Documentation/components/drivers/character/eeprom.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ IOCTL Commands
155155
The full list of ``ioctl()`` commands can be found in
156156
``include/nuttx/eeprom/eeprom.h``.
157157

158-
- ``EEPIOC_GEOMETRY``: Get the EEPROM geometry
158+
- ``EEPIOC_GEOMETRY``: Get the EEPROM geometry
159+
- ``EEPIOC_SETSPEED``: Set the SPI/I2C bus frequency
159160

160161
File Systems
161162
============

drivers/eeprom/Kconfig

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,41 @@ config EE25XX_FREQUENCY
3030
int "SPI EEPROM SCK frequency"
3131
default 10000000
3232
depends on SPI_EE_25XX
33+
---help---
34+
Default SPI bus frequency, it can be overwritten at runtime using the
35+
EEPIOC_SETSPEED ioctl. See eeprom/eeprom.h.
36+
37+
config EE25XX_START_DELAY
38+
int "SPI start delay"
39+
depends on SPI_DELAY_CONTROL
40+
range 0 1000000
41+
default 5000
42+
---help---
43+
The delay between CS active and first CLK. In ns.
44+
45+
config EE25XX_STOP_DELAY
46+
int "SPI stop delay"
47+
depends on SPI_DELAY_CONTROL
48+
range 0 1000000
49+
default 5000
50+
---help---
51+
The delay between last CLK and CS inactive. In ns.
52+
53+
config EE25XX_CS_DELAY
54+
int "SPI cs delay"
55+
depends on SPI_DELAY_CONTROL
56+
range 0 1000000
57+
default 5000
58+
---help---
59+
The delay between CS inactive and CS active again. In ns.
60+
61+
config EE25XX_IFDELAY
62+
int "SPI if delay"
63+
depends on SPI_DELAY_CONTROL
64+
range 0 1000000
65+
default 5000
66+
---help---
67+
The delay between frames. In ns.
3368

3469
endif # SPI_EE_25XX
3570

@@ -47,6 +82,9 @@ config EE24XX_FREQUENCY
4782
int "I2C EEPROM frequency (100000 or 400000)"
4883
default 100000
4984
depends on I2C_EE_24XX
85+
---help---
86+
Default I2C bus frequency, it can be overwritten at runtime using the
87+
EEPIOC_SETSPEED ioctl. See eeprom/eeprom.h.
5088

5189
config AT24CS_UUID
5290
bool "Device driver support for Atmel AT24CSxx UUID"

drivers/eeprom/i2c_xx24xx.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,6 @@
9696
* Pre-processor Definitions
9797
****************************************************************************/
9898

99-
#ifndef CONFIG_EE24XX_FREQUENCY
100-
# define CONFIG_EE24XX_FREQUENCY 100000
101-
#endif
102-
10399
#define UUID_SIZE 16
104100

105101
/****************************************************************************
@@ -124,23 +120,23 @@ struct ee24xx_dev_s
124120
{
125121
/* Bus management */
126122

127-
FAR struct i2c_master_s *i2c; /* I2C device where the EEPROM is attached */
128-
uint32_t freq; /* I2C bus speed */
129-
uint8_t addr; /* 7-bit unshifted I2C device address */
123+
FAR struct i2c_master_s *i2c; /* I2C device where the EEPROM is attached */
124+
uint32_t freq; /* I2C bus speed */
125+
uint8_t addr; /* 7-bit unshifted I2C device address */
130126

131127
/* Driver management */
132128

133-
mutex_t lock; /* file write access serialization */
134-
uint8_t refs; /* Nr of times the device has been opened */
135-
bool readonly; /* Flags */
129+
mutex_t lock; /* file write access serialization */
130+
uint8_t refs; /* Nr of times the device has been opened */
131+
bool readonly; /* Flags */
136132

137133
/* Expanded from geometry */
138134

139-
uint32_t size; /* total bytes in device */
140-
uint16_t pgsize; /* write block size, in bytes */
141-
uint16_t addrlen; /* number of bytes in data addresses */
142-
uint16_t haddrbits; /* Number of bits in high address part */
143-
uint16_t haddrshift; /* bit-shift of high address part */
135+
uint32_t size; /* total bytes in device */
136+
uint16_t pgsize; /* write block size, in bytes */
137+
uint16_t addrlen; /* number of bytes in data addresses */
138+
uint16_t haddrbits; /* Number of bits in high address part */
139+
uint16_t haddrshift; /* bit-shift of high address part */
144140
};
145141

146142
/****************************************************************************
@@ -807,6 +803,17 @@ static int ee24xx_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
807803
}
808804
break;
809805

806+
case EEPIOC_SETSPEED:
807+
{
808+
ret = nxmutex_lock(&eedev->lock);
809+
if (ret == OK)
810+
{
811+
eedev->freq = (uint32_t)arg;
812+
nxmutex_unlock(&eedev->lock);
813+
}
814+
}
815+
break;
816+
810817
default:
811818
ret = -ENOTTY;
812819
}

drivers/eeprom/spi_xx25xx.c

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,6 @@
120120
* Pre-processor Definitions
121121
****************************************************************************/
122122

123-
#ifndef CONFIG_EE25XX_SPIMODE
124-
# define CONFIG_EE25XX_SPIMODE 0
125-
#endif
126-
127123
/* EEPROM commands
128124
* High bit of low nibble used for A8 in 25xx040/at25040 products
129125
*/
@@ -176,15 +172,18 @@ struct ee25xx_geom_s
176172

177173
struct ee25xx_dev_s
178174
{
179-
struct spi_dev_s *spi; /* SPI device where the EEPROM is attached */
180-
uint16_t devid; /* SPI device ID to manage CS lines in board */
181-
uint32_t size; /* in bytes, expanded from geometry */
182-
uint16_t pgsize; /* write block size, in bytes, expanded from geometry */
183-
uint32_t secsize; /* write sector size, in bytes, expanded from geometry */
184-
uint16_t addrlen; /* number of BITS in data addresses */
185-
mutex_t lock; /* file access serialization */
186-
uint8_t refs; /* The number of times the device has been opened */
187-
uint8_t readonly; /* Flags */
175+
FAR struct spi_dev_s *spi; /* SPI device where the EEPROM is attached */
176+
uint16_t devid; /* SPI device ID to manage CS lines in board */
177+
uint32_t freq; /* SPI bus frequency in Hz */
178+
179+
uint32_t size; /* in bytes, expanded from geometry */
180+
uint16_t pgsize; /* write block size, in bytes, expanded from geometry */
181+
uint32_t secsize; /* write sector size, in bytes, expanded from geometry */
182+
uint16_t addrlen; /* number of BITS in data addresses */
183+
184+
mutex_t lock; /* file access serialization */
185+
uint8_t refs; /* The number of times the device has been opened */
186+
uint8_t readonly; /* Flags */
188187
};
189188

190189
/****************************************************************************
@@ -297,9 +296,16 @@ static const struct file_operations g_ee25xx_fops =
297296

298297
/****************************************************************************
299298
* Name: ee25xx_lock
299+
*
300+
* Description:
301+
* Lock the SPI bus associated with the driver, set its mode and frequency
302+
*
303+
* Input Parameters
304+
* priv - Device structure
305+
*
300306
****************************************************************************/
301307

302-
static void ee25xx_lock(FAR struct spi_dev_s *dev)
308+
static void ee25xx_lock(FAR struct ee25xx_dev_s *priv)
303309
{
304310
/* On SPI buses where there are multiple devices, it will be necessary to
305311
* lock SPI to have exclusive access to the buses for a sequence of
@@ -310,27 +316,39 @@ static void ee25xx_lock(FAR struct spi_dev_s *dev)
310316
* bus is unlocked.
311317
*/
312318

313-
SPI_LOCK(dev, true);
319+
SPI_LOCK(priv->spi, true);
314320

315321
/* After locking the SPI bus, the we also need call the setfrequency,
316322
* setbits, and setmode methods to make sure that the SPI is properly
317323
* configured for the device. If the SPI bus is being shared, then it may
318324
* have been left in an incompatible state.
319325
*/
320326

321-
SPI_SETMODE(dev, CONFIG_EE25XX_SPIMODE);
322-
SPI_SETBITS(dev, 8);
323-
SPI_HWFEATURES(dev, 0);
324-
SPI_SETFREQUENCY(dev, CONFIG_EE25XX_FREQUENCY);
327+
SPI_SETMODE(priv->spi, CONFIG_EE25XX_SPIMODE);
328+
SPI_SETBITS(priv->spi, 8);
329+
SPI_HWFEATURES(priv->spi, 0);
330+
SPI_SETFREQUENCY(priv->spi, priv->freq);
331+
#ifdef CONFIG_SPI_DELAY_CONTROL
332+
SPI_SETDELAY(priv->spi, CONFIG_EE25XX_START_DELAY,
333+
CONFIG_EE25XX_STOP_DELAY, CONFIG_EE25XX_CS_DELAY,
334+
CONFIG_EE25XX_IFDELAY);
335+
#endif
325336
}
326337

327338
/****************************************************************************
328339
* Name: ee25xx_unlock
340+
*
341+
* Description:
342+
* Unlock the SPI bus associated with the driver
343+
*
344+
* Input Parameters:
345+
* priv - Device structure
346+
*
329347
****************************************************************************/
330348

331-
static inline void ee25xx_unlock(FAR struct spi_dev_s *dev)
349+
static inline void ee25xx_unlock(FAR struct ee25xx_dev_s *priv)
332350
{
333-
SPI_LOCK(dev, false);
351+
SPI_LOCK(priv->spi, false);
334352
}
335353

336354
/****************************************************************************
@@ -390,7 +408,7 @@ static void ee25xx_waitwritecomplete(struct ee25xx_dev_s *priv)
390408
{
391409
/* Select this FLASH part */
392410

393-
ee25xx_lock(priv->spi);
411+
ee25xx_lock(priv);
394412
SPI_SELECT(priv->spi, SPIDEV_EEPROM(priv->devid), true);
395413

396414
/* Send "Read Status Register (RDSR)" command */
@@ -406,7 +424,7 @@ static void ee25xx_waitwritecomplete(struct ee25xx_dev_s *priv)
406424
/* Deselect the FLASH */
407425

408426
SPI_SELECT(priv->spi, SPIDEV_EEPROM(priv->devid), false);
409-
ee25xx_unlock(priv->spi);
427+
ee25xx_unlock(priv);
410428

411429
/* Given that writing could take up to a few milliseconds,
412430
* the following short delay in the "busy" case will allow
@@ -432,13 +450,13 @@ static void ee25xx_waitwritecomplete(struct ee25xx_dev_s *priv)
432450

433451
static void ee25xx_writeenable(FAR struct ee25xx_dev_s *eedev, int enable)
434452
{
435-
ee25xx_lock(eedev->spi);
453+
ee25xx_lock(eedev);
436454
SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), true);
437455

438456
SPI_SEND(eedev->spi, enable ? EE25XX_CMD_WREN : EE25XX_CMD_WRDIS);
439457

440458
SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), false);
441-
ee25xx_unlock(eedev->spi);
459+
ee25xx_unlock(eedev);
442460
}
443461

444462
/****************************************************************************
@@ -453,14 +471,14 @@ static void ee25xx_writepage(FAR struct ee25xx_dev_s *eedev,
453471
FAR const char *data,
454472
size_t len)
455473
{
456-
ee25xx_lock(eedev->spi);
474+
ee25xx_lock(eedev);
457475
SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), true);
458476

459477
ee25xx_sendcmd(eedev->spi, EE25XX_CMD_WRITE, eedev->addrlen, devaddr);
460478
SPI_SNDBLOCK(eedev->spi, data, len);
461479

462480
SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), false);
463-
ee25xx_unlock(eedev->spi);
481+
ee25xx_unlock(eedev);
464482
}
465483

466484
/****************************************************************************
@@ -645,7 +663,7 @@ static ssize_t ee25xx_read(FAR struct file *filep, FAR char *buffer,
645663
len = eedev->size - filep->f_pos;
646664
}
647665

648-
ee25xx_lock(eedev->spi);
666+
ee25xx_lock(eedev);
649667
SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), true);
650668

651669
/* STM32F4Disco: There is a 25 us delay here */
@@ -659,7 +677,7 @@ static ssize_t ee25xx_read(FAR struct file *filep, FAR char *buffer,
659677
/* STM32F4Disco: There is a 20 us delay here */
660678

661679
SPI_SELECT(eedev->spi, SPIDEV_EEPROM(eedev->devid), false);
662-
ee25xx_unlock(eedev->spi);
680+
ee25xx_unlock(eedev);
663681

664682
/* Update the file position */
665683

@@ -803,6 +821,17 @@ static int ee25xx_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
803821
}
804822
break;
805823

824+
case EEPIOC_SETSPEED:
825+
{
826+
ret = nxmutex_lock(&eedev->lock);
827+
if (ret == OK)
828+
{
829+
eedev->freq = (uint32_t)arg;
830+
nxmutex_unlock(&eedev->lock);
831+
}
832+
}
833+
break;
834+
806835
default:
807836
ret = -ENOTTY;
808837
}
@@ -858,6 +887,7 @@ int ee25xx_initialize(FAR struct spi_dev_s *dev, uint16_t spi_devid,
858887

859888
eedev->spi = dev;
860889
eedev->devid = spi_devid;
890+
eedev->freq = CONFIG_EE25XX_FREQUENCY;
861891
eedev->size = 128 << g_ee25xx_devices[devtype].bytes;
862892
eedev->pgsize = 8 << g_ee25xx_devices[devtype].pagesize;
863893
eedev->secsize = eedev->pgsize << g_ee25xx_devices[devtype].secsize;

include/nuttx/eeprom/eeprom.h

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/************************************************************************************
1+
/****************************************************************************
22
* include/nuttx/eeprom/eeprom.h
33
*
44
* SPDX-License-Identifier: Apache-2.0
@@ -20,7 +20,7 @@
2020
* License for the specific language governing permissions and limitations
2121
* under the License.
2222
*
23-
************************************************************************************/
23+
****************************************************************************/
2424

2525
/* This file includes common definitions to be used in all EEPROM drivers
2626
* (when applicable).
@@ -29,9 +29,9 @@
2929
#ifndef __INCLUDE_NUTTX_EEPROM_EEPROM_H
3030
#define __INCLUDE_NUTTX_EEPROM_EEPROM_H
3131

32-
/************************************************************************************
32+
/****************************************************************************
3333
* Included Files
34-
************************************************************************************/
34+
****************************************************************************/
3535

3636
#include <nuttx/config.h>
3737

@@ -40,24 +40,31 @@
4040

4141
#include <nuttx/fs/ioctl.h>
4242

43-
/************************************************************************************
43+
/****************************************************************************
4444
* Pre-processor Definitions
45-
************************************************************************************/
45+
****************************************************************************/
4646

47-
/* EEPROM IOCTL Commands ************************************************************/
47+
/* EEPROM IOCTL Commands ****************************************************/
4848

4949
#define EEPIOC_GEOMETRY _EEPIOC(0x000) /* Similar to BIOC_GEOMETRY:
50-
* Return the geometry of the EEPROM
51-
* device.
52-
* IN: Pointer to writable instance of
53-
* struct eeprom_geometry_s in which
54-
* to return the geometry.
55-
* OUT: Data return in user-provided
56-
* buffer. */
50+
* Return the geometry of the
51+
* EEPROM device.
52+
* IN: Pointer to writable
53+
* instance of struct
54+
* eeprom_geometry_s to be
55+
* populated
56+
* OUT: Data return in user-
57+
* provided buffer. */
5758

58-
/************************************************************************************
59+
#define EEPIOC_SETSPEED _EEPIOC(0x001) /* Overwrite the SPI/I2C bus speed
60+
* IN: Bus speed in Hz
61+
* OUT: None (ioctl return value
62+
* provides success/failure
63+
* indication). */
64+
65+
/****************************************************************************
5966
* Type Definitions
60-
************************************************************************************/
67+
****************************************************************************/
6168

6269
struct eeprom_geometry_s
6370
{

0 commit comments

Comments
 (0)