7#include "porting_assistant.h"
12#define MORSE_REG_ADDRESS_BASE 0x10000
13#define MORSE_REG_ADDRESS_WINDOW_0 MORSE_REG_ADDRESS_BASE
14#define MORSE_REG_ADDRESS_WINDOW_1 (MORSE_REG_ADDRESS_BASE + 1)
15#define MORSE_REG_ADDRESS_CONFIG (MORSE_REG_ADDRESS_BASE + 2)
17#define MORSE_CONFIG_ACCESS_1BYTE 0
18#define MORSE_CONFIG_ACCESS_2BYTE 1
19#define MORSE_CONFIG_ACCESS_4BYTE 2
22#define PACK_LE16(dst16_data, src8_array) \
24 dst16_data = *src8_array; \
25 dst16_data |= ((uint16_t)*(src8_array + 1) << 8); \
29#define PACK_BE16(dst16_data, src8_array) \
31 dst16_data = *(src8_array + 1); \
32 dst16_data |= ((uint16_t)*(src8_array) << 8); \
36#define UNPACK_LE16(dst8_array, src16_data) \
38 *dst8_array = (uint8_t)(src16_data); \
39 *(dst8_array + 1) = (uint8_t)(src16_data >> 8); \
43#define UNPACK_BE16(dst8_array, src16_data) \
45 *(dst8_array + 1) = (uint8_t)(src16_data); \
46 *(dst8_array) = (uint8_t)(src16_data >> 8); \
50#define PACK_LE32(dst32_data, src8_array) \
52 dst32_data = *src8_array; \
53 dst32_data |= ((uint32_t)*(src8_array + 1) << 8); \
54 dst32_data |= ((uint32_t)*(src8_array + 2) << 16); \
55 dst32_data |= ((uint32_t)*(src8_array + 3) << 24); \
59#define PACK_BE32(dst32_data, src8_array) \
61 dst32_data = *(src8_array + 3); \
62 dst32_data |= ((uint32_t)*(src8_array + 2) << 8); \
63 dst32_data |= ((uint32_t)*(src8_array + 1) << 16); \
64 dst32_data |= ((uint32_t)*(src8_array) << 24); \
68#define UNPACK_LE32(dst8_array, src32_data) \
70 *dst8_array = (uint8_t)(src32_data); \
71 *(dst8_array + 1) = (uint8_t)(src32_data >> 8); \
72 *(dst8_array + 2) = (uint8_t)(src32_data >> 16); \
73 *(dst8_array + 3) = (uint8_t)(src32_data >> 24); \
77#define UNPACK_BE32(dst8_array, src32_data) \
79 *(dst8_array + 3) = (uint8_t)(src32_data); \
80 *(dst8_array + 2) = (uint8_t)(src32_data >> 8); \
81 *(dst8_array + 1) = (uint8_t)(src32_data >> 16); \
82 *(dst8_array) = (uint8_t)(src32_data >> 24); \
86#define PACK_LE64(dst64_data, src8_array) \
88 dst64_data = ((uint64_t)*(src8_array + 0) << 0); \
89 dst64_data |= ((uint64_t)*(src8_array + 1) << 8); \
90 dst64_data |= ((uint64_t)*(src8_array + 2) << 16); \
91 dst64_data |= ((uint64_t)*(src8_array + 3) << 24); \
92 dst64_data |= ((uint64_t)*(src8_array + 4) << 32); \
93 dst64_data |= ((uint64_t)*(src8_array + 5) << 40); \
94 dst64_data |= ((uint64_t)*(src8_array + 6) << 48); \
95 dst64_data |= ((uint64_t)*(src8_array + 7) << 56); \
99#define PACK_BE64(dst64_data, src8_array) \
101 dst64_data = ((uint64_t)*(src8_array + 7) << 0); \
102 dst64_data |= ((uint64_t)*(src8_array + 6) << 8); \
103 dst64_data |= ((uint64_t)*(src8_array + 5) << 16); \
104 dst64_data |= ((uint64_t)*(src8_array + 4) << 24); \
105 dst64_data |= ((uint64_t)*(src8_array + 3) << 32); \
106 dst64_data |= ((uint64_t)*(src8_array + 2) << 40); \
107 dst64_data |= ((uint64_t)*(src8_array + 1) << 48); \
108 dst64_data |= ((uint64_t)*(src8_array + 0) << 56); \
112#define UNPACK_LE64(dst8_array, src64_data) \
114 *(dst8_array + 0) = (uint8_t)(src64_data >> 0); \
115 *(dst8_array + 1) = (uint8_t)(src64_data >> 8); \
116 *(dst8_array + 2) = (uint8_t)(src64_data >> 16); \
117 *(dst8_array + 3) = (uint8_t)(src64_data >> 24); \
118 *(dst8_array + 4) = (uint8_t)(src64_data >> 32); \
119 *(dst8_array + 5) = (uint8_t)(src64_data >> 40); \
120 *(dst8_array + 6) = (uint8_t)(src64_data >> 48); \
121 *(dst8_array + 7) = (uint8_t)(src64_data >> 56); \
125#define UNPACK_BE64(dst8_array, src64_data) \
127 *(dst8_array + 7) = (uint8_t)(src64_data >> 0); \
128 *(dst8_array + 6) = (uint8_t)(src64_data >> 8); \
129 *(dst8_array + 5) = (uint8_t)(src64_data >> 16); \
130 *(dst8_array + 4) = (uint8_t)(src64_data >> 24); \
131 *(dst8_array + 3) = (uint8_t)(src64_data >> 32); \
132 *(dst8_array + 2) = (uint8_t)(src64_data >> 40); \
133 *(dst8_array + 1) = (uint8_t)(src64_data >> 48); \
134 *(dst8_array + 0) = (uint8_t)(src64_data >> 56); \
138#define CMD53_MAX_BLOCKS 128
143 BLOCK_SIZE_FN1_LOG2 = 3,
144 BLOCK_SIZE_FN2 = 512,
145 BLOCK_SIZE_FN2_LOG2 = 9,
148enum max_block_transfer_size
150 MAX_BLOCK_TRANSFER_SIZE_FN1 = BLOCK_SIZE_FN1 * CMD53_MAX_BLOCKS,
151 MAX_BLOCK_TRANSFER_SIZE_FN2 = BLOCK_SIZE_FN2 * CMD53_MAX_BLOCKS,
155#define CHIP_ACTIVE_SEQ (0x00000000)
161 SDIO_DIR_CARD_TO_HOST = 0,
162 SDIO_DIR_HOST_TO_CARD = 1 << 6,
186#define SDIO_CCCR_IEN_ADDR 0x04u
187#define SDIO_CCCR_IEN_IENM (1u)
188#define SDIO_CCCR_IEN_IEN1 (1u << 1)
190#define SDIO_CCCR_BIC_ADDR 0x07u
191#define SDIO_CCCR_BIC_ECSI (1u << 5)
193static inline uint32_t min_u32(uint32_t a, uint32_t b)
216static int morse_cmd52_write(uint32_t address, uint8_t data,
enum mmhal_sdio_function function)
222 return sdio_spi_send_cmd(SDIO_CMD52, arg, NULL);
246 enum block_size block_size = BLOCK_SIZE_FN2;
247 enum block_size block_size_log2 = BLOCK_SIZE_FN2_LOG2;
251 block_size = BLOCK_SIZE_FN1;
252 block_size_log2 = BLOCK_SIZE_FN1_LOG2;
256 uint16_t num_blocks = len >> block_size_log2;
263 address & 0x0000ffff,
266 .transfer_length = num_blocks,
267 .block_size = BLOCK_SIZE_FN2,
276 uint32_t transfer_size = num_blocks *
block_size;
277 address += transfer_size;
278 data += transfer_size;
279 len -= transfer_size;
288 MMHAL_SDIO_MODE_BYTE,
289 address & 0x0000ffff,
292 .transfer_length = len,
324 enum block_size block_size = BLOCK_SIZE_FN2;
325 enum block_size block_size_log2 = BLOCK_SIZE_FN2_LOG2;
329 block_size = BLOCK_SIZE_FN1;
330 block_size_log2 = BLOCK_SIZE_FN1_LOG2;
334 uint16_t num_blocks = len >> block_size_log2;
341 address & 0x0000ffff,
343 .data = (uint8_t *)
data,
345 .block_size = BLOCK_SIZE_FN2,
354 uint32_t transfer_size = num_blocks *
block_size;
355 address += transfer_size;
356 data += transfer_size;
357 len -= transfer_size;
366 MMHAL_SDIO_MODE_BYTE,
367 address & 0x0000ffff,
369 .data = (uint8_t *)
data,
391static int morse_address_base_set(uint32_t address,
397 address &= 0xFFFF0000;
401 result = morse_cmd52_write(MORSE_REG_ADDRESS_WINDOW_0, (uint8_t)(address >> 16), function);
407 result = morse_cmd52_write(MORSE_REG_ADDRESS_WINDOW_1, (uint8_t)(address >> 24), function);
413 result = morse_cmd52_write(MORSE_REG_ADDRESS_CONFIG, access, function);
423int sdio_spi_read_le32(uint32_t address, uint32_t *
data)
426 uint8_t receive_data[4];
435 result = morse_address_base_set(address, MORSE_CONFIG_ACCESS_4BYTE, function);
441 result = morse_cmd53_read(function, address, receive_data,
sizeof(receive_data));
447 PACK_LE32(*
data, receive_data);
453int sdio_spi_read_multi_byte(uint32_t address, uint8_t *
data, uint32_t len)
457 enum max_block_transfer_size max_transfer_size = MAX_BLOCK_TRANSFER_SIZE_FN2;
460 if (len == 0 || (len & 0x03) != 0)
462 printf(
"Invalid length %lu\n", len);
471 result = morse_address_base_set(address, MORSE_CONFIG_ACCESS_4BYTE, function);
478 uint32_t size = min_u32(len, max_transfer_size);
482 uint32_t next_boundary = (address & 0xFFFF0000) + 0x10000;
483 if ((address + size) > next_boundary)
485 size = next_boundary - address;
488 morse_cmd53_read(function, address,
data, size);
496 if ((size >= 8) && !memcmp(
data,
data + 4, 4))
499 printf(
"Corrupt Payload. Re-Read first 8 bytes\n");
500 morse_cmd53_read(function, address,
data, 8);
512int sdio_spi_write_multi_byte(uint32_t address,
const uint8_t *
data, uint32_t len)
516 enum max_block_transfer_size max_transfer_size = MAX_BLOCK_TRANSFER_SIZE_FN2;
519 if (len == 0 || (len & 0x03) != 0)
521 printf(
"Invalid length %lu\n", len);
530 result = morse_address_base_set(address, MORSE_CONFIG_ACCESS_4BYTE, function);
537 uint32_t size = min_u32(len, max_transfer_size);
541 uint32_t next_boundary = (address & 0xFFFF0000) + 0x10000;
542 if ((address + size) > next_boundary)
544 size = next_boundary - address;
547 result = morse_cmd53_write(function, address,
data, size);
562int sdio_spi_write_le32(uint32_t address, uint32_t
data)
567 result = morse_address_base_set(address, MORSE_CONFIG_ACCESS_4BYTE, function);
573 result = morse_cmd53_write(function, address, (uint8_t *)&
data,
sizeof(
data));
579int sdio_spi_send_cmd(uint8_t cmd_idx, uint32_t arg, uint32_t *rsp)
584int sdio_spi_update_le32(uint32_t address, uint32_t mask, uint32_t value)
588 result = sdio_spi_read_le32(address, ®_value);
593 reg_value |= (value & mask);
594 reg_value &= (value | ~mask);
595 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.