LCOV - code coverage report
Current view: top level - zephyr/drivers - sdhc.h Hit Total Coverage
Test: new.info Lines: 78 94 83.0 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           1 : /*
       2             :  * Copyright 2022 NXP
       3             :  *
       4             :  * SPDX-License-Identifier: Apache-2.0
       5             :  */
       6             : 
       7             : /**
       8             :  * @file
       9             :  * @brief SD Host Controller public API header file.
      10             :  */
      11             : 
      12             : #ifndef ZEPHYR_INCLUDE_DRIVERS_SDHC_H_
      13             : #define ZEPHYR_INCLUDE_DRIVERS_SDHC_H_
      14             : 
      15             : #include <errno.h>
      16             : #include <zephyr/device.h>
      17             : #include <zephyr/sd/sd_spec.h>
      18             : 
      19             : /**
      20             :  * @brief SDHC interface
      21             :  * @defgroup sdhc_interface SDHC interface
      22             :  * @since 3.1
      23             :  * @version 0.1.0
      24             :  * @ingroup io_interfaces
      25             :  * @{
      26             :  */
      27             : 
      28             : #ifdef __cplusplus
      29             : extern "C" {
      30             : #endif
      31             : 
      32             : 
      33             : /**
      34             :  * @name SD command timeouts
      35             :  * @{
      36             :  */
      37           0 : #define SDHC_TIMEOUT_FOREVER (-1)
      38             : /** @} */
      39             : 
      40             : /**
      41             :  * @brief SD host controller command structure
      42             :  *
      43             :  * This command structure is used to send command requests to an SD
      44             :  * host controller, which will be sent to SD devices.
      45             :  */
      46           1 : struct sdhc_command {
      47           1 :         uint32_t opcode; /*!< SD Host specification CMD index */
      48           1 :         uint32_t arg; /*!< SD host specification argument */
      49           1 :         uint32_t response[4]; /*!< SD card response field */
      50           1 :         uint32_t response_type; /*!< Expected SD response type */
      51           1 :         unsigned int retries; /*!< Max number of retries */
      52           1 :         int timeout_ms; /*!< Command timeout in milliseconds */
      53             : };
      54             : 
      55           0 : #define SDHC_NATIVE_RESPONSE_MASK 0xF
      56           0 : #define SDHC_SPI_RESPONSE_TYPE_MASK 0xF0
      57             : 
      58             : /**
      59             :  * @brief SD host controller data structure
      60             :  *
      61             :  * This command structure is used to send data transfer requests to an SD
      62             :  * host controller, which will be sent to SD devices.
      63             :  */
      64           1 : struct sdhc_data {
      65           1 :         unsigned int block_addr; /*!< Block to start read from */
      66           1 :         unsigned int block_size; /*!< Block size */
      67           1 :         unsigned int blocks; /*!< Number of blocks */
      68           1 :         unsigned int bytes_xfered; /*!< populated with number of bytes sent by SDHC */
      69           1 :         void *data; /*!< Data to transfer or receive */
      70           1 :         int timeout_ms; /*!< data timeout in milliseconds */
      71             : };
      72             : 
      73             : /**
      74             :  * @brief SD bus mode.
      75             :  *
      76             :  * Most controllers will use push/pull, including spi, but
      77             :  * SDHC controllers that implement SD host specification can support open
      78             :  * drain mode
      79             :  */
      80           0 : enum sdhc_bus_mode {
      81             :         SDHC_BUSMODE_OPENDRAIN = 1,
      82             :         SDHC_BUSMODE_PUSHPULL = 2,
      83             : };
      84             : 
      85             : /**
      86             :  * @brief SD host controller power
      87             :  *
      88             :  * Many host controllers can control power to attached SD cards.
      89             :  * This enum allows applications to request the host controller power off
      90             :  * the SD card.
      91             :  */
      92           0 : enum sdhc_power {
      93             :         SDHC_POWER_OFF = 1,
      94             :         SDHC_POWER_ON = 2,
      95             : };
      96             : 
      97             : /**
      98             :  * @brief SD host controller bus width
      99             :  *
     100             :  * Only relevant in SD mode, SPI does not support bus width. UHS cards will
     101             :  * use 4 bit data bus, all cards start in 1 bit mode
     102             :  */
     103           0 : enum sdhc_bus_width {
     104             :         SDHC_BUS_WIDTH1BIT = 1U,
     105             :         SDHC_BUS_WIDTH4BIT = 4U,
     106             :         SDHC_BUS_WIDTH8BIT = 8U,
     107             : };
     108             : 
     109             : /**
     110             :  * @brief SD host controller timing mode
     111             :  *
     112             :  * Used by SD host controller to determine the timing of the cards attached
     113             :  * to the bus. Cards start with legacy timing, but UHS-II cards can go up to
     114             :  * SDR104.
     115             :  */
     116           1 : enum sdhc_timing_mode {
     117             :         SDHC_TIMING_LEGACY = 1U,
     118             :         /*!< Legacy 3.3V Mode */
     119             :         SDHC_TIMING_HS = 2U,
     120             :         /*!< Legacy High speed mode (3.3V) */
     121             :         SDHC_TIMING_SDR12 = 3U,
     122             :         /*!< Identification mode & SDR12 */
     123             :         SDHC_TIMING_SDR25 = 4U,
     124             :         /*!< High speed mode & SDR25 */
     125             :         SDHC_TIMING_SDR50 = 5U,
     126             :         /*!< SDR49 mode*/
     127             :         SDHC_TIMING_SDR104 = 6U,
     128             :         /*!< SDR104 mode */
     129             :         SDHC_TIMING_DDR50 = 7U,
     130             :         /*!< DDR50 mode */
     131             :         SDHC_TIMING_DDR52 = 8U,
     132             :         /*!< DDR52 mode */
     133             :         SDHC_TIMING_HS200 = 9U,
     134             :         /*!< HS200 mode */
     135             :         SDHC_TIMING_HS400 = 10U,
     136             :         /*!< HS400 mode */
     137             : };
     138             : 
     139             : /**
     140             :  * @brief SD voltage
     141             :  *
     142             :  * UHS cards can run with 1.8V signalling for improved power consumption. Legacy
     143             :  * cards may support 3.0V signalling, and all cards start at 3.3V.
     144             :  * Only relevant for SD controllers, not SPI ones.
     145             :  */
     146           1 : enum sd_voltage {
     147             :         SD_VOL_3_3_V = 1U,
     148             :         /*!< card operation voltage around 3.3v */
     149             :         SD_VOL_3_0_V = 2U,
     150             :         /*!< card operation voltage around 3.0v */
     151             :         SD_VOL_1_8_V = 3U,
     152             :         /*!< card operation voltage around 1.8v */
     153             :         SD_VOL_1_2_V = 4U,
     154             :         /*!< card operation voltage around 1.2v */
     155             : };
     156             : 
     157             : /**
     158             :  * @brief SD host controller capabilities
     159             :  *
     160             :  * SD host controller capability flags. These flags should be set by the SDHC
     161             :  * driver, using the @ref sdhc_get_host_props api.
     162             :  */
     163           1 : struct sdhc_host_caps {
     164           1 :         unsigned int timeout_clk_freq: 5;               /**< Timeout clock frequency */
     165             :         unsigned int _rsvd_6: 1;                        /**< Reserved */
     166           1 :         unsigned int timeout_clk_unit: 1;               /**< Timeout clock unit */
     167           1 :         unsigned int sd_base_clk: 8;                    /**< SD base clock frequency */
     168           1 :         unsigned int max_blk_len: 2;                    /**< Max block length */
     169           1 :         unsigned int bus_8_bit_support: 1;              /**< 8-bit Support for embedded device */
     170           1 :         unsigned int bus_4_bit_support: 1;              /**< 4 bit bus support */
     171           1 :         unsigned int adma_2_support: 1;                 /**< ADMA2 support */
     172             :         unsigned int _rsvd_20: 1;                       /**< Reserved */
     173           1 :         unsigned int high_spd_support: 1;               /**< High speed support */
     174           1 :         unsigned int sdma_support: 1;                   /**< SDMA support */
     175           1 :         unsigned int suspend_res_support: 1;            /**< Suspend/Resume support */
     176           1 :         unsigned int vol_330_support: 1;                /**< Voltage support 3.3V */
     177           1 :         unsigned int vol_300_support: 1;                /**< Voltage support 3.0V */
     178           1 :         unsigned int vol_180_support: 1;                /**< Voltage support 1.8V */
     179           1 :         unsigned int address_64_bit_support_v4: 1;      /**< 64-bit system address support for V4 */
     180           1 :         unsigned int address_64_bit_support_v3: 1;      /**< 64-bit system address support for V3 */
     181           1 :         unsigned int sdio_async_interrupt_support: 1;   /**< Asynchronous interrupt support */
     182           1 :         unsigned int slot_type: 2;                      /**< Slot type */
     183           1 :         unsigned int sdr50_support: 1;                  /**< SDR50 support */
     184           1 :         unsigned int sdr104_support: 1;                 /**< SDR104 support */
     185           1 :         unsigned int ddr50_support: 1;                  /**< DDR50 support */
     186           1 :         unsigned int uhs_2_support: 1;                  /**< UHS-II support */
     187           1 :         unsigned int drv_type_a_support: 1;             /**< Driver type A support */
     188           1 :         unsigned int drv_type_c_support: 1;             /**< Driver type C support */
     189           1 :         unsigned int drv_type_d_support: 1;             /**< Driver type D support */
     190             :         unsigned int _rsvd_39: 1;                       /**< Reserved */
     191           1 :         unsigned int retune_timer_count: 4;             /**< Timer count for re-tuning */
     192           1 :         unsigned int sdr50_needs_tuning: 1;             /**< Use tuning for SDR50 */
     193           1 :         unsigned int retuning_mode: 2;                  /**< Re-tuning mode */
     194           1 :         unsigned int clk_multiplier: 8;                 /**< Clock multiplier */
     195             :         unsigned int _rsvd_56: 3;                       /**< Reserved */
     196           1 :         unsigned int adma3_support: 1;                  /**< ADMA3 support */
     197           1 :         unsigned int vdd2_180_support: 1;               /**< 1.8V VDD2 support */
     198             :         unsigned int _rsvd_61: 3;                       /**< Reserved */
     199           1 :         unsigned int hs200_support: 1;                  /**< HS200 support */
     200           1 :         unsigned int hs400_support: 1;                  /**< HS400 support */
     201             : };
     202             : 
     203             : /**
     204             :  * @brief SD host controller I/O control structure
     205             :  *
     206             :  * Controls I/O settings for the SDHC. Note that only a subset of these settings
     207             :  * apply to host controllers in SPI mode. Populate this struct, then call
     208             :  * @ref sdhc_set_io to apply I/O settings
     209             :  */
     210           1 : struct sdhc_io {
     211           1 :         enum sdhc_clock_speed clock; /*!< Clock rate */
     212           1 :         enum sdhc_bus_mode bus_mode; /*!< command output mode */
     213           1 :         enum sdhc_power power_mode; /*!< SD power supply mode */
     214           1 :         enum sdhc_bus_width bus_width; /*!< SD bus width */
     215           1 :         enum sdhc_timing_mode timing; /*!< SD bus timing */
     216           1 :         enum sd_driver_type driver_type; /*!< SD driver type */
     217           1 :         enum sd_voltage signal_voltage; /*!< IO signalling voltage (usually 1.8 or 3.3V) */
     218             : };
     219             : 
     220             : /**
     221             :  * @brief SD host controller properties
     222             :  *
     223             :  * Populated by the host controller using @ref sdhc_get_host_props api.
     224             :  */
     225           1 : struct sdhc_host_props {
     226           1 :         unsigned int f_max; /*!< Max bus frequency */
     227           1 :         unsigned int f_min; /*!< Min bus frequency */
     228           1 :         unsigned int power_delay; /*!< Delay to allow SD to power up or down (in ms) */
     229           1 :         struct sdhc_host_caps host_caps; /*!< Host capability bitfield */
     230           1 :         uint32_t max_current_330; /*!< Max current (in mA) at 3.3V */
     231           1 :         uint32_t max_current_300; /*!< Max current (in mA) at 3.0V */
     232           1 :         uint32_t max_current_180; /*!< Max current (in mA) at 1.8V */
     233           1 :         bool is_spi; /*!< Is the host using SPI mode */
     234             : };
     235             : 
     236             : /**
     237             :  * @brief SD host controller interrupt sources
     238             :  *
     239             :  * Interrupt sources for SD host controller.
     240             :  */
     241           1 : enum sdhc_interrupt_source {
     242             :         SDHC_INT_SDIO = BIT(0), /*!< Card interrupt, used by SDIO cards */
     243             :         SDHC_INT_INSERTED = BIT(1), /*!< Card was inserted into slot */
     244             :         SDHC_INT_REMOVED = BIT(2), /*!< Card was removed from slot */
     245             : };
     246             : 
     247             : /**
     248             :  * @typedef sdhc_interrupt_cb_t
     249             :  * @brief SDHC card interrupt callback prototype
     250             :  *
     251             :  * Function prototype for SDHC card interrupt callback.
     252             :  * @param dev: SDHC device that produced interrupt
     253             :  * @param reason: one of @ref sdhc_interrupt_source values.
     254             :  * @param user_data: User data, set via @ref sdhc_enable_interrupt
     255             :  */
     256           1 : typedef void (*sdhc_interrupt_cb_t)(const struct device *dev, int reason,
     257             :                                     const void *user_data);
     258             : 
     259           0 : __subsystem struct sdhc_driver_api {
     260           0 :         int (*reset)(const struct device *dev);
     261           0 :         int (*request)(const struct device *dev,
     262             :                        struct sdhc_command *cmd,
     263             :                        struct sdhc_data *data);
     264           0 :         int (*set_io)(const struct device *dev, struct sdhc_io *ios);
     265           0 :         int (*get_card_present)(const struct device *dev);
     266           0 :         int (*execute_tuning)(const struct device *dev);
     267           0 :         int (*card_busy)(const struct device *dev);
     268           0 :         int (*get_host_props)(const struct device *dev,
     269             :                               struct sdhc_host_props *props);
     270           0 :         int (*enable_interrupt)(const struct device *dev,
     271             :                                 sdhc_interrupt_cb_t callback,
     272             :                                 int sources, void *user_data);
     273           0 :         int (*disable_interrupt)(const struct device *dev, int sources);
     274             : };
     275             : 
     276             : /**
     277             :  * @brief reset SDHC controller state
     278             :  *
     279             :  * Used when the SDHC has encountered an error. Resetting the SDHC controller
     280             :  * should clear all errors on the SDHC, but does not necessarily reset I/O
     281             :  * settings to boot (this can be done with @ref sdhc_set_io)
     282             :  *
     283             :  * @param dev: SD host controller device
     284             :  * @retval 0 reset succeeded
     285             :  * @retval -ETIMEDOUT: controller reset timed out
     286             :  * @retval -EIO: reset failed
     287             :  */
     288           1 : __syscall int sdhc_hw_reset(const struct device *dev);
     289             : 
     290             : static inline int z_impl_sdhc_hw_reset(const struct device *dev)
     291             : {
     292             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     293             : 
     294             :         if (!api->reset) {
     295             :                 return -ENOSYS;
     296             :         }
     297             : 
     298             :         return api->reset(dev);
     299             : }
     300             : 
     301             : 
     302             : /**
     303             :  * @brief Send command to SDHC
     304             :  *
     305             :  * Sends a command to the SD host controller, which will send this command to
     306             :  * attached SD cards.
     307             :  * @param dev: SDHC device
     308             :  * @param cmd: SDHC command
     309             :  * @param data: SDHC data. Leave NULL to send SD command without data.
     310             :  * @retval 0 command was sent successfully
     311             :  * @retval -ETIMEDOUT command timed out while sending
     312             :  * @retval -ENOTSUP host controller does not support command
     313             :  * @retval -EIO: I/O error
     314             :  */
     315           1 : __syscall int sdhc_request(const struct device *dev, struct sdhc_command *cmd,
     316             :                            struct sdhc_data *data);
     317             : 
     318             : static inline int z_impl_sdhc_request(const struct device *dev,
     319             :                                       struct sdhc_command *cmd,
     320             :                                       struct sdhc_data *data)
     321             : {
     322             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     323             : 
     324             :         if (!api->request) {
     325             :                 return -ENOSYS;
     326             :         }
     327             : 
     328             :         return api->request(dev, cmd, data);
     329             : }
     330             : 
     331             : /**
     332             :  * @brief set I/O properties of SDHC
     333             :  *
     334             :  * I/O properties should be reconfigured when the card has been sent a command
     335             :  * to change its own SD settings. This function can also be used to toggle
     336             :  * power to the SD card.
     337             :  * @param dev: SDHC device
     338             :  * @param io: I/O properties
     339             :  * @return 0 I/O was configured correctly
     340             :  * @return -ENOTSUP controller does not support these I/O settings
     341             :  * @return -EIO controller could not configure I/O settings
     342             :  */
     343           1 : __syscall int sdhc_set_io(const struct device *dev, struct sdhc_io *io);
     344             : 
     345             : static inline int z_impl_sdhc_set_io(const struct device *dev,
     346             :                                      struct sdhc_io *io)
     347             : {
     348             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     349             : 
     350             :         if (!api->set_io) {
     351             :                 return -ENOSYS;
     352             :         }
     353             : 
     354             :         return api->set_io(dev, io);
     355             : }
     356             : 
     357             : /**
     358             :  * @brief check for SDHC card presence
     359             :  *
     360             :  * Checks if card is present on the SD bus. Note that if a controller
     361             :  * requires cards be powered up to detect presence, it should do so in
     362             :  * this function.
     363             :  * @param dev: SDHC device
     364             :  * @retval 1 card is present
     365             :  * @retval 0 card is not present
     366             :  * @retval -EIO I/O error
     367             :  */
     368           1 : __syscall int sdhc_card_present(const struct device *dev);
     369             : 
     370             : static inline int z_impl_sdhc_card_present(const struct device *dev)
     371             : {
     372             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     373             : 
     374             :         if (!api->get_card_present) {
     375             :                 return -ENOSYS;
     376             :         }
     377             : 
     378             :         return api->get_card_present(dev);
     379             : }
     380             : 
     381             : 
     382             : /**
     383             :  * @brief run SDHC tuning
     384             :  *
     385             :  * SD cards require signal tuning for UHS modes SDR104 and SDR50. This function
     386             :  * allows an application to request the SD host controller to tune the card.
     387             :  * @param dev: SDHC device
     388             :  * @retval 0 tuning succeeded, card is ready for commands
     389             :  * @retval -ETIMEDOUT: tuning failed after timeout
     390             :  * @retval -ENOTSUP: controller does not support tuning
     391             :  * @retval -EIO: I/O error while tuning
     392             :  */
     393           1 : __syscall int sdhc_execute_tuning(const struct device *dev);
     394             : 
     395             : static inline int z_impl_sdhc_execute_tuning(const struct device *dev)
     396             : {
     397             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     398             : 
     399             :         if (!api->execute_tuning) {
     400             :                 return -ENOSYS;
     401             :         }
     402             : 
     403             :         return api->execute_tuning(dev);
     404             : }
     405             : 
     406             : /**
     407             :  * @brief check if SD card is busy
     408             :  *
     409             :  * This check should generally be implemented as checking the line level of the
     410             :  * DAT[0:3] lines of the SD bus. No SD commands need to be sent, the controller
     411             :  * simply needs to report the status of the SD bus.
     412             :  * @param dev: SDHC device
     413             :  * @retval 0 card is not busy
     414             :  * @retval 1 card is busy
     415             :  * @retval -EIO I/O error
     416             :  */
     417           1 : __syscall int sdhc_card_busy(const struct device *dev);
     418             : 
     419             : static inline int z_impl_sdhc_card_busy(const struct device *dev)
     420             : {
     421             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     422             : 
     423             :         if (!api->card_busy) {
     424             :                 return -ENOSYS;
     425             :         }
     426             : 
     427             :         return api->card_busy(dev);
     428             : }
     429             : 
     430             : 
     431             : /**
     432             :  * @brief Get SD host controller properties
     433             :  *
     434             :  * Gets host properties from the host controller. Host controller should
     435             :  * initialize all values in the @ref sdhc_host_props structure provided.
     436             :  * @param dev: SDHC device
     437             :  * @param props property structure to be filled by sdhc driver
     438             :  * @retval 0 function succeeded.
     439             :  * @retval -ENOTSUP host controller does not support this call
     440             :  */
     441           1 : __syscall int sdhc_get_host_props(const struct device *dev,
     442             :                                   struct sdhc_host_props *props);
     443             : 
     444             : static inline int z_impl_sdhc_get_host_props(const struct device *dev,
     445             :                                              struct sdhc_host_props *props)
     446             : {
     447             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     448             : 
     449             :         if (!api->get_host_props) {
     450             :                 return -ENOSYS;
     451             :         }
     452             : 
     453             :         return api->get_host_props(dev, props);
     454             : }
     455             : 
     456             : /**
     457             :  * @brief Enable SDHC interrupt sources.
     458             :  *
     459             :  * Enables SDHC interrupt sources. Each subsequent call of this function
     460             :  * should replace the previous callback set, and leave only the interrupts
     461             :  * specified in the "sources" argument enabled.
     462             :  * @param dev: SDHC device
     463             :  * @param callback: Callback called when interrupt occurs
     464             :  * @param sources: bitmask of @ref sdhc_interrupt_source values
     465             :  *        indicating which interrupts should produce a callback
     466             :  * @param user_data: parameter that will be passed to callback function
     467             :  * @retval 0 interrupts were enabled, and callback was installed
     468             :  * @retval -ENOTSUP: controller does not support this function
     469             :  * @retval -EIO: I/O error
     470             :  */
     471           1 : __syscall int sdhc_enable_interrupt(const struct device *dev,
     472             :                                     sdhc_interrupt_cb_t callback,
     473             :                                     int sources, void *user_data);
     474             : 
     475             : static inline int z_impl_sdhc_enable_interrupt(const struct device *dev,
     476             :                                                sdhc_interrupt_cb_t callback,
     477             :                                                int sources, void *user_data)
     478             : {
     479             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     480             : 
     481             :         if (!api->enable_interrupt) {
     482             :                 return -ENOSYS;
     483             :         }
     484             : 
     485             :         return api->enable_interrupt(dev, callback, sources, user_data);
     486             : }
     487             : 
     488             : /**
     489             :  * @brief Disable SDHC interrupt sources
     490             :  *
     491             :  * Disables SDHC interrupt sources. If multiple sources are enabled, only
     492             :  * the ones specified in "sources" will be masked.
     493             :  * @param dev: SDHC device
     494             :  * @param sources: bitmask of @ref sdhc_interrupt_source values
     495             :  *        indicating which interrupts should be disabled.
     496             :  * @retval 0 interrupts were disabled
     497             :  * @retval -ENOTSUP: controller does not support this function
     498             :  * @retval -EIO: I/O error
     499             :  */
     500           1 : __syscall int sdhc_disable_interrupt(const struct device *dev, int sources);
     501             : 
     502             : static inline int z_impl_sdhc_disable_interrupt(const struct device *dev,
     503             :                                                 int sources)
     504             : {
     505             :         const struct sdhc_driver_api *api = (const struct sdhc_driver_api *)dev->api;
     506             : 
     507             :         if (!api->disable_interrupt) {
     508             :                 return -ENOSYS;
     509             :         }
     510             : 
     511             :         return api->disable_interrupt(dev, sources);
     512             : }
     513             : 
     514             : /**
     515             :  * @}
     516             :  */
     517             : 
     518             : #ifdef __cplusplus
     519             : }
     520             : #endif
     521             : 
     522             : #include <zephyr/syscalls/sdhc.h>
     523             : #endif /* ZEPHYR_INCLUDE_DRIVERS_SDHC_H_ */

Generated by: LCOV version 1.14