Minor toshsd/sdmmc driver code cleanup/improvement.
This commit is contained in:
parent
9bd9497315
commit
5ab356a248
|
@ -26,7 +26,7 @@
|
|||
|
||||
// Controller specific macros. Add controller specific bits here.
|
||||
// MMC_CMD_[response type]_[transfer type]
|
||||
// Transfer type: R = read, MR = multi-block read, W = write, MW = multi-block write.
|
||||
// Transfer type: R = read, W = write.
|
||||
#define MMC_CMD_NONE(id) (CMD_RESP_NONE | (id))
|
||||
#define MMC_CMD_R1(id) (CMD_RESP_R1 | (id))
|
||||
#define MMC_CMD_R1b(id) (CMD_RESP_R1b | (id))
|
||||
|
@ -36,69 +36,67 @@
|
|||
#define MMC_CMD_R5(id) (CMD_RESP_R5 | (id))
|
||||
#define MMC_CMD_R1_R(id) (CMD_DIR_R | CMD_DT_EN | CMD_RESP_R1 | (id))
|
||||
#define MMC_CMD_R1_W(id) (CMD_DIR_W | CMD_DT_EN | CMD_RESP_R1 | (id))
|
||||
#define MMC_CMD_R1_MR(id) (CMD_MBT | CMD_DIR_R | CMD_DT_EN | CMD_RESP_R1 | (id))
|
||||
#define MMC_CMD_R1_MW(id) (CMD_MBT | CMD_DIR_W | CMD_DT_EN | CMD_RESP_R1 | (id))
|
||||
|
||||
|
||||
// Basic commands and read-stream command (class 0 and class 1).
|
||||
#define MMC_GO_IDLE_STATE MMC_CMD_NONE(0u) // -, [31:0] 0x00000000 GO_IDLE_STATE, 0xF0F0F0F0 GO_PRE_IDLE_STATE, 0xFFFFFFFA BOOT_INITIATION.
|
||||
#define MMC_SEND_OP_COND MMC_CMD_R3(1u) // R3, [31:0] OCR with-out busy.
|
||||
#define MMC_ALL_SEND_CID MMC_CMD_R2(2u) // R2, [31:0] stuff bits.
|
||||
#define MMC_SET_RELATIVE_ADDR MMC_CMD_R1(3u) // R1, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_SET_DSR MMC_CMD_NONE(4u) // -, [31:16] DSR [15:0] stuff bits.
|
||||
#define MMC_SLEEP_AWAKE MMC_CMD_R1b(5u) // R1b, [31:16] RCA [15] Sleep/Awake [14:0] stuff bits.
|
||||
#define MMC_SWITCH MMC_CMD_R1b(6u) // R1b, [31:26] Set to 0 [25:24] Access [23:16] Index [15:8] Value [7:3] Set to 0 [2:0] Cmd Set.
|
||||
#define MMC_SELECT_CARD MMC_CMD_R1(7u) // R1, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_DESELECT_CARD MMC_CMD_NONE(7u) // -, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_SELECT_CARD_R1b MMC_CMD_R1b(7u) // R1b, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_SEND_EXT_CSD MMC_CMD_R1_R(8u) // R1, [31:0] stuff bits.
|
||||
#define MMC_SEND_CSD MMC_CMD_R2(9u) // R2, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_SEND_CID MMC_CMD_R2(10u) // R2, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_READ_DAT_UNTIL_STOP MMC_CMD_R1_MR(11u) // R1, [31:0] data address.
|
||||
#define MMC_STOP_TRANSMISSION_R MMC_CMD_R1(12u) // R1, [31:16] RCA [15:1] stuff bits [0] HPI.
|
||||
#define MMC_STOP_TRANSMISSION_W MMC_CMD_R1b(12u) // R1b, [31:16] RCA [15:1] stuff bits [0] HPI.
|
||||
#define MMC_SEND_STATUS MMC_CMD_R1(13u) // R1, [31:16] RCA [15:1] stuff bits [0] HPI.
|
||||
#define MMC_BUSTEST_R MMC_CMD_R1_R(14u) // R1, [31:0] stuff bits.
|
||||
#define MMC_GO_INACTIVE_STATE MMC_CMD_NONE(15u) // -, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_BUSTEST_W MMC_CMD_R1_W(19u) // R1, [31:0] stuff bits.
|
||||
#define MMC_GO_IDLE_STATE MMC_CMD_NONE(0u) // -, [31:0] 0x00000000 GO_IDLE_STATE, 0xF0F0F0F0 GO_PRE_IDLE_STATE, 0xFFFFFFFA BOOT_INITIATION.
|
||||
#define MMC_SEND_OP_COND MMC_CMD_R3(1u) // R3, [31:0] OCR with-out busy.
|
||||
#define MMC_ALL_SEND_CID MMC_CMD_R2(2u) // R2, [31:0] stuff bits.
|
||||
#define MMC_SET_RELATIVE_ADDR MMC_CMD_R1(3u) // R1, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_SET_DSR MMC_CMD_NONE(4u) // -, [31:16] DSR [15:0] stuff bits.
|
||||
#define MMC_SLEEP_AWAKE MMC_CMD_R1b(5u) // R1b, [31:16] RCA [15] Sleep/Awake [14:0] stuff bits.
|
||||
#define MMC_SWITCH MMC_CMD_R1b(6u) // R1b, [31:26] Set to 0 [25:24] Access [23:16] Index [15:8] Value [7:3] Set to 0 [2:0] Cmd Set.
|
||||
#define MMC_SELECT_CARD MMC_CMD_R1(7u) // R1, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_DESELECT_CARD MMC_CMD_NONE(7u) // -, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_SELECT_CARD_R1b MMC_CMD_R1b(7u) // R1b, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_SEND_EXT_CSD MMC_CMD_R1_R(8u) // R1, [31:0] stuff bits.
|
||||
#define MMC_SEND_CSD MMC_CMD_R2(9u) // R2, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_SEND_CID MMC_CMD_R2(10u) // R2, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_READ_DAT_UNTIL_STOP MMC_CMD_R1_R(11u) // R1, [31:0] data address.
|
||||
#define MMC_STOP_TRANSMISSION_R MMC_CMD_R1(12u) // R1, [31:16] RCA [15:1] stuff bits [0] HPI.
|
||||
#define MMC_STOP_TRANSMISSION_W MMC_CMD_R1b(12u) // R1b, [31:16] RCA [15:1] stuff bits [0] HPI.
|
||||
#define MMC_SEND_STATUS MMC_CMD_R1(13u) // R1, [31:16] RCA [15:1] stuff bits [0] HPI.
|
||||
#define MMC_BUSTEST_R MMC_CMD_R1_R(14u) // R1, [31:0] stuff bits.
|
||||
#define MMC_GO_INACTIVE_STATE MMC_CMD_NONE(15u) // -, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_BUSTEST_W MMC_CMD_R1_W(19u) // R1, [31:0] stuff bits.
|
||||
|
||||
// Block-oriented read commands (class 2).
|
||||
#define MMC_SET_BLOCKLEN MMC_CMD_R1(16u) // R1, [31:0] block length.
|
||||
#define MMC_READ_SINGLE_BLOCK MMC_CMD_R1_R(17u) // R1, [31:0] data address.
|
||||
#define MMC_READ_MULTIPLE_BLOCK MMC_CMD_R1_MR(18u) // R1, [31:0] data address.
|
||||
#define MMC_SET_BLOCKLEN MMC_CMD_R1(16u) // R1, [31:0] block length.
|
||||
#define MMC_READ_SINGLE_BLOCK MMC_CMD_R1_R(17u) // R1, [31:0] data address.
|
||||
#define MMC_READ_MULTIPLE_BLOCK MMC_CMD_R1_R(18u) // R1, [31:0] data address.
|
||||
|
||||
// Stream write commands (class 3).
|
||||
#define MMC_WRITE_DAT_UNTIL_STOP MMC_CMD_R1_MW(20u) // R1, [31:0] data address.
|
||||
#define MMC_WRITE_DAT_UNTIL_STOP MMC_CMD_R1_W(20u) // R1, [31:0] data address.
|
||||
|
||||
// Block-oriented write commands (class 4).
|
||||
#define MMC_SET_BLOCK_COUNT MMC_CMD_R1(23u) // R1, [31] Reliable Write Request [30:16] set to 0 [15:0] number of blocks.
|
||||
#define MMC_WRITE_BLOCK MMC_CMD_R1_W(24u) // R1, [31:0] data address.
|
||||
#define MMC_WRITE_MULTIPLE_BLOCK MMC_CMD_R1_MW(25u) // R1, [31:0] data address.
|
||||
#define MMC_PROGRAM_CID MMC_CMD_R1_W(26u) // R1, [31:0] stuff bits.
|
||||
#define MMC_PROGRAM_CSD MMC_CMD_R1_W(27u) // R1, [31:0] stuff bits.
|
||||
#define MMC_SET_BLOCK_COUNT MMC_CMD_R1(23u) // R1, [31] Reliable Write Request [30:16] set to 0 [15:0] number of blocks.
|
||||
#define MMC_WRITE_BLOCK MMC_CMD_R1_W(24u) // R1, [31:0] data address.
|
||||
#define MMC_WRITE_MULTIPLE_BLOCK MMC_CMD_R1_W(25u) // R1, [31:0] data address.
|
||||
#define MMC_PROGRAM_CID MMC_CMD_R1_W(26u) // R1, [31:0] stuff bits.
|
||||
#define MMC_PROGRAM_CSD MMC_CMD_R1_W(27u) // R1, [31:0] stuff bits.
|
||||
|
||||
// Block-oriented write protection commands (class 6).
|
||||
#define MMC_SET_WRITE_PROT MMC_CMD_R1b(28u) // R1b, [31:0] data address.
|
||||
#define MMC_CLR_WRITE_PROT MMC_CMD_R1b(29u) // R1b, [31:0] data address.
|
||||
#define MMC_SEND_WRITE_PROT MMC_CMD_R1_R(30u) // R1, [31:0] write protect data address.
|
||||
#define MMC_SEND_WRITE_PROT_TYPE MMC_CMD_R1_R(31u) // R1, [31:0] write protect data address.
|
||||
#define MMC_SET_WRITE_PROT MMC_CMD_R1b(28u) // R1b, [31:0] data address.
|
||||
#define MMC_CLR_WRITE_PROT MMC_CMD_R1b(29u) // R1b, [31:0] data address.
|
||||
#define MMC_SEND_WRITE_PROT MMC_CMD_R1_R(30u) // R1, [31:0] write protect data address.
|
||||
#define MMC_SEND_WRITE_PROT_TYPE MMC_CMD_R1_R(31u) // R1, [31:0] write protect data address.
|
||||
|
||||
// Erase commands (class 5).
|
||||
#define MMC_ERASE_GROUP_START MMC_CMD_R1(35u) // R1, [31:0] data address.
|
||||
#define MMC_ERASE_GROUP_END MMC_CMD_R1(36u) // R1, [31:0] data address.
|
||||
#define MMC_ERASE MMC_CMD_R1b(38u) // R1b, [31] Secure request [30:16] set to 0 [15] Force Garbage Collect request [14:1] set to 0 [0] Identify Write block for Erase.
|
||||
#define MMC_ERASE_GROUP_START MMC_CMD_R1(35u) // R1, [31:0] data address.
|
||||
#define MMC_ERASE_GROUP_END MMC_CMD_R1(36u) // R1, [31:0] data address.
|
||||
#define MMC_ERASE MMC_CMD_R1b(38u) // R1b, [31] Secure request [30:16] set to 0 [15] Force Garbage Collect request [14:1] set to 0 [0] Identify Write block for Erase.
|
||||
|
||||
// I/O mode commands (class 9).
|
||||
#define MMC_FAST_IO MMC_CMD_R4(39u) // R4, [31:16] RCA [15:15] register write flag [14:8] register address [7:0] register data.
|
||||
#define MMC_GO_IRQ_STATE MMC_CMD_R5(40u) // R5, [31:0] stuff bits.
|
||||
#define MMC_FAST_IO MMC_CMD_R4(39u) // R4, [31:16] RCA [15:15] register write flag [14:8] register address [7:0] register data.
|
||||
#define MMC_GO_IRQ_STATE MMC_CMD_R5(40u) // R5, [31:0] stuff bits.
|
||||
|
||||
// Lock card commands (class 7).
|
||||
#define MMC_LOCK_UNLOCK MMC_CMD_R1_W(42u) // R1, [31:0] stuff bits.
|
||||
#define MMC_LOCK_UNLOCK MMC_CMD_R1_W(42u) // R1, [31:0] stuff bits.
|
||||
|
||||
// Application-specific commands (class 8).
|
||||
#define MMC_APP_CMD MMC_CMD_R1(55u) // R1, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_GEN_CMD_R MMC_CMD_R1_R(56u) // R1, [31:1] stuff bits [0] RD/WR = 1.
|
||||
#define MMC_GEN_CMD_W MMC_CMD_R1_W(56u) // R1, [31:1] stuff bits [0] RD/WR = 0.
|
||||
#define MMC_APP_CMD MMC_CMD_R1(55u) // R1, [31:16] RCA [15:0] stuff bits.
|
||||
#define MMC_GEN_CMD_R MMC_CMD_R1_R(56u) // R1, [31:1] stuff bits [0] RD/WR = 1.
|
||||
#define MMC_GEN_CMD_W MMC_CMD_R1_W(56u) // R1, [31:1] stuff bits [0] RD/WR = 0.
|
||||
|
||||
|
||||
// 7.13 Card status.
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// Controller specific macros. Add controller specific bits here.
|
||||
// SD_[command type]_[response type]_[transfer type]
|
||||
// Command type: CMD = regular command, ACMD = Application-Specific Command.
|
||||
// Transfer type: R = read, MR = multi-block read, W = write, MW = multi-block write.
|
||||
// Transfer type: R = read, W = write.
|
||||
#define SD_CMD_NONE(id) (CMD_RESP_NONE | (id))
|
||||
#define SD_CMD_R1(id) (CMD_RESP_R1 | (id))
|
||||
#define SD_CMD_R1b(id) (CMD_RESP_R1b | (id))
|
||||
|
@ -35,8 +35,6 @@
|
|||
#define SD_CMD_R7(id) (CMD_RESP_R7 | (id))
|
||||
#define SD_CMD_R1_R(id) (CMD_DIR_R | CMD_DT_EN | CMD_RESP_R1 | (id))
|
||||
#define SD_CMD_R1_W(id) (CMD_DIR_W | CMD_DT_EN | CMD_RESP_R1 | (id))
|
||||
#define SD_CMD_R1_MR(id) (CMD_MBT | CMD_DIR_R | CMD_DT_EN | CMD_RESP_R1 | (id))
|
||||
#define SD_CMD_R1_MW(id) (CMD_MBT | CMD_DIR_W | CMD_DT_EN | CMD_RESP_R1 | (id))
|
||||
#define SD_ACMD_R1(id) (CMD_RESP_R1 | CMD_ACMD | (id))
|
||||
#define SD_ACMD_R3(id) (CMD_RESP_R3 | CMD_ACMD | (id))
|
||||
#define SD_ACMD_R1_R(id) (CMD_DIR_R | CMD_DT_EN | CMD_RESP_R1 | CMD_ACMD | (id))
|
||||
|
@ -61,7 +59,7 @@
|
|||
// Block-Oriented Read Commands (class 2).
|
||||
#define SD_SET_BLOCKLEN SD_CMD_R1(16u) // R1, [31:0] block length.
|
||||
#define SD_READ_SINGLE_BLOCK SD_CMD_R1_R(17u) // R1, [31:0] data address.
|
||||
#define SD_READ_MULTIPLE_BLOCK SD_CMD_R1_MR(18u) // R1, [31:0] data address.
|
||||
#define SD_READ_MULTIPLE_BLOCK SD_CMD_R1_R(18u) // R1, [31:0] data address.
|
||||
#define SD_SEND_TUNING_BLOCK SD_CMD_R1_R(19u) // R1, [31:0] reserved bits (all 0).
|
||||
#define SD_SPEED_CLASS_CONTROL SD_CMD_R1b(20u) // R1b, [31:28] Speed Class Control [27:0] See command description.
|
||||
#define SD_ADDRESS_EXTENSION SD_CMD_R1(22u) // R1, [31:6] reserved bits (all 0) [5:0] extended address.
|
||||
|
@ -73,7 +71,7 @@
|
|||
// ADDRESS_EXTENSION
|
||||
// SET_BLOCK_COUNT
|
||||
#define SD_WRITE_BLOCK SD_CMD_R1_W(24u) // R1, [31:0] data address.
|
||||
#define SD_WRITE_MULTIPLE_BLOCK SD_CMD_R1_MW(25u) // R1, [31:0] data address.
|
||||
#define SD_WRITE_MULTIPLE_BLOCK SD_CMD_R1_W(25u) // R1, [31:0] data address.
|
||||
#define SD_PROGRAM_CSD SD_CMD_R1_W(27u) // R1, [31:0] stuff bits.
|
||||
|
||||
// Block Oriented Write Protection Commands (class 6).
|
||||
|
@ -111,8 +109,8 @@
|
|||
// Function Extension Commands (class 11).
|
||||
#define SD_READ_EXTR_SINGLE SD_CMD_R1_R(48u) // R1, [31] MIO0: Memory, 1: I/O [30:27] FNO[26] Reserved (=0) [25:9] ADDR [8:0] LEN.
|
||||
#define SD_WRITE_EXTR_SINGLE SD_CMD_R1_W(49u) // R1, [31] MIO0: Memory, 1: I/O [30:27] FNO [26] MW [25:9] ADDR [8:0] LEN/MASK.
|
||||
#define SD_READ_EXTR_MULTI SD_CMD_R1_MR(58u) // R1, [31] MIO0: Memory, 1: I/O [30:27] FNO [26] BUS0: 512B, 1: 32KB [25:9] ADDR [8:0] BUC.
|
||||
#define SD_WRITE_EXTR_MULTI SD_CMD_R1_MW(59u) // R1, [31] MIO0: Memory, 1: I/O [30:27] FNO [26] BUS0: 512B, 1: 32KB [25:9] ADDR [8:0] BUC.
|
||||
#define SD_READ_EXTR_MULTI SD_CMD_R1_R(58u) // R1, [31] MIO0: Memory, 1: I/O [30:27] FNO [26] BUS0: 512B, 1: 32KB [25:9] ADDR [8:0] BUC.
|
||||
#define SD_WRITE_EXTR_MULTI SD_CMD_R1_W(59u) // R1, [31] MIO0: Memory, 1: I/O [30:27] FNO [26] BUS0: 512B, 1: 32KB [25:9] ADDR [8:0] BUC.
|
||||
|
||||
// Command Queue Function Commands (class 1).
|
||||
#define SD_Q_MANAGEMENT SD_CMD_R1b(43u) // R1b, [31:21] Reserved [20:16]: Task ID [3:0]: Operation Code (Abort tasks etc.).
|
||||
|
|
|
@ -120,8 +120,8 @@ ALWAYS_INLINE vu32* getToshsdFifo(Toshsd *const regs)
|
|||
#define PORTSEL_UNK10 (1u<<10) // Unknown writable bit 10?
|
||||
|
||||
// REG_SD_STOP
|
||||
#define STOP_STOP (1u) // Stop/abort a transfer.
|
||||
#define STOP_AUTO_STOP (1u<<8) // Automatically send CMD12 on block transfer end.
|
||||
#define STOP_STOP (1u) // Abort data transfer and send STOP_TRANSMISSION CMD.
|
||||
#define STOP_AUTO_STOP (1u<<8) // Automatically send STOP_TRANSMISSION on multi-block transfer end.
|
||||
|
||||
// REG_SD_STATUS1/2 Write 0 to acknowledge a bit.
|
||||
// REG_SD_STATUS1/2_MASK (M) = Maskable bit. 1 = disabled.
|
||||
|
|
|
@ -60,11 +60,11 @@
|
|||
#endif // #ifdef _3DS
|
||||
|
||||
|
||||
#define SD_IF_COND_ARG (SD_CMD8_VHS_2_7_3_6V | SD_CMD8_CHK_PATT)
|
||||
#define SD_OP_COND_ARG (SD_ACMD41_XPC | SD_OCR_3_2_3_3V) // We support 150 mA and 3.3V. Without HCS bit.
|
||||
#define MMC_OP_COND_ARG (MMC_OCR_SECT_MODE | MMC_OCR_3_2_3_3V) // We support sector addressing and 3.3V.
|
||||
#define MMC_OCR_VOLT_MASK (MMC_OCR_3_2_3_3V) // We support 3.3V only.
|
||||
#define SD_OCR_VOLT_MASK (SD_OCR_3_2_3_3V) // We support 3.3V only.
|
||||
#define SD_IF_COND_ARG (SD_CMD8_VHS_2_7_3_6V | SD_CMD8_CHK_PATT)
|
||||
#define SD_OP_COND_ARG (SD_ACMD41_XPC | SD_OCR_VOLT_MASK) // We support 150 mA and 3.3V. Without HCS bit.
|
||||
#define MMC_OP_COND_ARG (MMC_OCR_SECT_MODE | MMC_OCR_VOLT_MASK) // We support sector addressing and 3.3V.
|
||||
|
||||
// Note: DEV_TYPE_NONE must be zero.
|
||||
enum
|
||||
|
@ -384,7 +384,7 @@ static u32 initTranState(SdmmcDev *const dev, const u8 devType, const u32 rca, c
|
|||
// Get sector count from EXT_CSD only if sector addressing is used because
|
||||
// byte addressed (e)MMC may set sector count to 0.
|
||||
dev->sectors = ext_csd[EXT_CSD_SEC_COUNT + 3]<<24 | ext_csd[EXT_CSD_SEC_COUNT + 2]<<16 |
|
||||
ext_csd[EXT_CSD_SEC_COUNT + 1]<<8 | ext_csd[EXT_CSD_SEC_COUNT + 0];
|
||||
ext_csd[EXT_CSD_SEC_COUNT + 1]<<8 | ext_csd[EXT_CSD_SEC_COUNT + 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
#include "drivers/toshsd_config.h"
|
||||
|
||||
|
||||
// Using atomic load/store produces better code than volatile
|
||||
// but still ensures that the status is always read from memory.
|
||||
#define GET_STATUS(ptr) atomic_load_explicit((ptr), memory_order_relaxed)
|
||||
#define SET_STATUS(ptr, val) atomic_store_explicit((ptr), (val), memory_order_relaxed)
|
||||
|
||||
|
||||
static u32 g_status[2] = {0};
|
||||
|
||||
|
||||
|
@ -31,14 +37,9 @@ ALWAYS_INLINE u8 port2Controller(const u8 portNum)
|
|||
return portNum / 2;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u8 irq2controller(const u32 id)
|
||||
{
|
||||
return (id == TOSHSD_IRQ_ID_CONTROLLER1 ? 0 : 1);
|
||||
}
|
||||
|
||||
static void toshsdIsr(const u32 id)
|
||||
{
|
||||
const u8 controller = irq2controller(id);
|
||||
const u8 controller = (id == TOSHSD_IRQ_ID_CONTROLLER1 ? 0 : 1);
|
||||
Toshsd *const regs = getToshsdRegs(controller);
|
||||
|
||||
g_status[controller] |= regs->sd_status;
|
||||
|
@ -67,6 +68,9 @@ void TOSHSD_init(void)
|
|||
regs->dma_ext_mode = DMA_EXT_DMA_MODE;
|
||||
|
||||
// Reset. Unlike similar controllers no delay is needed.
|
||||
// Resets the following regs:
|
||||
// REG_SD_STOP, REG_SD_RESP0-7, REG_SD_STATUS1-2, REG_SD_ERR_STATUS1-2,
|
||||
// REG_SD_CLK_CTRL, REG_SD_OPTION, REG_SDIO_STATUS.
|
||||
regs->soft_rst = SOFT_RST_RST;
|
||||
regs->soft_rst = SOFT_RST_NORST;
|
||||
|
||||
|
@ -175,8 +179,8 @@ static void getResponse(const Toshsd *const regs, ToshsdPort *const port, const
|
|||
// single block read transfer.
|
||||
static void doCpuTransfer(Toshsd *const regs, const u16 cmd, u32 *buf, const u32 *const statusPtr)
|
||||
{
|
||||
const u32 blockLen = regs->sd_blocklen;
|
||||
u32 blockCount = regs->sd_blockcount;
|
||||
const u32 wordBlockLen = regs->sd_blocklen / 4;
|
||||
u32 blockCount = regs->sd_blockcount;
|
||||
vu32 *const fifo = getToshsdFifo(regs);
|
||||
if(cmd & CMD_DIR_R)
|
||||
{
|
||||
|
@ -185,20 +189,18 @@ static void doCpuTransfer(Toshsd *const regs, const u16 cmd, u32 *buf, const u32
|
|||
__wfi();
|
||||
if(regs->sd_fifo32_cnt & FIFO32_FULL) // RX ready.
|
||||
{
|
||||
const u32 *const blockEnd = buf + (blockLen / 4);
|
||||
const u32 *const blockEnd = buf + wordBlockLen;
|
||||
do
|
||||
{
|
||||
buf[0] = *fifo;
|
||||
buf[1] = *fifo;
|
||||
buf[2] = *fifo;
|
||||
buf[3] = *fifo;
|
||||
|
||||
buf += 4;
|
||||
*buf++ = *fifo;
|
||||
*buf++ = *fifo;
|
||||
*buf++ = *fifo;
|
||||
*buf++ = *fifo;
|
||||
} while(buf < blockEnd);
|
||||
|
||||
blockCount--;
|
||||
}
|
||||
} while((atomic_load_explicit(statusPtr, memory_order_relaxed) & STATUS_MASK_ERR) == 0 && blockCount);
|
||||
} while((GET_STATUS(statusPtr) & STATUS_MASK_ERR) == 0 && blockCount > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -209,20 +211,18 @@ static void doCpuTransfer(Toshsd *const regs, const u16 cmd, u32 *buf, const u32
|
|||
__wfi();
|
||||
if(!(regs->sd_fifo32_cnt & FIFO32_NOT_EMPTY)) // TX request.
|
||||
{
|
||||
const u32 *const blockEnd = buf + (blockLen / 4);
|
||||
const u32 *const blockEnd = buf + wordBlockLen;
|
||||
do
|
||||
{
|
||||
*fifo = buf[0];
|
||||
*fifo = buf[1];
|
||||
*fifo = buf[2];
|
||||
*fifo = buf[3];
|
||||
|
||||
buf += 4;
|
||||
*fifo = *buf++;
|
||||
*fifo = *buf++;
|
||||
*fifo = *buf++;
|
||||
*fifo = *buf++;
|
||||
} while(buf < blockEnd);
|
||||
|
||||
blockCount--;
|
||||
}
|
||||
} while((atomic_load_explicit(statusPtr, memory_order_relaxed) & STATUS_MASK_ERR) == 0 && blockCount);
|
||||
} while((GET_STATUS(statusPtr) & STATUS_MASK_ERR) == 0 && blockCount > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,18 +233,20 @@ u32 TOSHSD_sendCommand(ToshsdPort *const port, const u16 cmd, const u32 arg)
|
|||
|
||||
// Clear status before sending another command.
|
||||
u32 *const statusPtr = &g_status[controller];
|
||||
atomic_store_explicit(statusPtr, 0, memory_order_relaxed);
|
||||
SET_STATUS(statusPtr, 0);
|
||||
|
||||
setPort(regs, port);
|
||||
regs->sd_blockcount = port->blocks; // sd_blockcount32 doesn't need to be set.
|
||||
regs->sd_stop = ((cmd & CMD_MBT) ? STOP_AUTO_STOP : 0); // Auto CMD12 on multi-block transfer.
|
||||
const u16 blocks = port->blocks;
|
||||
regs->sd_blockcount = blocks; // sd_blockcount32 doesn't need to be set.
|
||||
regs->sd_stop = STOP_AUTO_STOP; // Auto STOP_TRANSMISSION (CMD12) on multi-block transfer.
|
||||
regs->sd_arg = arg;
|
||||
|
||||
// We don't need FIFO IRQs when using DMA. buf = NULL means DMA.
|
||||
u32 *buf = port->buf;
|
||||
const u16 fifoIrqs = (buf != NULL ? (cmd & CMD_DIR_R ? FIFO32_FULL_IE : FIFO32_NOT_EMPTY_IE) : 0u);
|
||||
regs->sd_fifo32_cnt = fifoIrqs | FIFO32_CLEAR | FIFO32_EN;
|
||||
regs->sd_cmd = cmd; // Start.
|
||||
u16 f32Cnt = FIFO32_CLEAR | FIFO32_EN;
|
||||
if(buf != NULL) f32Cnt |= (cmd & CMD_DIR_R ? FIFO32_FULL_IE : FIFO32_NOT_EMPTY_IE);
|
||||
regs->sd_fifo32_cnt = f32Cnt;
|
||||
regs->sd_cmd = (blocks > 1 ? CMD_MBT | cmd : cmd); // Start.
|
||||
|
||||
// If we have to transfer data do so now.
|
||||
if((cmd & CMD_DT_EN) && (buf != NULL))
|
||||
|
@ -253,15 +255,15 @@ u32 TOSHSD_sendCommand(ToshsdPort *const port, const u16 cmd, const u32 arg)
|
|||
// Response end usually comes immediately after the command
|
||||
// has been sent so we need to check before __wfi().
|
||||
// On error response end still fires.
|
||||
while(!(atomic_load_explicit(statusPtr, memory_order_relaxed) & STATUS_RESP_END)) __wfi();
|
||||
while((GET_STATUS(statusPtr) & STATUS_RESP_END) == 0) __wfi();
|
||||
getResponse(regs, port, cmd);
|
||||
|
||||
// Wait for data end if needed.
|
||||
// On error data end still fires.
|
||||
if(cmd & CMD_DT_EN)
|
||||
while(!(atomic_load_explicit(statusPtr, memory_order_relaxed) & STATUS_DATA_END)) __wfi();
|
||||
while((GET_STATUS(statusPtr) & STATUS_DATA_END) == 0) __wfi();
|
||||
|
||||
// STATUS_CMD_BUSY is no longer set at this point.
|
||||
|
||||
return atomic_load_explicit(statusPtr, memory_order_relaxed) & STATUS_MASK_ERR;
|
||||
return GET_STATUS(statusPtr) & STATUS_MASK_ERR;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue