Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to profi200s dsi sd card driver #160

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion code/core/arm7/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ include $(DEVKITARM)/ds_rules
# all directories are relative to this makefile
#---------------------------------------------------------------------------------
BUILD := build
SOURCES := source source/IpcServices source/Sound
SOURCES := source source/IpcServices source/Sound source/mmc
INCLUDES := source ../common build
DATA :=

Expand Down
9 changes: 4 additions & 5 deletions code/core/arm7/source/IpcServices/FsIpcService.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#include "common.h"
#include "../mmc/sdmmc.h"
#include <string.h>
#include "dldi.h"
#include "FsIpcService.h"

extern "C" int sdmmc_sd_startup();

void FsIpcService::Start()
{
if (isDSiMode())
{
sdmmc_sd_startup();
SDMMC_init(SDMMC_DEV_CARD);
}
ThreadIpcService::Start();
}
Expand Down Expand Up @@ -68,12 +67,12 @@ void FsIpcService::DldiWriteSectors(const fs_ipc_cmd_t* cmd) const

void FsIpcService::DsiSdReadSectors(const fs_ipc_cmd_t* cmd) const
{
sdmmc_sdcard_readsectors(cmd->sector, cmd->count, cmd->buffer);
SDMMC_readSectors(SDMMC_DEV_CARD, cmd->sector, cmd->buffer, cmd->count);
SendResponseMessage(0);
}

void FsIpcService::DsiSdWriteSectors(const fs_ipc_cmd_t* cmd) const
{
sdmmc_sdcard_writesectors(cmd->sector, cmd->count, cmd->buffer);
SDMMC_writeSectors(SDMMC_DEV_CARD, cmd->sector, cmd->buffer, cmd->count);
SendResponseMessage(0);
}
6 changes: 6 additions & 0 deletions code/core/arm7/source/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "Arm7State.h"
#include "ExitMode.h"
#include "FramerateAdjustment.h"
#include "mmc/tmio.h"

static FsIpcService sFsIpcService;
static GbaSoundIpcService sGbaSoundIpcService;
Expand Down Expand Up @@ -107,6 +108,11 @@ static void initializeArm7()
sio_setGpioSiIrq(false);
sio_setGpioMode(RCNT0_L_MODE_GPIO);

if (isDSiMode())
{
TMIO_init();
}

initializeIpcServices();

snd_setMasterVolume(127);
Expand Down
21 changes: 21 additions & 0 deletions code/core/arm7/source/mmc/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 profi200

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
16 changes: 16 additions & 0 deletions code/core/arm7/source/mmc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# DSi (TWL) SDMMC code

## Usage
* Call `TMIO_init()` once **after** irqInit() (libnds).
* Call `SDMMC_init(const u8 devNum)`.

If SDMMC_init() succeeded you can use all other SDMMC_...() functions. SDMMC_init() can be called again at any time to reinitialize the SD card/eMMC provided you call SDMMC_deinit() first.

DMA is supported for SDMMC_readSectors() and SDMMC_writeSectors() by passing a NULL pointer for buf and setting up a NDMA channel prior to calling these functions. Note that the TMIO driver does not support unaligned access for DMA and buffers not a multiple of 4 bytes (for CPU and DMA transfers). It's recommended to add a bounce buffer or cache to make sure buffers are 4 bytes aligned.

## License
This software is licensed under the MIT license. See LICENSE.txt for details.

