walnux/include/nuttx/spi/spi.h
raiden00pl 7675be7a09 include/nuttx/motor: add registers definitions for DRV8301 - 3-phase smart gate driver
This is intended to use in a board-specific logic and depends highly on a custom application.
That's why no common driver logic is provided for now.
2022-02-17 01:07:59 +08:00

605 lines
22 KiB
C

/****************************************************************************
* include/nuttx/spi/spi.h
*
* 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.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_SPI_SPI_H
#define __INCLUDE_NUTTX_SPI_SPI_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* These SPI configuration options affect the form of the SPI interface:
*
* CONFIG_SPI_EXCHANGE - Driver supports a single exchange method
* (vs a recvblock() and sndblock() methods).
* CONFIG_SPI_CMDDATA - Devices on the SPI bus require out-of-band support
* to distinguish command transfers from data transfers. Such devices
* will often support either 9-bit SPI (yech) or 8-bit SPI and a GPIO
* output that selects between command and data.
* CONFIG_SPI_HWFEATURES - Include an interface method to support special,
* hardware-specific SPI features.
*/
/* Access macros ************************************************************/
/****************************************************************************
* Name: SPI_LOCK
*
* Description:
* 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
* transfers. The bus should be locked before the chip is selected. After
* locking the SPI bus, the caller should then also call the setfrequency,
* setbits, and setmode methods to make sure that the SPI is properly
* configured for the device. If the SPI bus is being shared, then it
* may have been left in an incompatible state.
*
* Input Parameters:
* dev - Device-specific state data
* lock - true: Lock spi bus, false: unlock SPI bus
*
* Returned Value:
* None
*
****************************************************************************/
#define SPI_LOCK(d,l) (d)->ops->lock(d,l)
/****************************************************************************
* Name: 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.
* Required.
*
* Input Parameters:
* dev - Device-specific state data
* devid - Identifies the device to select
* selected - true: slave selected, false: slave de-selected
*
* Returned Value:
* None
*
****************************************************************************/
#define SPI_SELECT(d,id,s) ((d)->ops->select(d,id,s))
/****************************************************************************
* Name: SPI_SETFREQUENCY
*
* Description:
* Set the SPI frequency. Required.
*
* Input Parameters:
* dev - Device-specific state data
* frequency - The SPI frequency requested
*
* Returned Value:
* Returns the actual frequency selected
*
****************************************************************************/
#define SPI_SETFREQUENCY(d,f) ((d)->ops->setfrequency(d,f))
/****************************************************************************
* Name: SPI_SETDELAY
*
* Description:
* Set the SPI Delays in nanoseconds. Optional.
*
* Input Parameters:
* dev - Device-specific state data
* startdelay - The delay between CS active and first CLK
* stopdelay - The delay between last CLK and CS inactive
* csdelay - The delay between CS inactive and CS active again
* ifdelay - The delay between frames
*
* Returned Value:
* Returns zero (OK) on success; a negated errno value is return on any
* failure.
*
****************************************************************************/
#ifdef CONFIG_SPI_DELAY_CONTROL
# define SPI_SETDELAY(d,a,b,c,i) ((d)->ops->setdelay(d,a,b,c,i))
#endif
/****************************************************************************
* Name: SPI_SETMODE
*
* Description:
* Set the SPI mode. Optional. See enum spi_mode_e for mode definitions.
*
* Input Parameters:
* dev - Device-specific state data
* mode - The SPI mode requested
*
* Returned Value:
* none
*
****************************************************************************/
#define SPI_SETMODE(d,m) \
do { if ((d)->ops->setmode) (d)->ops->setmode(d,m); } while (0)
/****************************************************************************
* Name: SPI_SETBITS
*
* Description:
* Set the number of bits per word.
*
* Input Parameters:
* dev - Device-specific state data
* nbits - The number of bits in an SPI word.
*
* Returned Value:
* none
*
****************************************************************************/
#define SPI_SETBITS(d,b) \
do { if ((d)->ops->setbits) (d)->ops->setbits(d,b); } while (0)
/****************************************************************************
* Name: SPI_HWFEATURES
*
* Description:
* Set hardware-specific feature flags.
*
* Input Parameters:
* dev - Device-specific state data
* features - H/W feature flags
*
* Returned Value:
* Zero (OK) if the selected H/W features are enabled; A negated errno
* value if any H/W feature is not supportable.
*
****************************************************************************/
#ifdef CONFIG_SPI_HWFEATURES
/* If there are multiple SPI drivers, some may not support hardware
* feature selection.
*/
# define SPI_HWFEATURES(d,f) \
(((d)->ops->hwfeatures) ? (d)->ops->hwfeatures(d,f) : ((f) == 0 ? OK : -ENOSYS))
/* These are currently defined feature flags:
*
* Bit 0: HWFEAT_CRCGENERATION
* Hardware CRC generation
* Bit 1: HWFEAT_FORCE_CS_INACTIVE_AFTER_TRANSFER
* CS rises after every Transmission, also if we provide new data
* immediately
* Bit 2: HWFEAT_FORCE_CS_ACTIVE_AFTER_TRANSFER
* CS does not rise automatically after a transmission, also if
* the spi runs out of data (for a long time)
* Bit 3: HWFEAT_ESCAPE_LASTXFER
* Do not set the LASTXFER-Bit at the last word of the next
* exchange, Flag is auto-resetting after the next LASTXFER
* condition. (see spi_exchange)
* Bit 4: HWFEAT_LSBFIRST
* Data transferred LSB first (default is MSB first)
* Bit 5: Turn deferred trigger mode on or off. Primarily used for DMA
* mode. If a transfer is deferred then the DMA will not actually
* be triggered until a subsequent call to SPI_TRIGGER to set it
* off.
*/
# ifdef CONFIG_SPI_CRCGENERATION
# define HWFEAT_CRCGENERATION (1 << 0)
# endif
# ifdef CONFIG_SPI_CS_CONTROL
# define HWFEAT_FORCE_CS_CONTROL_MASK (7 << 1)
# define HWFEAT_FORCE_CS_INACTIVE_AFTER_TRANSFER (1 << 1)
# define HWFEAT_FORCE_CS_ACTIVE_AFTER_TRANSFER (1 << 2)
# define HWFEAT_ESCAPE_LASTXFER (1 << 3)
# endif
# ifdef CONFIG_SPI_BITORDER
# define HWFEAT_MSBFIRST (0 << 4)
# define HWFEAT_LSBFIRST (1 << 4)
# endif
# ifdef CONFIG_SPI_TRIGGER
# define HWFEAT_TRIGGER (1 << 5)
# endif
#else
/* Any attempt to select hardware features with CONFIG_SPI_HWFEATURES
* deselected will return an -ENOSYS error.
*/
# define SPI_HWFEATURES(d,f) (((f) == 0) ? OK : -ENOSYS)
#endif
/****************************************************************************
* Name: SPI_STATUS
*
* Description:
* Get SPI/MMC status. Optional.
*
* Input Parameters:
* dev - Device-specific state data
* devid - Identifies the device to report status on
*
* Returned Value:
* Returns a bitset of status values (see SPI_STATUS_* defines)
*
****************************************************************************/
#define SPI_STATUS(d,id) \
((d)->ops->status ? (d)->ops->status(d, id) : SPI_STATUS_PRESENT)
/* SPI status bits -- Some dedicated for SPI MMC/SD support and may have no
* relationship to SPI other than needed by the SPI MMC/SD interface
*/
#define SPI_STATUS_PRESENT 0x01 /* Bit 0=1: MMC/SD card present */
#define SPI_STATUS_WRPROTECTED 0x02 /* Bit 1=1: MMC/SD card write protected */
/****************************************************************************
* Name: SPI_CMDDATA
*
* Description:
* Some devices require an additional out-of-band bit to specify if the
* next word sent to the device is a command or data. This is typical, for
* example, in "9-bit" displays where the 9th bit is the CMD/DATA bit.
* This function provides selection of command or data.
*
* This "latches" the CMD/DATA state. It does not have to be called before
* every word is transferred; only when the CMD/DATA state changes. This
* method is required if CONFIG_SPI_CMDDATA is selected in the NuttX
* configuration
*
* Input Parameters:
* dev - Device-specific state data
* cmd - TRUE: The following word is a command; FALSE: the following words
* are data.
*
* Returned Value:
* OK unless an error occurs. Then a negated errno value is returned
*
****************************************************************************/
#ifdef CONFIG_SPI_CMDDATA
# define SPI_CMDDATA(d,id,cmd) ((d)->ops->cmddata(d,id,cmd))
#endif
/****************************************************************************
* Name: SPI_SEND
*
* Description:
* Exchange one word on SPI. Required.
*
* Input Parameters:
* dev - Device-specific state data
* wd - The word to send. The size of the data is determined by the
* number of bits selected for the SPI interface.
*
* Returned Value:
* Received value
*
****************************************************************************/
#define SPI_SEND(d,wd) ((d)->ops->send(d,(uint16_t)(wd)))
/****************************************************************************
* Name: SPI_SNDBLOCK
*
* Description:
* Send a block of data on SPI. Required.
*
* Input Parameters:
* dev - Device-specific state data
* buffer - A pointer to the buffer of data to be sent
* nwords - The length of data to send from the buffer in number of words.
* The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_SPI_EXCHANGE
# define SPI_SNDBLOCK(d,b,l) ((d)->ops->exchange(d,b,0,l))
#else
# define SPI_SNDBLOCK(d,b,l) ((d)->ops->sndblock(d,b,l))
#endif
/****************************************************************************
* Name: SPI_RECVBLOCK
*
* Description:
* Receive a block of data from SPI. Required.
*
* Input Parameters:
* dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data
* nwords - The length of data that can be received in the buffer in number
* of words. The wordsize is determined by the number of bits-
* per-word selected for the SPI interface. If nbits <= 8, the
* data is packed into uint8_t's; if nbits > 8, the data is packed
* into uint16_t's
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_SPI_EXCHANGE
# define SPI_RECVBLOCK(d,b,l) ((d)->ops->exchange(d,0,b,l))
#else
# define SPI_RECVBLOCK(d,b,l) ((d)->ops->recvblock(d,b,l))
#endif
/****************************************************************************
* Name: SPI_EXCHANGE
*
* Description:
* Exchange a block of data from SPI. Required.
*
* Input Parameters:
* dev - Device-specific state data
* txbuffer - A pointer to the buffer of data to be sent
* rxbuffer - A pointer to the buffer in which to receive data
* nwords - The length of data to be exchanged in units of words. The
* wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_SPI_EXCHANGE
# define SPI_EXCHANGE(d,t,r,l) ((d)->ops->exchange(d,t,r,l))
#endif
/****************************************************************************
* Name: SPI_REGISTERCALLBACK
*
* Description:
* Register a callback that will be invoked on any media status change
* (i.e, anything that would be reported differently by SPI_STATUS).
* Optional
*
* Input Parameters:
* dev - Device-specific state data
* callback - The function to call on the media change
* arg - A caller provided value to return with the callback
*
* Returned Value:
* 0 on success; negated errno on failure.
*
****************************************************************************/
#define SPI_REGISTERCALLBACK(d,c,a) \
((d)->ops->registercallback ? (d)->ops->registercallback(d,c,a) : -ENOSYS)
/****************************************************************************
* Name: SPI_TRIGGER
*
* Description:
* Trigger a previously configured DMA transfer.
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* OK - Trigger was fired
* -ENOSYS - Trigger not fired due to lack of DMA or low level support
* -EIO - Trigger not fired because not previously primed
*
****************************************************************************/
# define SPI_TRIGGER(d) \
(((d)->ops->trigger) ? ((d)->ops->trigger(d)) : -ENOSYS)
/* SPI Device Macros ********************************************************/
/* This builds a SPI devid from its type and index */
#define SPIDEV_ID(type,index) ((((uint32_t)(type) & 0xffff) << 16) | \
((uint32_t)(index) & 0xffff))
/* This retrieves the fields from a SPI devid */
#define SPIDEVID_TYPE (devid) (((uint32_t)(devid) >> 16) & 0xffff)
#define SPIDEVID_INDEX(devid) ((uint32_t)(devid) & 0xffff)
/* These are standard definitions for the defined SPI device IDs. The index
* argument, n, is the instance number. This should be zero if there is
* only one instance of the SPI device on the SPI bus. Indices greater than
* zero discriminate the additional devices of the same type on the SPI bus.
*/
#define SPIDEV_NONE(n) SPIDEV_ID(SPIDEVTYPE_NONE, (n))
#define SPIDEV_MMCSD(n) SPIDEV_ID(SPIDEVTYPE_MMCSD, (n))
#define SPIDEV_FLASH(n) SPIDEV_ID(SPIDEVTYPE_FLASH, (n))
#define SPIDEV_ETHERNET(n) SPIDEV_ID(SPIDEVTYPE_ETHERNET, (n))
#define SPIDEV_DISPLAY(n) SPIDEV_ID(SPIDEVTYPE_DISPLAY, (n))
#define SPIDEV_CAMERA(n) SPIDEV_ID(SPIDEVTYPE_CAMERA, (n))
#define SPIDEV_WIRELESS(n) SPIDEV_ID(SPIDEVTYPE_WIRELESS, (n))
#define SPIDEV_TOUCHSCREEN(n) SPIDEV_ID(SPIDEVTYPE_TOUCHSCREEN, (n))
#define SPIDEV_EXPANDER(n) SPIDEV_ID(SPIDEVTYPE_EXPANDER, (n))
#define SPIDEV_MUX(n) SPIDEV_ID(SPIDEVTYPE_MUX, (n))
#define SPIDEV_AUDIO_DATA(n) SPIDEV_ID(SPIDEVTYPE_AUDIO_DATA, (n))
#define SPIDEV_AUDIO_CTRL(n) SPIDEV_ID(SPIDEVTYPE_AUDIO_CTRL, (n))
#define SPIDEV_EEPROM(n) SPIDEV_ID(SPIDEVTYPE_EEPROM, (n))
#define SPIDEV_ACCELEROMETER(n) SPIDEV_ID(SPIDEVTYPE_ACCELEROMETER, (n))
#define SPIDEV_BAROMETER(n) SPIDEV_ID(SPIDEVTYPE_BAROMETER, (n))
#define SPIDEV_TEMPERATURE(n) SPIDEV_ID(SPIDEVTYPE_TEMPERATURE, (n))
#define SPIDEV_IEEE802154(n) SPIDEV_ID(SPIDEVTYPE_IEEE802154, (n))
#define SPIDEV_CONTACTLESS(n) SPIDEV_ID(SPIDEVTYPE_CONTACTLESS, (n))
#define SPIDEV_CANBUS(n) SPIDEV_ID(SPIDEVTYPE_CANBUS, (n))
#define SPIDEV_USBHOST(n) SPIDEV_ID(SPIDEVTYPE_USBHOST, (n))
#define SPIDEV_LPWAN(n) SPIDEV_ID(SPIDEVTYPE_LPWAN, (n))
#define SPIDEV_ADC(n) SPIDEV_ID(SPIDEVTYPE_ADC, (n))
#define SPIDEV_MOTOR(n) SPIDEV_ID(SPIDEVTYPE_MOTOR, (n))
#define SPIDEV_USER(n) SPIDEV_ID(SPIDEVTYPE_USER, (n))
/****************************************************************************
* Public Types
****************************************************************************/
/* The type of the media change callback function */
typedef CODE void (*spi_mediachange_t)(FAR void *arg);
/* If the board supports multiple SPI devices types, this enumeration
* identifies which is selected or de-selected.
* There may be more than one instance of each type on a bus, see below.
*/
enum spi_devtype_e
{
SPIDEVTYPE_NONE = 0, /* Not a valid value */
SPIDEVTYPE_MMCSD, /* Select SPI MMC/SD device */
SPIDEVTYPE_FLASH, /* Select SPI FLASH device */
SPIDEVTYPE_ETHERNET, /* Select SPI Ethernet device */
SPIDEVTYPE_DISPLAY, /* Select SPI LCD/OLED display device */
SPIDEVTYPE_CAMERA, /* Select SPI imaging device */
SPIDEVTYPE_WIRELESS, /* Select SPI Wireless device */
SPIDEVTYPE_TOUCHSCREEN, /* Select SPI touchscreen device */
SPIDEVTYPE_EXPANDER, /* Select SPI I/O expander device */
SPIDEVTYPE_MUX, /* Select SPI multiplexer device */
SPIDEVTYPE_AUDIO_DATA, /* Select SPI audio codec device data port */
SPIDEVTYPE_AUDIO_CTRL, /* Select SPI audio codec device control port */
SPIDEVTYPE_EEPROM, /* Select SPI EEPROM device */
SPIDEVTYPE_ACCELEROMETER, /* Select SPI Accelerometer device */
SPIDEVTYPE_BAROMETER, /* Select SPI Pressure/Barometer device */
SPIDEVTYPE_TEMPERATURE, /* Select SPI Temperature sensor device */
SPIDEVTYPE_IEEE802154, /* Select SPI IEEE 802.15.4 wireless device */
SPIDEVTYPE_CONTACTLESS, /* Select SPI Contactless device */
SPIDEVTYPE_CANBUS, /* Select SPI CAN bus controller over SPI */
SPIDEVTYPE_USBHOST, /* Select SPI USB host controller over SPI */
SPIDEVTYPE_LPWAN, /* Select SPI LPWAN controller over SPI */
SPIDEVTYPE_ADC, /* Select SPI ADC device */
SPIDEVTYPE_MOTOR, /* Select SPI motor device */
SPIDEVTYPE_USER /* Board-specific values start here
* This must always be the last definition. */
};
/* Certain SPI devices may required different clocking modes */
enum spi_mode_e
{
SPIDEV_MODE0 = 0, /* CPOL=0 CPHA=0 */
SPIDEV_MODE1, /* CPOL=0 CPHA=1 */
SPIDEV_MODE2, /* CPOL=1 CPHA=0 */
SPIDEV_MODE3, /* CPOL=1 CPHA=1 */
SPIDEV_MODETI, /* CPOL=0 CPHA=1 TI Synchronous Serial Frame Format */
};
#ifdef CONFIG_SPI_HWFEATURES
/* This is a type wide enough to support all hardware features */
typedef uint8_t spi_hwfeatures_t;
#endif
/* The SPI vtable */
struct spi_dev_s;
struct spi_ops_s
{
CODE int (*lock)(FAR struct spi_dev_s *dev, bool lock);
CODE void (*select)(FAR struct spi_dev_s *dev, uint32_t devid,
bool selected);
CODE uint32_t (*setfrequency)(FAR struct spi_dev_s *dev,
uint32_t frequency);
#ifdef CONFIG_SPI_DELAY_CONTROL
CODE int (*setdelay)(FAR struct spi_dev_s *dev, uint32_t a,
uint32_t b, uint32_t c, uint32_t i);
#endif
CODE void (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
CODE void (*setbits)(FAR struct spi_dev_s *dev, int nbits);
#ifdef CONFIG_SPI_HWFEATURES
CODE int (*hwfeatures)(FAR struct spi_dev_s *dev,
spi_hwfeatures_t features);
#endif
CODE uint8_t (*status)(FAR struct spi_dev_s *dev, uint32_t devid);
#ifdef CONFIG_SPI_CMDDATA
CODE int (*cmddata)(FAR struct spi_dev_s *dev, uint32_t devid,
bool cmd);
#endif
CODE uint32_t (*send)(FAR struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SPI_EXCHANGE
CODE void (*exchange)(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords);
#else
CODE void (*sndblock)(FAR struct spi_dev_s *dev,
FAR const void *buffer, size_t nwords);
CODE void (*recvblock)(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
#endif
#ifdef CONFIG_SPI_TRIGGER
CODE int (*trigger)(FAR struct spi_dev_s *dev);
#endif
CODE int (*registercallback)(FAR struct spi_dev_s *dev,
spi_mediachange_t callback, void *arg);
};
/* SPI private data. This structure only defines the initial fields of the
* structure visible to the SPI client. The specific implementation may
* add additional, device specific fields
*/
struct spi_dev_s
{
FAR const struct spi_ops_s *ops;
};
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __INCLUDE_NUTTX_SPI_SPI_H */