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