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