zephyr/include/zephyr/drivers/sdhc.h
Yong Cong Sin bbe5e1e6eb build: namespace the generated headers with zephyr/
Namespaced the generated headers with `zephyr` to prevent
potential conflict with other headers.

Introduce a temporary Kconfig `LEGACY_GENERATED_INCLUDE_PATH`
that is enabled by default. This allows the developers to
continue the use of the old include paths for the time being
until it is deprecated and eventually removed. The Kconfig will
generate a build-time warning message, similar to the
`CONFIG_TIMER_RANDOM_GENERATOR`.

Updated the includes path of in-tree sources accordingly.

Most of the changes here are scripted, check the PR for more
info.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
2024-05-28 22:03:55 +02:00

524 lines
16 KiB
C

/*
* Copyright 2022 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief SD Host Controller public API header file.
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_SDHC_H_
#define ZEPHYR_INCLUDE_DRIVERS_SDHC_H_
#include <errno.h>
#include <zephyr/device.h>
#include <zephyr/sd/sd_spec.h>
/**
* @brief SDHC interface
* @defgroup sdhc_interface SDHC interface
* @since 3.1
* @version 0.1.0
* @ingroup io_interfaces
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name SD command timeouts
* @{
*/
#define SDHC_TIMEOUT_FOREVER (-1)
/** @} */
/**
* @brief SD host controller command structure
*
* This command structure is used to send command requests to an SD
* host controller, which will be sent to SD devices.
*/
struct sdhc_command {
uint32_t opcode; /*!< SD Host specification CMD index */
uint32_t arg; /*!< SD host specification argument */
uint32_t response[4]; /*!< SD card response field */
uint32_t response_type; /*!< Expected SD response type */
unsigned int retries; /*!< Max number of retries */
int timeout_ms; /*!< Command timeout in milliseconds */
};
#define SDHC_NATIVE_RESPONSE_MASK 0xF
#define SDHC_SPI_RESPONSE_TYPE_MASK 0xF0
/**
* @brief SD host controller data structure
*
* This command structure is used to send data transfer requests to an SD
* host controller, which will be sent to SD devices.
*/
struct sdhc_data {
unsigned int block_addr; /*!< Block to start read from */
unsigned int block_size; /*!< Block size */
unsigned int blocks; /*!< Number of blocks */
unsigned int bytes_xfered; /*!< populated with number of bytes sent by SDHC */
void *data; /*!< Data to transfer or receive */
int timeout_ms; /*!< data timeout in milliseconds */
};
/**
* @brief SD bus mode.
*
* Most controllers will use push/pull, including spi, but
* SDHC controllers that implement SD host specification can support open
* drain mode
*/
enum sdhc_bus_mode {
SDHC_BUSMODE_OPENDRAIN = 1,
SDHC_BUSMODE_PUSHPULL = 2,
};
/**
* @brief SD host controller power
*
* Many host controllers can control power to attached SD cards.
* This enum allows applications to request the host controller power off
* the SD card.
*/
enum sdhc_power {
SDHC_POWER_OFF = 1,
SDHC_POWER_ON = 2,
};
/**
* @brief SD host controller bus width
*
* Only relevant in SD mode, SPI does not support bus width. UHS cards will
* use 4 bit data bus, all cards start in 1 bit mode
*/
enum sdhc_bus_width {
SDHC_BUS_WIDTH1BIT = 1U,
SDHC_BUS_WIDTH4BIT = 4U,
SDHC_BUS_WIDTH8BIT = 8U,
};
/**
* @brief SD host controller timing mode
*
* Used by SD host controller to determine the timing of the cards attached
* to the bus. Cards start with legacy timing, but UHS-II cards can go up to
* SDR104.
*/
enum sdhc_timing_mode {
SDHC_TIMING_LEGACY = 1U,
/*!< Legacy 3.3V Mode */
SDHC_TIMING_HS = 2U,
/*!< Legacy High speed mode (3.3V) */
SDHC_TIMING_SDR12 = 3U,
/*!< Identification mode & SDR12 */
SDHC_TIMING_SDR25 = 4U,
/*!< High speed mode & SDR25 */
SDHC_TIMING_SDR50 = 5U,
/*!< SDR49 mode*/
SDHC_TIMING_SDR104 = 6U,
/*!< SDR104 mode */
SDHC_TIMING_DDR50 = 7U,
/*!< DDR50 mode */
SDHC_TIMING_DDR52 = 8U,
/*!< DDR52 mode */
SDHC_TIMING_HS200 = 9U,
/*!< HS200 mode */
SDHC_TIMING_HS400 = 10U,
/*!< HS400 mode */
};
/**
* @brief SD voltage
*
* UHS cards can run with 1.8V signalling for improved power consumption. Legacy
* cards may support 3.0V signalling, and all cards start at 3.3V.
* Only relevant for SD controllers, not SPI ones.
*/
enum sd_voltage {
SD_VOL_3_3_V = 1U,
/*!< card operation voltage around 3.3v */
SD_VOL_3_0_V = 2U,
/*!< card operation voltage around 3.0v */
SD_VOL_1_8_V = 3U,
/*!< card operation voltage around 1.8v */
SD_VOL_1_2_V = 4U,
/*!< card operation voltage around 1.2v */
};
/**
* @brief SD host controller capabilities
*
* SD host controller capability flags. These flags should be set by the SDHC
* driver, using the @ref sdhc_get_host_props api.
*/
struct sdhc_host_caps {
unsigned int timeout_clk_freq: 5; /**< Timeout clock frequency */
unsigned int _rsvd_6: 1; /**< Reserved */
unsigned int timeout_clk_unit: 1; /**< Timeout clock unit */
unsigned int sd_base_clk: 8; /**< SD base clock frequency */
unsigned int max_blk_len: 2; /**< Max block length */
unsigned int bus_8_bit_support: 1; /**< 8-bit Support for embedded device */
unsigned int bus_4_bit_support: 1; /**< 4 bit bus support */
unsigned int adma_2_support: 1; /**< ADMA2 support */
unsigned int _rsvd_20: 1; /**< Reserved */
unsigned int high_spd_support: 1; /**< High speed support */
unsigned int sdma_support: 1; /**< SDMA support */
unsigned int suspend_res_support: 1; /**< Suspend/Resume support */
unsigned int vol_330_support: 1; /**< Voltage support 3.3V */
unsigned int vol_300_support: 1; /**< Voltage support 3.0V */
unsigned int vol_180_support: 1; /**< Voltage support 1.8V */
unsigned int address_64_bit_support_v4: 1; /**< 64-bit system address support for V4 */
unsigned int address_64_bit_support_v3: 1; /**< 64-bit system address support for V3 */
unsigned int sdio_async_interrupt_support: 1; /**< Asynchronous interrupt support */
unsigned int slot_type: 2; /**< Slot type */
unsigned int sdr50_support: 1; /**< SDR50 support */
unsigned int sdr104_support: 1; /**< SDR104 support */
unsigned int ddr50_support: 1; /**< DDR50 support */
unsigned int uhs_2_support: 1; /**< UHS-II support */
unsigned int drv_type_a_support: 1; /**< Driver type A support */
unsigned int drv_type_c_support: 1; /**< Driver type C support */
unsigned int drv_type_d_support: 1; /**< Driver type D support */
unsigned int _rsvd_39: 1; /**< Reserved */
unsigned int retune_timer_count: 4; /**< Timer count for re-tuning */
unsigned int sdr50_needs_tuning: 1; /**< Use tuning for SDR50 */
unsigned int retuning_mode: 2; /**< Re-tuning mode */
unsigned int clk_multiplier: 8; /**< Clock multiplier */
unsigned int _rsvd_56: 3; /**< Reserved */
unsigned int adma3_support: 1; /**< ADMA3 support */
unsigned int vdd2_180_support: 1; /**< 1.8V VDD2 support */
unsigned int _rsvd_61: 3; /**< Reserved */
unsigned int hs200_support: 1; /**< HS200 support */
unsigned int hs400_support: 1; /**< HS400 support */
};
/**
* @brief SD host controller I/O control structure
*
* Controls I/O settings for the SDHC. Note that only a subset of these settings
* apply to host controllers in SPI mode. Populate this struct, then call
* @ref sdhc_set_io to apply I/O settings
*/
struct sdhc_io {
enum sdhc_clock_speed clock; /*!< Clock rate */
enum sdhc_bus_mode bus_mode; /*!< command output mode */
enum sdhc_power power_mode; /*!< SD power supply mode */
enum sdhc_bus_width bus_width; /*!< SD bus width */
enum sdhc_timing_mode timing; /*!< SD bus timing */
enum sd_driver_type driver_type; /*!< SD driver type */
enum sd_voltage signal_voltage; /*!< IO signalling voltage (usually 1.8 or 3.3V) */
};
/**
* @brief SD host controller properties
*
* Populated by the host controller using @ref sdhc_get_host_props api.
*/
struct sdhc_host_props {
unsigned int f_max; /*!< Max bus frequency */
unsigned int f_min; /*!< Min bus frequency */
unsigned int power_delay; /*!< Delay to allow SD to power up or down (in ms) */
struct sdhc_host_caps host_caps; /*!< Host capability bitfield */
uint32_t max_current_330; /*!< Max current (in mA) at 3.3V */
uint32_t max_current_300; /*!< Max current (in mA) at 3.0V */
uint32_t max_current_180; /*!< Max current (in mA) at 1.8V */
bool is_spi; /*!< Is the host using SPI mode */
};
/**
* @brief SD host controller interrupt sources
*
* Interrupt sources for SD host controller.
*/
enum sdhc_interrupt_source {
SDHC_INT_SDIO = BIT(0), /*!< Card interrupt, used by SDIO cards */
SDHC_INT_INSERTED = BIT(1), /*!< Card was inserted into slot */
SDHC_INT_REMOVED = BIT(2), /*!< Card was removed from slot */
};
/**
* @typedef sdhc_interrupt_cb_t
* @brief SDHC card interrupt callback prototype
*
* Function prototype for SDHC card interrupt callback.
* @param dev: SDHC device that produced interrupt
* @param reason: one of @ref sdhc_interrupt_source values.
* @param user_data: User data, set via @ref sdhc_enable_interrupt
*/
typedef void (*sdhc_interrupt_cb_t)(const struct device *dev, int reason,
const void *user_data);
__subsystem struct sdhc_driver_api {
int (*reset)(const struct device *dev);
int (*request)(const struct device *dev,
struct sdhc_command *cmd,
struct sdhc_data *data);
int (*set_io)(const struct device *dev, struct sdhc_io *ios);
int (*get_card_present)(const struct device *dev);
int (*execute_tuning)(const struct device *dev);
int (*card_busy)(const struct device *dev);
int (*get_host_props)(const struct device *dev,
struct sdhc_host_props *props);
int (*enable_interrupt)(const struct device *dev,
sdhc_interrupt_cb_t callback,
int sources, void *user_data);
int (*disable_interrupt)(const struct device *dev, int sources);
};
/**
* @brief reset SDHC controller state
*
* Used when the SDHC has encountered an error. Resetting the SDHC controller
* should clear all errors on the SDHC, but does not necessarily reset I/O
* settings to boot (this can be done with @ref sdhc_set_io)
*
* @param dev: SD host controller device
* @retval 0 reset succeeded
* @retval -ETIMEDOUT: controller reset timed out
* @retval -EIO: reset failed
*/
__syscall int sdhc_hw_reset(const struct device *dev);
static inline int z_impl_sdhc_hw_reset(const struct device *dev)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->reset) {
return -ENOSYS;
}
return api->reset(dev);
}
/**
* @brief Send command to SDHC
*
* Sends a command to the SD host controller, which will send this command to
* attached SD cards.
* @param dev: SDHC device
* @param cmd: SDHC command
* @param data: SDHC data. Leave NULL to send SD command without data.
* @retval 0 command was sent successfully
* @retval -ETIMEDOUT command timed out while sending
* @retval -ENOTSUP host controller does not support command
* @retval -EIO: I/O error
*/
__syscall int sdhc_request(const struct device *dev, struct sdhc_command *cmd,
struct sdhc_data *data);
static inline int z_impl_sdhc_request(const struct device *dev,
struct sdhc_command *cmd,
struct sdhc_data *data)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->request) {
return -ENOSYS;
}
return api->request(dev, cmd, data);
}
/**
* @brief set I/O properties of SDHC
*
* I/O properties should be reconfigured when the card has been sent a command
* to change its own SD settings. This function can also be used to toggle
* power to the SD card.
* @param dev: SDHC device
* @param io: I/O properties
* @return 0 I/O was configured correctly
* @return -ENOTSUP controller does not support these I/O settings
* @return -EIO controller could not configure I/O settings
*/
__syscall int sdhc_set_io(const struct device *dev, struct sdhc_io *io);
static inline int z_impl_sdhc_set_io(const struct device *dev,
struct sdhc_io *io)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->set_io) {
return -ENOSYS;
}
return api->set_io(dev, io);
}
/**
* @brief check for SDHC card presence
*
* Checks if card is present on the SD bus. Note that if a controller
* requires cards be powered up to detect presence, it should do so in
* this function.
* @param dev: SDHC device
* @retval 1 card is present
* @retval 0 card is not present
* @retval -EIO I/O error
*/
__syscall int sdhc_card_present(const struct device *dev);
static inline int z_impl_sdhc_card_present(const struct device *dev)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->get_card_present) {
return -ENOSYS;
}
return api->get_card_present(dev);
}
/**
* @brief run SDHC tuning
*
* SD cards require signal tuning for UHS modes SDR104 and SDR50. This function
* allows an application to request the SD host controller to tune the card.
* @param dev: SDHC device
* @retval 0 tuning succeeded, card is ready for commands
* @retval -ETIMEDOUT: tuning failed after timeout
* @retval -ENOTSUP: controller does not support tuning
* @retval -EIO: I/O error while tuning
*/
__syscall int sdhc_execute_tuning(const struct device *dev);
static inline int z_impl_sdhc_execute_tuning(const struct device *dev)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->execute_tuning) {
return -ENOSYS;
}
return api->execute_tuning(dev);
}
/**
* @brief check if SD card is busy
*
* This check should generally be implemented as checking the line level of the
* DAT[0:3] lines of the SD bus. No SD commands need to be sent, the controller
* simply needs to report the status of the SD bus.
* @param dev: SDHC device
* @retval 0 card is not busy
* @retval 1 card is busy
* @retval -EIO I/O error
*/
__syscall int sdhc_card_busy(const struct device *dev);
static inline int z_impl_sdhc_card_busy(const struct device *dev)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->card_busy) {
return -ENOSYS;
}
return api->card_busy(dev);
}
/**
* @brief Get SD host controller properties
*
* Gets host properties from the host controller. Host controller should
* initialize all values in the @ref sdhc_host_props structure provided.
* @param dev: SDHC device
* @param props property structure to be filled by sdhc driver
* @retval 0 function succeeded.
* @retval -ENOTSUP host controller does not support this call
*/
__syscall int sdhc_get_host_props(const struct device *dev,
struct sdhc_host_props *props);
static inline int z_impl_sdhc_get_host_props(const struct device *dev,
struct sdhc_host_props *props)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->get_host_props) {
return -ENOSYS;
}
return api->get_host_props(dev, props);
}
/**
* @brief Enable SDHC interrupt sources.
*
* Enables SDHC interrupt sources. Each subsequent call of this function
* should replace the previous callback set, and leave only the interrupts
* specified in the "sources" argument enabled.
* @param dev: SDHC device
* @param callback: Callback called when interrupt occurs
* @param sources: bitmask of @ref sdhc_interrupt_source values
* indicating which interrupts should produce a callback
* @param user_data: parameter that will be passed to callback function
* @retval 0 interrupts were enabled, and callback was installed
* @retval -ENOTSUP: controller does not support this function
* @retval -EIO: I/O error
*/
__syscall int sdhc_enable_interrupt(const struct device *dev,
sdhc_interrupt_cb_t callback,
int sources, void *user_data);
static inline int z_impl_sdhc_enable_interrupt(const struct device *dev,
sdhc_interrupt_cb_t callback,
int sources, void *user_data)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->enable_interrupt) {
return -ENOSYS;
}
return api->enable_interrupt(dev, callback, sources, user_data);
}
/**
* @brief Disable SDHC interrupt sources
*
* Disables SDHC interrupt sources. If multiple sources are enabled, only
* the ones specified in "sources" will be masked.
* @param dev: SDHC device
* @param sources: bitmask of @ref sdhc_interrupt_source values
* indicating which interrupts should be disabled.
* @retval 0 interrupts were disabled
* @retval -ENOTSUP: controller does not support this function
* @retval -EIO: I/O error
*/
__syscall int sdhc_disable_interrupt(const struct device *dev, int sources);
static inline int z_impl_sdhc_disable_interrupt(const struct device *dev,
int sources)
{
const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
if (!api->disable_interrupt) {
return -ENOSYS;
}
return api->disable_interrupt(dev, sources);
}
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#include <zephyr/syscalls/sdhc.h>
#endif /* ZEPHYR_INCLUDE_DRIVERS_SDHC_H_ */