Exemptions:
* The [BlocksDS](https://github.com/blocksds) project and its members are exempt from MIT licensing. They are permitted to relicense the source code of this repository, at their discretion, to the [zlib license](https://zlib.net/zlib_license.html). In doing so they may alter, supplement or entirely remove the copyright notice for each file they choose to relicense.
* The [dsi-modchip](https://github.com/dsi-modchip) project and its members are exempt from MIT licensing. They are permitted to relicense the source code of this repository, at their discretion, to the [LGPL license version 3 or later](https://www.gnu.org/licenses/lgpl-3.0.html). In doing so they may alter, supplement or entirely remove the copyright notice for each file they choose to relicense.
235 changes: 235 additions & 0 deletions code/core/arm7/source/mmc/mmc_spec.h

Large diffs are not rendered by default.

192 changes: 192 additions & 0 deletions code/core/arm7/source/mmc/sd_spec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
#pragma once

// SPDX-License-Identifier: MIT
// Copyright (c) 2023 profi200

// Based on SD specification version 8.00.

#include "tmio.h"


// 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, 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))
#define SD_CMD_R2(id) (CMD_RESP_R2 | (id))
#define SD_CMD_R6(id) (CMD_RESP_R6 | (id))
#define SD_CMD_R7(id) (CMD_RESP_R7 | (id))
#define SD_CMD_R1_R(id) (CMD_DATA_R | CMD_DATA_EN | CMD_RESP_R1 | (id))
#define SD_CMD_R1_W(id) (CMD_DATA_W | CMD_DATA_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_DATA_R | CMD_DATA_EN | CMD_RESP_R1 | CMD_ACMD | (id))


// Basic Commands (class 0).
#define SD_GO_IDLE_STATE SD_CMD_NONE(0u) // -, [31:0] stuff bits.
#define SD_ALL_SEND_CID SD_CMD_R2(2u) // R2, [31:0] stuff bits.
#define SD_SEND_RELATIVE_ADDR SD_CMD_R6(3u) // R6, [31:0] stuff bits.
#define SD_SET_DSR SD_CMD_NONE(4u) // -, [31:16] DSR [15:0] stuff bits.
#define SD_SELECT_CARD SD_CMD_R1b(7u) // R1b, [31:16] RCA [15:0] stuff bits.
#define SD_DESELECT_CARD SD_CMD_NONE(7u) // -, [31:16] RCA [15:0] stuff bits.
#define SD_SEND_IF_COND SD_CMD_R7(8u) // R7, [31:12] reserved bits [11:8] supply voltage (VHS) [7:0] check pattern.
#define SD_SEND_CSD SD_CMD_R2(9u) // R2, [31:16] RCA [15:0] stuff bits.
#define SD_SEND_CID SD_CMD_R2(10u) // R2, [31:16] RCA [15:0] stuff bits.
#define SD_VOLTAGE_SWITCH SD_CMD_R1(11u) // R1, [31:0] reserved bits (all 0).
#define SD_STOP_TRANSMISSION SD_CMD_R1b(12u) // R1b, [31:0] stuff bits.
#define SD_SEND_STATUS SD_CMD_R1(13u) // R1, [31:16] RCA [15] Send Task Status Register [14:0] stuff bits.
#define SD_SEND_TASK_STATUS SD_CMD_R1(13u) // R1, [31:16] RCA [15] Send Task Status Register [14:0] stuff bits.
#define SD_GO_INACTIVE_STATE SD_CMD_NONE(15u) // -, [31:16] RCA [15:0] reserved bits.

// 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_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.
#define SD_SET_BLOCK_COUNT SD_CMD_R1(23u) // R1, [31:0] Block Count.

// Block-Oriented Write Commands (class 4).
// SET_BLOCKLEN
// SPEED_CLASS_CONTROL
// 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_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).
#define SD_SET_WRITE_PROT SD_CMD_R1b(28u) // R1b, [31:0] data address.
#define SD_CLR_WRITE_PROT SD_CMD_R1b(29u) // R1b, [31:0] data address.
#define SD_SEND_WRITE_PROT SD_CMD_R1_R(30u) // R1, [31:0] write protect data address.

// Erase Commands (class 5).
#define SD_ERASE_WR_BLK_START SD_CMD_R1(32u) // R1, [31:0] data address.
#define SD_ERASE_WR_BLK_END SD_CMD_R1(33u) // R1, [31:0] data address.
#define SD_ERASE SD_CMD_R1b(38u) // R1b, [31:0] Erase Function.

// Lock Card (class 7).
// SET_BLOCKLEN
// Command 40 "Defined by DPS Spec.".
#define SD_LOCK_UNLOCK SD_CMD_R1_W(42u) // R1, [31:0] Reserved bits (Set all 0).

// Application-Specific Commands (class 8).
#define SD_APP_CMD SD_CMD_R1(55u) // R1, [31:16] RCA [15:0] stuff bits.
#define SD_GEN_CMD_R SD_CMD_R1_R(56u) // R1, [31:1] stuff bits. [0]: RD/WR = 1.
#define SD_GEN_CMD_W SD_CMD_R1_W(56u) // R1, [31:1] stuff bits. [0]: RD/WR = 0.

// Application Specific Commands used/reserved by SD Memory Card.
#define SD_APP_SET_BUS_WIDTH SD_ACMD_R1(6u) // R1, [31:2] stuff bits [1:0] bus width.
#define SD_APP_SD_STATUS SD_ACMD_R1_R(13u) // R1, [31:0] stuff bits.
#define SD_APP_SEND_NUM_WR_BLOCKS SD_ACMD_R1_R(22u) // R1, [31:0] stuff bits.
#define SD_APP_SET_WR_BLK_ERASE_COUNT SD_ACMD_R1(23u) // R1, [31:23] stuff bits [22:0] Number of blocks.
#define SD_APP_SD_SEND_OP_COND SD_ACMD_R3(41u) // R3, [31] reserved bit [30] HCS (OCR[30]) [29] reserved for eSD [28] XPC [27:25] reserved bits [24] S18R [23:0] VDD Voltage Window (OCR[23:0]).
#define SD_APP_SET_CLR_CARD_DETECT SD_ACMD_R1(42u) // R1, [31:1] stuff bits [0] set_cd.
#define SD_APP_SEND_SCR SD_ACMD_R1_R(51u) // R1, [31:0] stuff bits.

// Switch Function Commands (class 10).
#define SD_SWITCH_FUNC SD_CMD_R1_R(6u) // R1, [31] Mode 0: Check function 1: Switch function [30:24] reserved (All '0') [23:20] reserved for function group 6 (0h or Fh) [19:16] reserved for function group 5 (0h or Fh) [15:12] function group 4 for PowerLimit [11:8] function group 3 for Drive Strength [7:4] function group 2 for Command System [3:0] function group 1 for Access Mode.

// 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_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.).
#define SD_Q_TASK_INFO_A SD_CMD_R1(44u) // R1, [31] Reserved [30] Direction [29:24] Extended Address [23] Priority [22:21] Reserved [20:16] Task ID [15:0] Number of Blocks.
#define SD_Q_TASK_INFO_B SD_CMD_R1(45u) // R1, [31:0] Start block address.
#define SD_Q_RD_TASK SD_CMD_R1_R(46u) // R1, [31:21] Reserved [20:16] Task ID [15:0] Reserved.
#define SD_Q_WR_TASK SD_CMD_R1_W(47u) // R1, [31:21] Reserved [20:16] Task ID [15:0] Reserved.


// 4.10.1 Card Status.
// Type:
// E: Error bit.
// S: Status bit.
// R: Detected and set for the actual command response.
// X: Detected and set during command execution. The host can get the status by issuing a command with R1 response.
//
// Clear Condition:
// A: According to the card current status.
// B: Always related to the previous command. Reception of a valid command will clear it (with a delay of one command).
// C: Clear by read.
#define SD_R1_AKE_SEQ_ERROR (1u<<3) // E R C, Error in the sequence of the authentication process.
#define SD_R1_APP_CMD (1u<<5) // S R C, The card will expect ACMD, or an indication that the command has been interpreted as ACMD.
#define SD_R1_FX_EVENT (1u<<6) // S X A, ExtensionFunctions may set this bit to get host to deal with events.
#define SD_R1_READY_FOR_DATA (1u<<8) // S X A, Corresponds to buffer empty signaling on the bus.
#define SD_R1_STATE_IDLE (0u<<9) // S X B
#define SD_R1_STATE_READY (1u<<9) // S X B
#define SD_R1_STATE_IDENT (2u<<9) // S X B
#define SD_R1_STATE_STBY (3u<<9) // S X B
#define SD_R1_STATE_TRAN (4u<<9) // S X B
#define SD_R1_STATE_DATA (5u<<9) // S X B
#define SD_R1_STATE_RCV (6u<<9) // S X B
#define SD_R1_STATE_PRG (7u<<9) // S X B
#define SD_R1_STATE_DIS (8u<<9) // S X B
#define SD_R1_ERASE_RESET (1u<<13) // S R C, An erase sequence was cleared before executing because an out of erase sequence command was received.
#define SD_R1_CARD_ECC_DISABLED (1u<<14) // S X A, The command has been executed without using the internal ECC.
#define SD_R1_WP_ERASE_SKIP (1u<<15) // E R X C, Set when only partial address space was erased due to existing write protected blocks or the temporary or permanent write protected cardwas erased.
#define SD_R1_CSD_OVERWRITE (1u<<16) // E R X C, Can be either one of the following errors: -The read only section of the CSD does not match the card content. -An attempt to reverse the copy (set as original) or permanent WP (unprotected) bits was made.
// 17 reserved for DEFERRED_RESPONSE (Refer to eSD Addendum)
#define SD_R1_ERROR (1u<<19) // E R X C, A general or an unknown error occurred during the operation.
#define SD_R1_CC_ERROR (1u<<20) // E R X C, Internal card controller error:
#define SD_R1_CARD_ECC_FAILED (1u<<21) // E R X C, Card internal ECC was applied but failed to correct the data.
#define SD_R1_ILLEGAL_COMMAND (1u<<22) // E R B, Command not legal for the card state.
#define SD_R1_COM_CRC_ERROR (1u<<23) // E R B, The CRC check of the previous command failed.
#define SD_R1_LOCK_UNLOCK_FAILED (1u<<24) // E R X C, Set when a sequence or password error has been detected in lock/unlock card command.
#define SD_R1_CARD_IS_LOCKED (1u<<25) // S X A, When set, signals that the card is locked by the host.
#define SD_R1_WP_VIOLATION (1u<<26) // E R X C, Set when the host attempts to write to a protected block or to thetemporary or permanent write protected card.
#define SD_R1_ERASE_PARAM (1u<<27) // E R X C, An invalid selection of write-blocks for erase occurred.
#define SD_R1_ERASE_SEQ_ERROR (1u<<28) // E R C, An error in the sequence of erase commands occurred.
#define SD_R1_BLOCK_LEN_ERROR (1u<<29) // E R X C, The transferred block length is not allowed for this card, or the number of transferred bytes does not match the block length.
#define SD_R1_ADDRESS_ERROR (1u<<30) // E R X C, A misaligned address which did not match the block length was used in the command.
#define SD_R1_OUT_OF_RANGE (1u<<31) // E R X C, The command's argument was out of the allowed range for this card.

#define SD_R1_ERR_ALL (SD_R1_OUT_OF_RANGE | SD_R1_ADDRESS_ERROR | SD_R1_BLOCK_LEN_ERROR | \
SD_R1_ERASE_SEQ_ERROR | SD_R1_ERASE_PARAM | SD_R1_WP_VIOLATION | \
SD_R1_LOCK_UNLOCK_FAILED | SD_R1_COM_CRC_ERROR | SD_R1_ILLEGAL_COMMAND | \
SD_R1_CARD_ECC_FAILED | SD_R1_CC_ERROR | SD_R1_ERROR | \
SD_R1_CSD_OVERWRITE | SD_R1_WP_ERASE_SKIP | SD_R1_AKE_SEQ_ERROR)

// Argument bits for SEND_IF_COND (CMD8).
#define SD_CMD8_CHK_PATT (0xAAu) // Check pattern.
#define SD_CMD8_VHS_2_7_3_6V (1u<<8) // Voltage supplied (VHS) 2.7-3.6V.
#define SD_CMD8_PCIe (1u<<12) // PCIe Avail-ability.
#define SD_CMD8_PCIe_1_2V (1u<<13) // PCIe 1.2V Support.

// 5.1 OCR register.
#define SD_OCR_2_7_2_8V (1u<<15) // 2.7-2.8V.
#define SD_OCR_2_8_2_9V (1u<<16) // 2.8-2.9V.
#define SD_OCR_2_9_3_0V (1u<<17) // 2.9-3.0V.
#define SD_OCR_3_0_3_1V (1u<<18) // 3.0-3.1V.
#define SD_OCR_3_1_3_2V (1u<<19) // 3.1-3.2V.
#define SD_OCR_3_2_3_3V (1u<<20) // 3.2-3.3V.
#define SD_OCR_3_3_3_4V (1u<<21) // 3.3-3.4V.
#define SD_OCR_3_4_3_5V (1u<<22) // 3.4-3.5V.
#define SD_OCR_3_5_3_6V (1u<<23) // 3.5-3.6V.
#define SD_OCR_S18A (1u<<24) // S18A: Switching to 1.8V Accepted. 0b: Continues current voltage signaling, 1b: Ready for switching signal voltage.
#define SD_OCR_CO2T (1u<<27) // Over 2TB Card. CCS must also be 1 if this is 1.
#define SD_OCR_UHS_II (1u<<29) // UHS-II Card Status. 0b: Non UHS-II Card, 1b: UHS-II Card.
#define SD_OCR_CCS (1u<<30) // Card Capacity Status. 0b: SDSC, 1b: SDHC or SDXC.
#define SD_OCR_READY (1u<<31) // Busy Status. 0b: On Initialization, 1b: Initialization Complete.

// Argument bits for SEND_OP_COND (ACMD41).
// For voltage bits see OCR register above.
#define SD_ACMD41_S18R (1u<<24) // S18R: Switching to 1.8V Request. 0b: Use current signal voltage, 1b: Switch to 1.8V signal voltage.
#define SD_ACMD41_HO2T (1u<<27) // Over 2TB Supported Host. HCS must also be 1 if this is 1.
#define SD_ACMD41_XPC (1u<<28) // SDXC Power Control. 0b: Power Saving, 1b: Maximum Performance.
#define SD_ACMD41_HCS (1u<<30) // Host Capacity Support. 0b: SDSC Only Host, 1b: SDHC or SDXC Supported.

// 4.3.10 Switch Function Command.
// mode: 0 = check function, 1 = set function
// pwr: Function group 4 Power Limit.
// driver: Function group 3 Driver Strength.
// cmd: Function group 2 Command system.
// acc: Function group 1 Access mode.
#define SD_SWITCH_FUNC_ARG(mode, pwr, driver, cmd, acc) ((mode)<<31 | 0xFFu<<16 | ((pwr)&0xFu)<<12 | ((driver)&0xFu)<<8 | ((cmd)&0xFu)<<4 | ((acc)&0xFu))
Loading