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 #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 struct sdhc_command {
47 uint32_t opcode; /*!< SD Host specification CMD index */
48 uint32_t arg; /*!< SD host specification argument */
49 uint32_t response[4]; /*!< SD card response field */
50 uint32_t response_type; /*!< Expected SD response type */
51 unsigned int retries; /*!< Max number of retries */
52 int timeout_ms; /*!< Command timeout in milliseconds */
53 };
54
55 #define SDHC_NATIVE_RESPONSE_MASK 0xF
56 #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 struct sdhc_data {
65 unsigned int block_addr; /*!< Block to start read from */
66 unsigned int block_size; /*!< Block size */
67 unsigned int blocks; /*!< Number of blocks */
68 unsigned int bytes_xfered; /*!< populated with number of bytes sent by SDHC */
69 void *data; /*!< Data to transfer or receive */
70 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 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 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 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 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 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 struct sdhc_host_caps {
164 unsigned int timeout_clk_freq: 5; /**< Timeout clock frequency */
165 unsigned int _rsvd_6: 1; /**< Reserved */
166 unsigned int timeout_clk_unit: 1; /**< Timeout clock unit */
167 unsigned int sd_base_clk: 8; /**< SD base clock frequency */
168 unsigned int max_blk_len: 2; /**< Max block length */
169 unsigned int bus_8_bit_support: 1; /**< 8-bit Support for embedded device */
170 unsigned int bus_4_bit_support: 1; /**< 4 bit bus support */
171 unsigned int adma_2_support: 1; /**< ADMA2 support */
172 unsigned int _rsvd_20: 1; /**< Reserved */
173 unsigned int high_spd_support: 1; /**< High speed support */
174 unsigned int sdma_support: 1; /**< SDMA support */
175 unsigned int suspend_res_support: 1; /**< Suspend/Resume support */
176 unsigned int vol_330_support: 1; /**< Voltage support 3.3V */
177 unsigned int vol_300_support: 1; /**< Voltage support 3.0V */
178 unsigned int vol_180_support: 1; /**< Voltage support 1.8V */
179 unsigned int address_64_bit_support_v4: 1; /**< 64-bit system address support for V4 */
180 unsigned int address_64_bit_support_v3: 1; /**< 64-bit system address support for V3 */
181 unsigned int sdio_async_interrupt_support: 1; /**< Asynchronous interrupt support */
182 unsigned int slot_type: 2; /**< Slot type */
183 unsigned int sdr50_support: 1; /**< SDR50 support */
184 unsigned int sdr104_support: 1; /**< SDR104 support */
185 unsigned int ddr50_support: 1; /**< DDR50 support */
186 unsigned int uhs_2_support: 1; /**< UHS-II support */
187 unsigned int drv_type_a_support: 1; /**< Driver type A support */
188 unsigned int drv_type_c_support: 1; /**< Driver type C support */
189 unsigned int drv_type_d_support: 1; /**< Driver type D support */
190 unsigned int _rsvd_39: 1; /**< Reserved */
191 unsigned int retune_timer_count: 4; /**< Timer count for re-tuning */
192 unsigned int sdr50_needs_tuning: 1; /**< Use tuning for SDR50 */
193 unsigned int retuning_mode: 2; /**< Re-tuning mode */
194 unsigned int clk_multiplier: 8; /**< Clock multiplier */
195 unsigned int _rsvd_56: 3; /**< Reserved */
196 unsigned int adma3_support: 1; /**< ADMA3 support */
197 unsigned int vdd2_180_support: 1; /**< 1.8V VDD2 support */
198 unsigned int _rsvd_61: 3; /**< Reserved */
199 unsigned int hs200_support: 1; /**< HS200 support */
200 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 struct sdhc_io {
211 enum sdhc_clock_speed clock; /*!< Clock rate */
212 enum sdhc_bus_mode bus_mode; /*!< command output mode */
213 enum sdhc_power power_mode; /*!< SD power supply mode */
214 enum sdhc_bus_width bus_width; /*!< SD bus width */
215 enum sdhc_timing_mode timing; /*!< SD bus timing */
216 enum sd_driver_type driver_type; /*!< SD driver type */
217 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 struct sdhc_host_props {
226 unsigned int f_max; /*!< Max bus frequency */
227 unsigned int f_min; /*!< Min bus frequency */
228 unsigned int power_delay; /*!< Delay to allow SD to power up or down (in ms) */
229 struct sdhc_host_caps host_caps; /*!< Host capability bitfield */
230 uint32_t max_current_330; /*!< Max current (in mA) at 3.3V */
231 uint32_t max_current_300; /*!< Max current (in mA) at 3.0V */
232 uint32_t max_current_180; /*!< Max current (in mA) at 1.8V */
233 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 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 typedef void (*sdhc_interrupt_cb_t)(const struct device *dev, int reason,
257 const void *user_data);
258
259 __subsystem struct sdhc_driver_api {
260 int (*reset)(const struct device *dev);
261 int (*request)(const struct device *dev,
262 struct sdhc_command *cmd,
263 struct sdhc_data *data);
264 int (*set_io)(const struct device *dev, struct sdhc_io *ios);
265 int (*get_card_present)(const struct device *dev);
266 int (*execute_tuning)(const struct device *dev);
267 int (*card_busy)(const struct device *dev);
268 int (*get_host_props)(const struct device *dev,
269 struct sdhc_host_props *props);
270 int (*enable_interrupt)(const struct device *dev,
271 sdhc_interrupt_cb_t callback,
272 int sources, void *user_data);
273 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 __syscall int sdhc_hw_reset(const struct device *dev);
289
z_impl_sdhc_hw_reset(const struct device * dev)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 __syscall int sdhc_request(const struct device *dev, struct sdhc_command *cmd,
316 struct sdhc_data *data);
317
z_impl_sdhc_request(const struct device * dev,struct sdhc_command * cmd,struct sdhc_data * data)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 __syscall int sdhc_set_io(const struct device *dev, struct sdhc_io *io);
344
z_impl_sdhc_set_io(const struct device * dev,struct sdhc_io * io)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 __syscall int sdhc_card_present(const struct device *dev);
369
z_impl_sdhc_card_present(const struct device * dev)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 __syscall int sdhc_execute_tuning(const struct device *dev);
394
z_impl_sdhc_execute_tuning(const struct device * dev)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 __syscall int sdhc_card_busy(const struct device *dev);
418
z_impl_sdhc_card_busy(const struct device * dev)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 __syscall int sdhc_get_host_props(const struct device *dev,
442 struct sdhc_host_props *props);
443
z_impl_sdhc_get_host_props(const struct device * dev,struct sdhc_host_props * props)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 __syscall int sdhc_enable_interrupt(const struct device *dev,
472 sdhc_interrupt_cb_t callback,
473 int sources, void *user_data);
474
z_impl_sdhc_enable_interrupt(const struct device * dev,sdhc_interrupt_cb_t callback,int sources,void * user_data)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 __syscall int sdhc_disable_interrupt(const struct device *dev, int sources);
501
z_impl_sdhc_disable_interrupt(const struct device * dev,int sources)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_ */
524