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