7#include "porting_assistant.h"
13#define MORSE_REG_ADDRESS_BASE 0x10000
14#define MORSE_REG_ADDRESS_WINDOW_0 MORSE_REG_ADDRESS_BASE
15#define MORSE_REG_ADDRESS_WINDOW_1 (MORSE_REG_ADDRESS_BASE + 1)
16#define MORSE_REG_ADDRESS_CONFIG (MORSE_REG_ADDRESS_BASE + 2)
18#define MORSE_CONFIG_ACCESS_1BYTE 0
19#define MORSE_CONFIG_ACCESS_2BYTE 1
20#define MORSE_CONFIG_ACCESS_4BYTE 2
23#define PACK_LE16(dst16_data, src8_array) \
25 dst16_data = *src8_array; \
26 dst16_data |= ((uint16_t)*(src8_array+1) << 8); \
30#define PACK_BE16(dst16_data, src8_array) \
32 dst16_data = *(src8_array+1); \
33 dst16_data |= ((uint16_t)*(src8_array) << 8); \
37#define UNPACK_LE16(dst8_array, src16_data) \
39 *dst8_array = (uint8_t)(src16_data); \
40 *(dst8_array+1) = (uint8_t)(src16_data >> 8); \
44#define UNPACK_BE16(dst8_array, src16_data) \
46 *(dst8_array+1) = (uint8_t)(src16_data); \
47 *(dst8_array) = (uint8_t)(src16_data >> 8); \
51#define PACK_LE32(dst32_data, src8_array) \
53 dst32_data = *src8_array; \
54 dst32_data |= ((uint32_t)*(src8_array+1) << 8); \
55 dst32_data |= ((uint32_t)*(src8_array+2) << 16); \
56 dst32_data |= ((uint32_t)*(src8_array+3) << 24); \
60#define PACK_BE32(dst32_data, src8_array) \
62 dst32_data = *(src8_array+3); \
63 dst32_data |= ((uint32_t)*(src8_array+2) << 8); \
64 dst32_data |= ((uint32_t)*(src8_array+1) << 16); \
65 dst32_data |= ((uint32_t)*(src8_array) << 24); \
69#define UNPACK_LE32(dst8_array, src32_data) \
71 *dst8_array = (uint8_t)(src32_data); \
72 *(dst8_array+1) = (uint8_t)(src32_data >> 8); \
73 *(dst8_array+2) = (uint8_t)(src32_data >> 16); \
74 *(dst8_array+3) = (uint8_t)(src32_data >> 24); \
78#define UNPACK_BE32(dst8_array, src32_data) \
80 *(dst8_array+3) = (uint8_t)(src32_data); \
81 *(dst8_array+2) = (uint8_t)(src32_data >> 8); \
82 *(dst8_array+1) = (uint8_t)(src32_data >> 16); \
83 *(dst8_array) = (uint8_t)(src32_data >> 24); \
87#define PACK_LE64(dst64_data, src8_array) \
89 dst64_data = ((uint64_t)*(src8_array+0) << 0); \
90 dst64_data |= ((uint64_t)*(src8_array+1) << 8); \
91 dst64_data |= ((uint64_t)*(src8_array+2) << 16); \
92 dst64_data |= ((uint64_t)*(src8_array+3) << 24); \
93 dst64_data |= ((uint64_t)*(src8_array+4) << 32); \
94 dst64_data |= ((uint64_t)*(src8_array+5) << 40); \
95 dst64_data |= ((uint64_t)*(src8_array+6) << 48); \
96 dst64_data |= ((uint64_t)*(src8_array+7) << 56); \
100#define PACK_BE64(dst64_data, src8_array) \
102 dst64_data = ((uint64_t)*(src8_array+7) << 0); \
103 dst64_data |= ((uint64_t)*(src8_array+6) << 8); \
104 dst64_data |= ((uint64_t)*(src8_array+5) << 16); \
105 dst64_data |= ((uint64_t)*(src8_array+4) << 24); \
106 dst64_data |= ((uint64_t)*(src8_array+3) << 32); \
107 dst64_data |= ((uint64_t)*(src8_array+2) << 40); \
108 dst64_data |= ((uint64_t)*(src8_array+1) << 48); \
109 dst64_data |= ((uint64_t)*(src8_array+0) << 56); \
113#define UNPACK_LE64(dst8_array, src64_data) \
115 *(dst8_array+0) = (uint8_t)(src64_data >> 0); \
116 *(dst8_array+1) = (uint8_t)(src64_data >> 8); \
117 *(dst8_array+2) = (uint8_t)(src64_data >> 16); \
118 *(dst8_array+3) = (uint8_t)(src64_data >> 24); \
119 *(dst8_array+4) = (uint8_t)(src64_data >> 32); \
120 *(dst8_array+5) = (uint8_t)(src64_data >> 40); \
121 *(dst8_array+6) = (uint8_t)(src64_data >> 48); \
122 *(dst8_array+7) = (uint8_t)(src64_data >> 56); \
126#define UNPACK_BE64(dst8_array, src64_data) \
128 *(dst8_array+7) = (uint8_t)(src64_data >> 0); \
129 *(dst8_array+6) = (uint8_t)(src64_data >> 8); \
130 *(dst8_array+5) = (uint8_t)(src64_data >> 16); \
131 *(dst8_array+4) = (uint8_t)(src64_data >> 24); \
132 *(dst8_array+3) = (uint8_t)(src64_data >> 32); \
133 *(dst8_array+2) = (uint8_t)(src64_data >> 40); \
134 *(dst8_array+1) = (uint8_t)(src64_data >> 48); \
135 *(dst8_array+0) = (uint8_t)(src64_data >> 56); \
140#define CMD53_MAX_BLOCKS 128
145 BLOCK_SIZE_FN1_LOG2 = 3,
146 BLOCK_SIZE_FN2 = 512,
147 BLOCK_SIZE_FN2_LOG2 = 9,
150enum max_block_transfer_size
152 MAX_BLOCK_TRANSFER_SIZE_FN1 = BLOCK_SIZE_FN1 * CMD53_MAX_BLOCKS,
153 MAX_BLOCK_TRANSFER_SIZE_FN2 = BLOCK_SIZE_FN2 * CMD53_MAX_BLOCKS,
158#define CHIP_ACTIVE_SEQ (0x00000000)
164 SDIO_DIR_CARD_TO_HOST = 0,
165 SDIO_DIR_HOST_TO_CARD = 1 << 6,
189#define SDIO_CCCR_IEN_ADDR 0x04u
190#define SDIO_CCCR_IEN_IENM (1u)
191#define SDIO_CCCR_IEN_IEN1 (1u << 1)
193#define SDIO_CCCR_BIC_ADDR 0x07u
194#define SDIO_CCCR_BIC_ECSI (1u << 5)
197static inline uint32_t min_u32(uint32_t a, uint32_t b)
220static int morse_cmd52_write(uint32_t address, uint8_t data,
enum mmhal_sdio_function function)
226 return sdio_spi_send_cmd(SDIO_CMD52, arg, NULL);
244 uint8_t *data, uint32_t len)
248 enum block_size block_size = BLOCK_SIZE_FN2;
249 enum block_size block_size_log2 = BLOCK_SIZE_FN2_LOG2;
253 block_size = BLOCK_SIZE_FN1;
254 block_size_log2 = BLOCK_SIZE_FN1_LOG2;
258 uint16_t num_blocks = len >> block_size_log2;
263 address & 0x0000ffff, num_blocks),
265 .transfer_length = num_blocks,
266 .block_size = BLOCK_SIZE_FN2,
275 uint32_t transfer_size = num_blocks *
block_size;
276 address += transfer_size;
277 data += transfer_size;
278 len -= transfer_size;
286 address & 0x0000ffff, len),
288 .transfer_length = len,
314 const uint8_t *
data, uint32_t len)
318 enum block_size block_size = BLOCK_SIZE_FN2;
319 enum block_size block_size_log2 = BLOCK_SIZE_FN2_LOG2;
323 block_size = BLOCK_SIZE_FN1;
324 block_size_log2 = BLOCK_SIZE_FN1_LOG2;
328 uint16_t num_blocks = len >> block_size_log2;
333 address & 0x0000ffff, num_blocks),
334 .data = (uint8_t *)
data,
336 .block_size = BLOCK_SIZE_FN2,
345 uint32_t transfer_size = num_blocks *
block_size;
346 address += transfer_size;
347 data += transfer_size;
348 len -= transfer_size;
356 address & 0x0000ffff, len),
357 .data = (uint8_t *)
data,
379static int morse_address_base_set(uint32_t address, uint8_t access,
384 address &= 0xFFFF0000;
388 result = morse_cmd52_write(MORSE_REG_ADDRESS_WINDOW_0, (uint8_t)(address >> 16),
395 result = morse_cmd52_write(MORSE_REG_ADDRESS_WINDOW_1, (uint8_t)(address >> 24),
402 result = morse_cmd52_write(MORSE_REG_ADDRESS_CONFIG, access, function);
412int sdio_spi_read_le32(uint32_t address, uint32_t *
data)
415 uint8_t receive_data[4];
424 result = morse_address_base_set(address, MORSE_CONFIG_ACCESS_4BYTE, function);
430 result = morse_cmd53_read(function, address, receive_data,
sizeof(receive_data));
436 PACK_LE32(*
data, receive_data);
442int sdio_spi_read_multi_byte(uint32_t address, uint8_t *
data, uint32_t len)
446 enum max_block_transfer_size max_transfer_size = MAX_BLOCK_TRANSFER_SIZE_FN2;
449 if (len == 0 || (len & 0x03) != 0)
451 printf(
"Invalid length %lu\n", len);
460 result = morse_address_base_set(address, MORSE_CONFIG_ACCESS_4BYTE, function);
467 uint32_t size = min_u32(len, max_transfer_size);
471 uint32_t next_boundary = (address & 0xFFFF0000) + 0x10000;
472 if ((address + size) > next_boundary)
474 size = next_boundary - address;
477 morse_cmd53_read(function, address,
data, size);
485 if ((size >= 8) && !memcmp(
data,
data+4, 4)) {
487 printf(
"Corrupt Payload. Re-Read first 8 bytes\n");
488 morse_cmd53_read(function, address,
data, 8);
500int sdio_spi_write_multi_byte(uint32_t address,
const uint8_t *
data, uint32_t len)
504 enum max_block_transfer_size max_transfer_size = MAX_BLOCK_TRANSFER_SIZE_FN2;
507 if (len == 0 || (len & 0x03) != 0)
509 printf(
"Invalid length %lu\n", len);
518 result = morse_address_base_set(address, MORSE_CONFIG_ACCESS_4BYTE, function);
525 uint32_t size = min_u32(len, max_transfer_size);
529 uint32_t next_boundary = (address & 0xFFFF0000) + 0x10000;
530 if ((address + size) > next_boundary)
532 size = next_boundary - address;
535 result = morse_cmd53_write(function, address,
data, size);
550int sdio_spi_write_le32(uint32_t address, uint32_t
data)
555 result = morse_address_base_set(address, MORSE_CONFIG_ACCESS_4BYTE, function);
561 result = morse_cmd53_write(function, address, (uint8_t*)&
data,
sizeof(
data));
567int sdio_spi_send_cmd(uint8_t cmd_idx, uint32_t arg, uint32_t *rsp)
572int sdio_spi_update_le32(uint32_t address, uint32_t mask, uint32_t value)
576 result = sdio_spi_read_le32(address, ®_value);
581 reg_value |= (value & mask);
582 reg_value &= (value | ~mask);
583 result = sdio_spi_write_le32(address, reg_value);
static uint32_t mmhal_make_cmd53_arg(enum mmhal_sdio_rw rw, enum mmhal_sdio_function fn, enum mmhal_sdio_mode mode, uint32_t address, uint16_t count)
Construct an SDIO CMD53 argument based on the given arguments.
static uint32_t mmhal_make_cmd52_arg(enum mmhal_sdio_rw rw, enum mmhal_sdio_function fn, uint32_t address, uint8_t write_data)
Construct an SDIO CMD52 argument based on the given arguments.
mmhal_sdio_function
SDIO CMD52/CMD53 function number.
#define MMHAL_SDIO_ADDRESS_MAX
CMD52/53 Register Address maximum value.
@ MMHAL_SDIO_MODE_BLOCK
Byte mode.
@ MMHAL_SDIO_READ
Read operation.
@ MMHAL_SDIO_WRITE
Write operation.
@ MMHAL_SDIO_FUNCTION_1
Function 0.
@ MMHAL_SDIO_FUNCTION_2
Function 1.
int mmhal_wlan_sdio_cmd53_read(const struct mmhal_wlan_sdio_cmd53_read_args *args)
Execute an SDIO CMD53 read.
int mmhal_wlan_sdio_cmd53_write(const struct mmhal_wlan_sdio_cmd53_write_args *args)
Execute an SDIO CMD53 write.
int mmhal_wlan_sdio_cmd(uint8_t cmd_idx, uint32_t arg, uint32_t *rsp)
Execute an SDIO command without data.
@ MMHAL_SDIO_INVALID_ARGUMENT
Invalid argument given (e.g., incorrect buffer alignment).
@ MMHAL_SDIO_OTHER_ERROR
Another error not covered by the above error codes.
#define MMOSAL_ASSERT(expr)
Assert that the given expression evaluates to true and abort execution if not.
Arguments structure for mmhal_wlan_sdio_cmd53_read().
uint16_t block_size
If non-zero this indicates that the data should be transferred in block mode with the given block siz...
uint32_t sdio_arg
The SDIO argument.
uint8_t * data
Pointer to the data buffer to receive the data.
Arguments structure for mmhal_wlan_sdio_cmd53_write().
const uint8_t * data
Pointer to the data buffer.
uint16_t block_size
If non-zero this indicates that the data should be transferred in block mode with the given block siz...
uint16_t transfer_length
Transfer length measured in blocks if block_size is non-zero otherwise in bytes.
uint32_t sdio_arg
The SDIO argument.