ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_sdhi.c
Go to the documentation of this file.
1
42
43#include "ra8_sdhi.h"
44
45#include <stdint.h>
46
47#include "ra8_attributes.h"
48#include "ra8_check.h"
49#include "ra8_err.h"
50#include "ra8_hw_err.h"
51#include "ra8_log.h"
52#include "ra8_mstp.h"
53#include "ra8_mstp_regs.h"
54#include "ra8_sdhi_regs.h"
55
56static const char* s_tag = "SDHI";
57
66
68static void* s_sdhi_ctx;
69
91
102typedef enum : uint32_t {
105
106ra8_err_t ra8_sdhi_init(uint8_t instance)
107{
108 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
109 RA8_CHECK_NULL_PTR(reg, s_tag, "instance out of range");
110
111 /* HUM Ch 11.2.7 "MSTPCRB : Module Stop Control Register B" p 444 */
112 const ra8_err_t mst_err = ra8_mstp_enable(s_sdhi_mstp_table[instance]);
113 /* GCOVR_EXCL_BR_START -- MSTP HW readback */
114 RA8_RETURN_ON_ERROR(mst_err, s_tag, "sdhi_init: mstp enable");
115 /* GCOVR_EXCL_BR_STOP */
116
117 /* HUM Ch 47.2.15 "SD_INFO1 : SD Card Interrupt Flag Register 1" p 3129 */
118 /* Drop any stale flags before reset so the card-detection latch is
119 * not interpreted as an event by the consumer. */
120 reg->SD_INFO1 = 0U;
121
122 /* HUM Ch 47.2.31 "SOFT_RST : Software Reset Register" p 3148 */
123 /* Mirror FSP r_sdhi_hw_cfg(): assert reset (SDRST=0), release
124 * reset (SDRST=1). This brings every status flag and bus-state
125 * machine to a known idle state. */
128
129 /* HUM Ch 47.2.18 "SD_CLK_CTRL : SD Clock Control Register" p 3138 */
130 /* Slowest CLKSEL (PCLKB/64) with CLKEN/CLKCTRLEN cleared; the
131 * card-stack consumer will retune for 25 MHz / 50 MHz once
132 * identification completes. */
134
135 /* HUM Ch 47.2.27 "SDIO_MODE : SDIO Mode Control Register" p 3144 */
136 /* HUM Ch 47.2.30 "SD_DMAEN : DMA Mode Enable Register" p 3147 */
137 /* HUM Ch 47.2.32 "SDIF_MODE : SD Interface Mode Setting" p 3148 */
138 /* HUM Ch 47.2.33 "EXT_SWAP : Swap Control Register" p 3149 */
139 /* Disable SDIO mode, DMA, MMC test-CRC mask, and endian-swap so
140 * the FIFO interface starts in the canonical big-endian-aware
141 * configuration. */
142 reg->SDIO_MODE = 0U;
143 reg->SD_DMAEN = 0U;
144 reg->SDIF_MODE = 0U;
145 reg->EXT_SWAP = 0U;
146
147 /* HUM Ch 47.2.16 "SD_OPTION : SD Card Access Control Option Register" p 3139-3140 */
148 /* 1-bit-wide bus (WIDTH=1, WIDTH8=0), default timeout counters. The
149 * consumer flips WIDTH/WIDTH8 via ::ra8_sdhi_set_bus_width_4bit once
150 * the card acknowledges ACMD6. */
151 reg->SD_OPTION = (uint32_t)k_ra8_sdhi_option_bus_1bit;
152
153 /* HUM Ch 47.2.17 "SD_INFO2_MASK : SD Card Interrupt Mask 2" p 3137 */
154 /* HUM Ch 47.2.16 "SD_INFO1_MASK : SD Card Interrupt Mask 1" p 3136 */
155 /* All interrupts masked off until ::ra8_sdhi_attach_handler installs
156 * a callback. */
157 reg->SD_INFO1_MASK = 0U;
158 reg->SD_INFO2_MASK = 0U;
159 reg->SD_INFO2 = 0U;
160
161 ra8_log_info_val(s_tag, "sdhi_init inst", (uint32_t)instance);
162 return k_ra8_ok;
163}
164
165ra8_err_t ra8_sdhi_deinit(uint8_t instance)
166{
167 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
168 RA8_CHECK_NULL_PTR(reg, s_tag, "instance out of range");
169
170 /* HUM Ch 47.2.31 "SOFT_RST : Software Reset Register" p 3148 */
171 /* Hold the IP in reset before clearing per-register state and
172 * gating the module clock. */
174
175 /* HUM Ch 47.2.15 "SD_INFO1 / SD_INFO2 / masks" p 3140 */
176 reg->SD_INFO1 = 0U;
177 reg->SD_INFO2 = 0U;
178 reg->SD_INFO1_MASK = 0U;
179 reg->SD_INFO2_MASK = 0U;
180 reg->SD_CLK_CTRL = 0U;
181 return ra8_mstp_disable(s_sdhi_mstp_table[instance]);
182}
183
184ra8_err_t ra8_sdhi_send_command(uint8_t instance, uint32_t cmd, uint32_t arg, uint32_t* out_rsp)
185{
186 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
187 RA8_CHECK_NULL_PTR(reg, s_tag, "instance out of range");
188
189 /* HUM Ch 47.2.2 "SD_ARG / SD_ARG1 : SD Command Argument" p 3128 */
190 /* HUM Ch 47.2.1 "SD_CMD : Command Type Register" p 3123 */
191 /* Load SD_ARG, then SD_CMD kicks the command out on the bus.
192 * FSP r_sdhi.c r_sdhi_command_send_no_wait() splits the argument
193 * into the legacy SD_ARG1 (upper 16 bits) plus SD_ARG (lower 16
194 * bits); on RA8D2 SD_ARG is a full 32-bit register so a single
195 * write is sufficient. */
196 reg->SD_ARG = arg;
197 reg->SD_CMD = cmd;
198
199 /* HUM Ch 47.2.15 "SD_INFO1 : SD Card Interrupt Flag Register 1" p 3129 */
200 /* Poll SD_INFO1.RSPEND (bit 0) with bounded spin budget. */
201 for (uint32_t i = 0U; i < k_ra8_sdhi_cmd_spin; ++i) {
202#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
203 if (ra8_fake_mmio_poll(&reg->SD_INFO1,
204 i,
205 (reg->SD_INFO1 & k_ra8_sdhi_info1_rspend_mask) != 0U)) {
206#else
207 if ((reg->SD_INFO1 & k_ra8_sdhi_info1_rspend_mask) != 0U) {
208#endif
209 if (out_rsp != nullptr) {
210 /* HUM Ch 47.2.5 "SD_RSP10..SD_RSP76 : Response Registers" p 3132 */
211 out_rsp[0] = reg->SD_RSP10;
212 out_rsp[1] = reg->SD_RSP32;
213 out_rsp[2] = reg->SD_RSP54;
214 out_rsp[3] = reg->SD_RSP76;
215 }
217 return k_ra8_ok;
218 }
219 }
221}
222
223ra8_err_t ra8_sdhi_set_clock(uint8_t instance, uint32_t divider)
224{
225 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
226 RA8_CHECK_NULL_PTR(reg, s_tag, "instance out of range");
227 /* HUM Ch 47.2.18 "SD_CLK_CTRL : SD Clock Control Register" p 3138 */
228 /* Preserve CLKEN (bit 8) and CLKCTRLEN (bit 9) -- caller controls
229 * only the CLKSEL[7:0] divider. FSP r_sdhi_set_clock() snapshots
230 * CLKCTRLEN, OR's CLKEN back in, and writes the merged value;
231 * mirror that semantics so a runtime divider change does not
232 * silently disable the SD bus clock. */
233 const uint32_t preserved =
235 reg->SD_CLK_CTRL = (divider & k_ra8_sdhi_clk_ctrl_setting_mask) | preserved;
236 return k_ra8_ok;
237}
238
240{
241 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
242 RA8_CHECK_NULL_PTR(reg, s_tag, "set_bus_width: instance out of range");
243
244 /* Reject anything that is not one of the three valid lane counts.
245 * This compound decision (3 conditions) is MC/DC-tested in
246 * test_ra8_sdhi_width.c. */
247 if ((width != k_ra8_sdhi_bus_width_1bit) && (width != k_ra8_sdhi_bus_width_4bit) &&
248 (width != k_ra8_sdhi_bus_width_8bit)) {
250 }
251
252 /* Map the lane count onto the SD_OPTION.WIDTH / WIDTH8 selector per
253 * the HUM Ch 47.2.16 truth table: 1-bit is WIDTH=1 (the initial
254 * value below), 4-bit is both bits clear, 8-bit is WIDTH8 only. */
255 uint32_t sel = (uint32_t)k_ra8_sdhi_option_width_bit;
256 if (width == k_ra8_sdhi_bus_width_4bit) {
257 sel = 0U;
258 } else if (width == k_ra8_sdhi_bus_width_8bit) {
259 sel = (uint32_t)k_ra8_sdhi_option_width8_bit;
260 }
261
262 /* HUM Ch 47.2.16 "SD_OPTION : SD Card Access Control Option Register" p 3139-3140 */
263 /* Read-modify-write: clear WIDTH+WIDTH8, OR in the new selector, and
264 * preserve TOP / CTOP / TOUTMASK / reserved bit 14. */
265 reg->SD_OPTION = (reg->SD_OPTION & ~(uint32_t)k_ra8_sdhi_option_width_mask) | sel;
266 return k_ra8_ok;
267}
268
269ra8_err_t ra8_sdhi_set_bus_width_4bit(uint8_t instance, uint16_t rca)
270{
271 volatile const r_sdhi_regs_t* reg = ra8_sdhi(instance);
272 RA8_CHECK_NULL_PTR(reg, s_tag, "set_bus_width_4bit: instance out of range");
273
274 uint32_t rsp[4] = {0U, 0U, 0U, 0U};
275 const uint32_t cmd55_arg = (uint32_t)rca << (uint32_t)k_ra8_sdhi_rca_arg_shift;
276
277 /* HUM Ch 47.2.1 "SD_CMD : Command Type Register" p 3123 */
278 /* CMD55 APP_CMD prefix (arg = RCA<<16) -- required before any ACMDxx. */
279 const ra8_err_t e55 =
280 ra8_sdhi_send_command(instance, (uint32_t)k_ra8_sdhi_cmd_app_cmd, cmd55_arg, rsp);
281 RA8_RETURN_ON_ERROR(e55, s_tag, "acmd6: CMD55 timeout");
282 const uint32_t cmd55_rsp = rsp[0];
283
284 /* HUM Ch 47.2.2 "SD_ARG : SD Command Argument" p 3124 */
285 /* ACMD6 SET_BUS_WIDTH -- arg bits[1:0] = 0b10 selects the 4-bit bus. */
286 const ra8_err_t e6 = ra8_sdhi_send_command(instance,
289 rsp);
290 RA8_RETURN_ON_ERROR(e6, s_tag, "acmd6: ACMD6 timeout");
291 const uint32_t acmd6_rsp = rsp[0];
292
293 /* Card acknowledges only when CMD55 echoed APP_CMD AND the ACMD6 R1
294 * response carries no error bits. This compound decision (2
295 * conditions) is MC/DC-tested in test_ra8_sdhi_width.c. On any
296 * rejection the host stays at the 1-bit default. */
297 const bool app_cmd_ready = (cmd55_rsp & (uint32_t)k_ra8_sdhi_r1_app_cmd_mask) != 0U;
298 const bool acmd6_clean = (acmd6_rsp & (uint32_t)k_ra8_sdhi_r1_error_mask) == 0U;
299 if ((!app_cmd_ready) || (!acmd6_clean)) {
301 }
302
303 /* Card switched to 4-bit -- widen the host side to match. */
305}
306
308{
309 volatile const r_sdhi_regs_t* reg = ra8_sdhi(instance);
310 RA8_CHECK_NULL_PTR(reg, s_tag, "set_bus_width_8bit: instance out of range");
311
312 uint32_t rsp[4] = {0U, 0U, 0U, 0U};
313
314 /* HUM Ch 47.2.1 "SD_CMD : Command Type Register" p 3123 */
315 /* HUM Ch 47.2.2 "SD_ARG : SD Command Argument" p 3124 */
316 /* eMMC CMD6 SWITCH -- write EXT_CSD[183] BUS_WIDTH = 2 (8-bit). This
317 * is a native command with no CMD55 app prefix (unlike SD ACMD6). */
318 const ra8_err_t e6 = ra8_sdhi_send_command(instance,
320 (uint32_t)k_ra8_sdhi_cmd6_arg_8bit,
321 rsp);
322 RA8_RETURN_ON_ERROR(e6, s_tag, "switch8: CMD6 timeout");
323
324 /* The device accepts only when the R1b response carries no error /
325 * status-violation bits; otherwise the host stays at its current
326 * width. An SD card, which cannot do 8-bit, is rejected here. */
327 if ((rsp[0] & (uint32_t)k_ra8_sdhi_r1_error_mask) != 0U) {
329 }
330
331 /* Device switched to 8-bit -- widen the host side to match. */
333}
334
335ra8_err_t ra8_sdhi_get_status(uint8_t instance, uint32_t* out_mask)
336{
337 RA8_CHECK_NULL_PTR(out_mask, s_tag, "out_mask must not be nullptr");
338 volatile const r_sdhi_regs_t* reg = ra8_sdhi(instance);
339 RA8_CHECK_NULL_PTR(reg, s_tag, "instance out of range");
340 /* HUM Ch 47.2.15 "SD_INFO1 : SD Card Interrupt Flag Register 1" p 3129 */
341 *out_mask = reg->SD_INFO1;
342 return k_ra8_ok;
343}
344
345ra8_err_t ra8_sdhi_clear_status(uint8_t instance, uint32_t mask)
346{
347 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
348 RA8_CHECK_NULL_PTR(reg, s_tag, "instance out of range");
349 /* HUM Ch 47.2.15 "SD_INFO1 : SD Card Interrupt Flag Register 1" p 3129 */
350 /* SD_INFO1 bits are write-0-to-clear. Read-modify-write so unset
351 * bits in `mask` continue to read 1 (canonical pattern from FSP
352 * r_sdhi_access_irq_process()). */
353 reg->SD_INFO1 = reg->SD_INFO1 & ~mask;
354 return k_ra8_ok;
355}
356
358{
359 s_sdhi_fn = fn;
360 s_sdhi_ctx = ctx;
361 return k_ra8_ok;
362}
363
365void ra8_sdhi_dispatch(uint8_t instance)
366{
367 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
368 if (reg == nullptr) {
369 return;
370 }
371 /* HUM Ch 47.2.15 "SD_INFO1 : SD Card Interrupt Flag Register 1" p 3129 */
372 const uint32_t mask = reg->SD_INFO1;
374 void* const ctx = s_sdhi_ctx;
375 reg->SD_INFO1 = 0U;
376 if (fn != nullptr) {
377 fn(ctx, instance, mask);
378 }
379}
380
382{
383 if (instance >= k_ra8_sdhi_instance_count) {
385 }
386 return ra8_mstp_disable(s_sdhi_mstp_table[instance]);
387}
388
390{
391 if (instance >= k_ra8_sdhi_instance_count) {
393 }
394 return ra8_mstp_enable(s_sdhi_mstp_table[instance]);
395}
396
407typedef enum : uint32_t {
410
426
460static ra8_err_t internal_sdhi_send(volatile r_sdhi_regs_t* reg, uint32_t cmd, uint32_t arg)
461{
462 /* HUM Ch 47.2.2 "SD_ARG : SD Command Argument" p 3124 */
463 /* HUM Ch 47.2.1 "SD_CMD : Command Type Register" p 3123 */
464 reg->SD_ARG = arg;
465 reg->SD_CMD = cmd;
466
467 /* HUM Ch 47.2.15 "SD_INFO1 : SD Card Interrupt Flag Register 1" p 3129 */
468 for (uint32_t i = 0U; i < k_ra8_sdhi_cmd_spin; ++i) {
469#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
470 if (ra8_fake_mmio_poll(&reg->SD_INFO1,
471 i,
472 (reg->SD_INFO1 & k_ra8_sdhi_info1_rspend_mask) != 0U)) {
473#else
474 if ((reg->SD_INFO1 & k_ra8_sdhi_info1_rspend_mask) != 0U) {
475#endif
477 return k_ra8_ok;
478 }
479 }
481}
482
507static void internal_sdhi_setup_xfer(volatile r_sdhi_regs_t* reg, uint32_t block_count)
508{
509 /* HUM Ch 47.2.4 "SD_STOP : Data Stop Register" p 3125 */
510 /* HUM Ch 47.2.6 "SD_SECCNT : Block Count Register" p 3126 */
511 if (block_count > 1U) {
513 reg->SD_SECCNT = block_count;
514 } else {
515 reg->SD_STOP = 0U;
516 }
517
518 /* HUM Ch 47.2.19 "SD_SIZE : Transfer Data Length Register" p 3139 */
520}
521
551static ra8_err_t internal_sdhi_drain(volatile r_sdhi_regs_t* reg, uint8_t* buf, uint32_t words)
552{
553 uint8_t* cursor = buf;
554 for (uint32_t w = 0U; w < words; ++w) {
555 uint32_t spin = 0U;
556 for (; spin < k_ra8_sdhi_fifo_spin; ++spin) {
557#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
558 if (ra8_fake_mmio_poll(&reg->SD_INFO2,
559 spin,
560 (reg->SD_INFO2 & k_ra8_sdhi_info2_bre_mask) != 0U)) {
561#else
562 if ((reg->SD_INFO2 & k_ra8_sdhi_info2_bre_mask) != 0U) {
563#endif
564 break;
565 }
566 }
567 if (spin >= k_ra8_sdhi_fifo_spin) {
569 }
570 const uint32_t word = reg->SD_BUF0;
571 cursor[0] = (uint8_t)(word & k_ra8_sdhi_byte_mask);
572 cursor[1] = (uint8_t)((word >> k_ra8_sdhi_shift_b1) & k_ra8_sdhi_byte_mask);
573 cursor[2] = (uint8_t)((word >> k_ra8_sdhi_shift_b2) & k_ra8_sdhi_byte_mask);
574 cursor[3] = (uint8_t)((word >> k_ra8_sdhi_shift_b3) & k_ra8_sdhi_byte_mask);
576 }
577 return k_ra8_ok;
578}
579
609static ra8_err_t internal_sdhi_fill(volatile r_sdhi_regs_t* reg, const uint8_t* buf, uint32_t words)
610{
611 const uint8_t* cursor = buf;
612 for (uint32_t w = 0U; w < words; ++w) {
613 uint32_t spin = 0U;
614 for (; spin < k_ra8_sdhi_fifo_spin; ++spin) {
615#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
616 if (ra8_fake_mmio_poll(&reg->SD_INFO2,
617 spin,
618 (reg->SD_INFO2 & k_ra8_sdhi_info2_bwe_mask) != 0U)) {
619#else
620 if ((reg->SD_INFO2 & k_ra8_sdhi_info2_bwe_mask) != 0U) {
621#endif
622 break;
623 }
624 }
625 if (spin >= k_ra8_sdhi_fifo_spin) {
627 }
628 const uint32_t word = (uint32_t)cursor[0] | ((uint32_t)cursor[1] << k_ra8_sdhi_shift_b1) |
629 ((uint32_t)cursor[2] << k_ra8_sdhi_shift_b2) |
630 ((uint32_t)cursor[3] << k_ra8_sdhi_shift_b3);
631 reg->SD_BUF0 = word;
633 }
634 return k_ra8_ok;
635}
636
664static ra8_err_t internal_sdhi_finish_xfer(volatile r_sdhi_regs_t* reg, uint32_t block_count)
665{
666 if (block_count > 1U) {
667 /* HUM Ch 47.2.1 "SD_CMD : Command Type Register" p 3123 */
668 const ra8_err_t stop_err =
670 RA8_RETURN_ON_ERROR(stop_err, s_tag, "block_xfer: CMD12 timeout");
671 }
672 reg->SD_INFO1 = 0U;
673 reg->SD_INFO2 = 0U;
674 return k_ra8_ok;
675}
676
677ra8_err_t ra8_sdhi_read_block(uint8_t instance, uint32_t lba, uint8_t* buf, uint32_t block_count)
678{
679 RA8_CHECK_NULL_PTR(buf, s_tag, "read_block: buf must not be nullptr");
680 if (block_count == 0U) {
682 }
683 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
684 RA8_CHECK_NULL_PTR(reg, s_tag, "read_block: instance out of range");
685
686 internal_sdhi_setup_xfer(reg, block_count);
687
688 const uint32_t cmd = (block_count > 1U) ? (uint32_t)k_ra8_sdhi_cmd_read_multi_block
690 const ra8_err_t cmd_err = internal_sdhi_send(reg, cmd, lba);
691 RA8_RETURN_ON_ERROR(cmd_err, s_tag, "read_block: RSPEND timeout");
692
693 /* HUM Ch 47.2.21 "SD_BUF0 : SD Buffer Register" p 3143 */
694 const uint32_t total_words = block_count * k_ra8_sdhi_words_per_block;
695 const ra8_err_t drain_err = internal_sdhi_drain(reg, buf, total_words);
696 RA8_RETURN_ON_ERROR(drain_err, s_tag, "read_block: BRE timeout");
697
698 return internal_sdhi_finish_xfer(reg, block_count);
699}
700
702ra8_sdhi_write_block(uint8_t instance, uint32_t lba, const uint8_t* buf, uint32_t block_count)
703{
704 RA8_CHECK_NULL_PTR(buf, s_tag, "write_block: buf must not be nullptr");
705 if (block_count == 0U) {
707 }
708 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
709 RA8_CHECK_NULL_PTR(reg, s_tag, "write_block: instance out of range");
710
711 internal_sdhi_setup_xfer(reg, block_count);
712
713 const uint32_t cmd = (block_count > 1U) ? (uint32_t)k_ra8_sdhi_cmd_write_multi_block
715 const ra8_err_t cmd_err = internal_sdhi_send(reg, cmd, lba);
716 RA8_RETURN_ON_ERROR(cmd_err, s_tag, "write_block: RSPEND timeout");
717
718 /* HUM Ch 47.2.21 "SD_BUF0 : SD Buffer Register" p 3143 */
719 const uint32_t total_words = block_count * k_ra8_sdhi_words_per_block;
720 const ra8_err_t fill_err = internal_sdhi_fill(reg, buf, total_words);
721 RA8_RETURN_ON_ERROR(fill_err, s_tag, "write_block: BWE timeout");
722
723 return internal_sdhi_finish_xfer(reg, block_count);
724}
725
726ra8_err_t ra8_sdhi_attach_dma(uint8_t instance, uint8_t enable)
727{
728 volatile r_sdhi_regs_t* reg = ra8_sdhi(instance);
729 RA8_CHECK_NULL_PTR(reg, s_tag, "attach_dma: instance out of range");
730
731 /* HUM Ch 47.2.30 "SD_DMAEN : DMA Mode Enable Register" p 3147 */
732 /* HUM Ch 47.2.17 "SD_INFO2_MASK : SD Card Interrupt Mask 2" p 3137 */
733 /* FSP r_sdhi_transfer_read / r_sdhi_transfer_write set the BREM
734 * and BWEM mask bits whenever DMAEN is asserted, so that the
735 * DMA-driven path does not race with the polled BRE / BWE wait
736 * the PIO path uses. Mirror that pairing here. */
737 if (enable != 0U) {
740 } else {
741 reg->SD_DMAEN = 0U;
743 }
744 return k_ra8_ok;
745}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_ISR_SAFE
The function is callable from interrupt context.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Bounded wait-flag primitives for RA8D2 HAL drivers.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info_val(tag, message, value)
RA8 log info val.
Definition ra8_log.h:366
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_enable(ra8_mstp_t id)
Reference-counted "ungate this peripheral" request.
Definition ra8_mstp.c:343
ra8_err_t ra8_mstp_disable(ra8_mstp_t id)
Reference-counted "gate this peripheral" request.
Definition ra8_mstp.c:382
Module Stop Control (MSTP) register layout for the Renesas RA8D2.
ra8_mstp_t
Packed (reg << 8) | bit module-stop identifier.
@ k_ra8_mstp_sdhi1
MSTPC11 SDHI1.
@ k_ra8_mstp_sdhi0
MSTPC12 SDHI0.
static ra8_err_t internal_sdhi_send(volatile r_sdhi_regs_t *reg, uint32_t cmd, uint32_t arg)
Issue a data-transfer command and wait for RSPEND.
Definition ra8_sdhi.c:460
ra8_err_t ra8_sdhi_read_block(uint8_t instance, uint32_t lba, uint8_t *buf, uint32_t block_count)
Read one or more 512-byte SD blocks via the SD_BUF0 FIFO.
Definition ra8_sdhi.c:677
ra8_err_t ra8_sdhi_get_status(uint8_t instance, uint32_t *out_mask)
Read the SD_INFO1 status register.
Definition ra8_sdhi.c:335
static ra8_err_t internal_sdhi_drain(volatile r_sdhi_regs_t *reg, uint8_t *buf, uint32_t words)
Drain words 32-bit FIFO words from SD_BUF0 into buf.
Definition ra8_sdhi.c:551
ra8_sdhi_byte_split_t
Byte / shift constants for the 32-bit FIFO word splitter.
Definition ra8_sdhi.c:420
@ k_ra8_sdhi_shift_b1
bits 15..8 -> byte 1
Definition ra8_sdhi.c:422
@ k_ra8_sdhi_shift_b2
bits 23..16 -> byte 2
Definition ra8_sdhi.c:423
@ k_ra8_sdhi_byte_mask
low-byte select mask
Definition ra8_sdhi.c:421
@ k_ra8_sdhi_shift_b3
bits 31..24 -> byte 3
Definition ra8_sdhi.c:424
static void internal_sdhi_setup_xfer(volatile r_sdhi_regs_t *reg, uint32_t block_count)
Common data-phase setup shared by read_block / write_block.
Definition ra8_sdhi.c:507
ra8_err_t ra8_sdhi_write_block(uint8_t instance, uint32_t lba, const uint8_t *buf, uint32_t block_count)
Write one or more 512-byte SD blocks via the SD_BUF0 FIFO.
Definition ra8_sdhi.c:702
static void * s_sdhi_ctx
Definition ra8_sdhi.c:68
ra8_err_t ra8_sdhi_exit_stop(uint8_t instance)
Exit MSTP-gated stop.
Definition ra8_sdhi.c:389
static ra8_err_t internal_sdhi_fill(volatile r_sdhi_regs_t *reg, const uint8_t *buf, uint32_t words)
Push words 32-bit FIFO words from buf into SD_BUF0.
Definition ra8_sdhi.c:609
ra8_err_t ra8_sdhi_set_clock(uint8_t instance, uint32_t divider)
Set the SD bus clock divider (SD_CLK_CTRL).
Definition ra8_sdhi.c:223
ra8_err_t ra8_sdhi_send_command(uint8_t instance, uint32_t cmd, uint32_t arg, uint32_t *out_rsp)
Issue a single SD command and read the 4-word response.
Definition ra8_sdhi.c:184
ra8_sdhi_init_const_t
SDHI register-bring-up constants mirrored from FSP r_sdhi.c.
Definition ra8_sdhi.c:82
@ k_ra8_sdhi_soft_rst_release
release RST
Definition ra8_sdhi.c:84
@ k_ra8_sdhi_clk_ctrl_setting_mask
CLKSEL[7:0].
Definition ra8_sdhi.c:88
@ k_ra8_sdhi_clk_ctrl_clkctrlen_mask
SD_CLK_CTRL.CLKCTRLEN bit-9.
Definition ra8_sdhi.c:87
@ k_ra8_sdhi_clk_ctrl_clken_mask
SD_CLK_CTRL.CLKEN bit-8.
Definition ra8_sdhi.c:86
@ k_ra8_sdhi_clk_ctrl_default
CLKSEL=64, CLKEN/CLKCTRLEN=0.
Definition ra8_sdhi.c:85
@ k_ra8_sdhi_info1_rspend_mask
SD_INFO1.RSPEND bit-0.
Definition ra8_sdhi.c:89
@ k_ra8_sdhi_soft_rst_assert
drive RST low
Definition ra8_sdhi.c:83
void ra8_sdhi_dispatch(uint8_t instance)
Dispatch an SDHI event – snapshot status + fire callback.
Definition ra8_sdhi.c:365
static const ra8_mstp_t s_sdhi_mstp_table[k_ra8_sdhi_instance_count]
Per-instance MSTP id lookup.
Definition ra8_sdhi.c:62
static ra8_err_t internal_sdhi_finish_xfer(volatile r_sdhi_regs_t *reg, uint32_t block_count)
Tear down the data phase: optional CMD12 + flag cleanup.
Definition ra8_sdhi.c:664
static ra8_sdhi_event_fn_t s_sdhi_fn
Definition ra8_sdhi.c:67
ra8_sdhi_timing_t
Bounded spin budget for ra8_sdhi_send_command response wait.
Definition ra8_sdhi.c:102
@ k_ra8_sdhi_cmd_spin
RA8 SDHI cmd spin.
Definition ra8_sdhi.c:103
ra8_err_t ra8_sdhi_clear_status(uint8_t instance, uint32_t mask)
Clear SD_INFO1 status bits via write-0-to-clear.
Definition ra8_sdhi.c:345
ra8_err_t ra8_sdhi_attach_dma(uint8_t instance, uint8_t enable)
Enable or disable DMAC-driven SDHI transfers.
Definition ra8_sdhi.c:726
ra8_err_t ra8_sdhi_init(uint8_t instance)
Initialise an SDHI instance.
Definition ra8_sdhi.c:106
ra8_err_t ra8_sdhi_attach_handler(ra8_sdhi_event_fn_t fn, void *ctx)
Attach an SDHI event callback (shared across instances).
Definition ra8_sdhi.c:357
ra8_err_t ra8_sdhi_deinit(uint8_t instance)
Tear down an SDHI instance.
Definition ra8_sdhi.c:165
ra8_err_t ra8_sdhi_enter_stop(uint8_t instance)
Put an SDHI instance into MSTP-gated stop.
Definition ra8_sdhi.c:381
ra8_err_t ra8_sdhi_set_bus_width(uint8_t instance, ra8_sdhi_bus_width_t width)
Program the host-side SD data-bus width (SD_OPTION.WIDTH / WIDTH8).
Definition ra8_sdhi.c:239
ra8_sdhi_fifo_timing_t
Bounded spin budget for the per-word BRE / BWE poll.
Definition ra8_sdhi.c:407
@ k_ra8_sdhi_fifo_spin
RA8 SDHI FIFO spin.
Definition ra8_sdhi.c:408
ra8_err_t ra8_sdhi_set_bus_width_4bit(uint8_t instance, uint16_t rca)
Negotiate a 4-bit data bus with the card via CMD55 + ACMD6.
Definition ra8_sdhi.c:269
ra8_err_t ra8_sdhi_set_bus_width_8bit(uint8_t instance)
Negotiate an 8-bit data bus with an eMMC device via CMD6 SWITCH.
Definition ra8_sdhi.c:307
SD/MMC Host Interface (SDHI) driver scaffold.
void(* ra8_sdhi_event_fn_t)(void *ctx, uint8_t instance, uint32_t status_mask)
SDHI event callback.
Definition ra8_sdhi.h:48
ra8_sdhi_bus_width_t
SD data-bus width accepted by ra8_sdhi_set_bus_width.
Definition ra8_sdhi.h:66
@ k_ra8_sdhi_bus_width_1bit
Single data lane (power-on safe default).
Definition ra8_sdhi.h:68
@ k_ra8_sdhi_bus_width_4bit
Four data lanes (SD default-speed wide).
Definition ra8_sdhi.h:69
@ k_ra8_sdhi_bus_width_8bit
Eight data lanes (eMMC only).
Definition ra8_sdhi.h:70
SDHI (SD/MMC host interface) register layout for the Renesas RA8D2.
@ k_ra8_sdhi_rca_arg_shift
RCA occupies SD_ARG[31:16].
@ k_ra8_sdhi_option_bus_1bit
1-bit safe default: WIDTH=1, WIDTH8=0 (0xC0E0).
@ k_ra8_sdhi_option_width_bit
WIDTH (bit 15): 1 -> narrow bus.
@ k_ra8_sdhi_option_width8_bit
WIDTH8 (bit 13): 1 -> 8-bit.
@ k_ra8_sdhi_option_width_mask
Combined WIDTH+WIDTH8 clear mask for read-modify-write.
@ k_ra8_sdhi_block_bytes
SD block size in bytes.
@ k_ra8_sdhi_words_per_block
512 / 4 = 128 word fills per block
@ k_ra8_sdhi_fifo_word_bytes
SD_BUF0 FIFO word width.
@ k_ra8_sdhi_r1_app_cmd_mask
R1 bit 5 APP_CMD acknowledged.
@ k_ra8_sdhi_r1_error_mask
R1 error/violation bit-mask.
@ k_ra8_sdhi_acmd6_arg_4bit
ACMD6 arg: 4-bit data bus.
static volatile r_sdhi_regs_t * ra8_sdhi(uint8_t instance)
Get pointer to SDHI instance N (0 or 1).
@ k_ra8_sdhi_cmd6_arg_8bit
Whole CMD6 SWITCH argument: BUS_WIDTH <- 8-bit (0x03B70200).
@ k_ra8_sdhi_instance_count
RA8 SDHI instance count.
@ k_ra8_sdhi_info2_bre_mask
SD_INFO2.BRE bit 8.
@ k_ra8_sdhi_info2_bwe_mask
SD_INFO2.BWE bit 9.
@ k_ra8_sdhi_stop_seccnt_en
SD_STOP.SEC bit 8.
@ k_ra8_sdhi_info2_brem_bwem
SD_INFO2_MASK.
@ k_ra8_sdhi_dmaen_set
SD_DMAEN.DMAEN bit 1.
@ k_ra8_sdhi_cmd_emmc_switch
CMD6 SWITCH (eMMC EXT_CSD).
@ k_ra8_sdhi_cmd_write_multi_block
CMD25 WRITE_MULTIPLE_BLOCK.
@ k_ra8_sdhi_cmd_stop_transmission
CMD12 STOP_TRANSMISSION.
@ k_ra8_sdhi_cmd_read_multi_block
CMD18 READ_MULTIPLE_BLOCK.
@ k_ra8_sdhi_cmd_app_cmd
CMD55 APP_CMD prefix.
@ k_ra8_sdhi_cmd_write_single_block
CMD24 WRITE_SINGLE_BLOCK.
@ k_ra8_sdhi_cmd_set_bus_width
ACMD6 SET_BUS_WIDTH (SD).
@ k_ra8_sdhi_cmd_read_single_block
CMD17 READ_SINGLE_BLOCK.
SDHI register window.
volatile uint32_t SD_SECCNT
+0x14 Block Count.
volatile uint32_t SD_ARG
+0x08 Argument (32-bit).
volatile uint32_t SD_INFO1_MASK
+0x40 Interrupt Mask 1.
volatile uint32_t SOFT_RST
+0x1C0 Software Reset.
volatile uint32_t SD_INFO2_MASK
+0x44 Interrupt Mask 2.
volatile uint32_t SD_CMD
+0x00 Command Type Register.
volatile uint32_t SD_INFO1
+0x38 Interrupt Flag 1.
volatile uint32_t SD_RSP32
+0x20 Response 32.
volatile uint32_t SD_STOP
+0x10 Stop.
volatile uint32_t SD_OPTION
+0x50 Access Control Option.
volatile uint32_t SD_INFO2
+0x3C Interrupt Flag 2.
volatile uint32_t SDIF_MODE
+0x1CC SD Interface Mode.
volatile uint32_t SD_SIZE
+0x4C Transfer Data Length.
volatile uint32_t SD_DMAEN
+0x1B0 DMA Mode Enable.
volatile uint32_t SD_BUF0
+0x60 Buffer Register.
volatile uint32_t SDIO_MODE
+0x68 SDIO Mode Control.
volatile uint32_t EXT_SWAP
+0x1E0 Endian Swap Control.
volatile uint32_t SD_RSP10
+0x18 Response 10.
volatile uint32_t SD_RSP54
+0x28 Response 54.
volatile uint32_t SD_RSP76
+0x30 Response 76.
volatile uint32_t SD_CLK_CTRL
+0x48 Clock Control.