mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
Fusee: Deployed new SDMMC driver in fusee-secondary. All stages boot now.
Fusee: Fixed wrong argument in se.c function. Fusee: Improved timers.
This commit is contained in:
parent
49ba91a8f3
commit
3db9ce32fa
44 changed files with 5247 additions and 4802 deletions
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "lib/printk.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a GPIO bank object that corresponds to the given GPIO pin,
|
* Returns a GPIO bank object that corresponds to the given GPIO pin,
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "hwinit.h"
|
#include "hwinit.h"
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
#include "timers.h"
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "stage2.h"
|
#include "stage2.h"
|
||||||
#include "chainloader.h"
|
#include "chainloader.h"
|
||||||
|
@ -123,13 +124,6 @@ int main(void) {
|
||||||
printk("Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
|
printk("Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
|
||||||
printk("Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
printk("Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
||||||
|
|
||||||
#ifndef I_KNOW_WHAT_I_AM_DOING
|
|
||||||
#error "Fusee is a work-in-progress bootloader, and is not ready for usage yet. If you want to play with it anyway, please #define I_KNOW_WHAT_I_AM_DOING -- and recognize that we will be unable to provide support until it is ready for general usage :)"
|
|
||||||
|
|
||||||
printk("Warning: Fus\xe9" "e is not yet completed, and not ready for general testing!\n");
|
|
||||||
fatal_error("Please do not seek support for it until it is done.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Load the BCT0 configuration ini off of the SD. */
|
/* Load the BCT0 configuration ini off of the SD. */
|
||||||
bct0 = load_config();
|
bct0 = load_config();
|
||||||
|
|
||||||
|
@ -142,10 +136,12 @@ int main(void) {
|
||||||
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
|
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
|
||||||
memcpy(&stage2_args->version, &stage2_version, 4);
|
memcpy(&stage2_args->version, &stage2_version, 4);
|
||||||
stage2_args->display_initialized = false;
|
stage2_args->display_initialized = false;
|
||||||
memcpy(&stage2_args->sd_sdmmc, &g_sd_sdmmc, sizeof(g_sd_sdmmc));
|
|
||||||
strcpy(stage2_args->bct0, bct0);
|
strcpy(stage2_args->bct0, bct0);
|
||||||
g_chainloader_argc = 2;
|
g_chainloader_argc = 2;
|
||||||
|
|
||||||
|
/* Wait a while. */
|
||||||
|
mdelay(1000);
|
||||||
|
|
||||||
/* Deinitialize the display, console, etc. */
|
/* Deinitialize the display, console, etc. */
|
||||||
cleanup_env();
|
cleanup_env();
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ static int sdmmc_device_rw(sdmmc_device_t *device, uint32_t sector, uint32_t num
|
||||||
sdmmc_device_send_status(device);
|
sdmmc_device_send_status(device);
|
||||||
|
|
||||||
/* Wait for a while. */
|
/* Wait for a while. */
|
||||||
udelay(100000);
|
mdelay(100);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -504,8 +504,8 @@ static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool i
|
||||||
/* Keep checking if timeout expired. */
|
/* Keep checking if timeout expired. */
|
||||||
is_timeout = (get_time_since(timebase) > 2000000);
|
is_timeout = (get_time_since(timebase) > 2000000);
|
||||||
|
|
||||||
/* Delay for an appropriate period. */
|
/* Delay for a minimum of 10 milliseconds. */
|
||||||
udelay(10000);
|
mdelay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1161,8 +1161,8 @@ static int sdmmc_mmc_send_op_cond(sdmmc_device_t *device, SdmmcBusVoltage bus_vo
|
||||||
/* Keep checking if timeout expired. */
|
/* Keep checking if timeout expired. */
|
||||||
is_timeout = (get_time_since(timebase) > 2000000);
|
is_timeout = (get_time_since(timebase) > 2000000);
|
||||||
|
|
||||||
/* Delay for an appropriate period. */
|
/* Delay for a minimum of 10 milliseconds. */
|
||||||
udelay(10000);
|
mdelay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1357,11 +1357,23 @@ static int sdmmc_mmc_select_bkops(sdmmc_device_t *device)
|
||||||
return sdmmc_device_send_status(device);
|
return sdmmc_device_send_status(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition)
|
||||||
|
{
|
||||||
|
uint32_t arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_PART_CONFIG) << 16) | ((partition) << 8));
|
||||||
|
|
||||||
|
/* Try to change the active partition. */
|
||||||
|
if (!sdmmc_mmc_switch(device, arg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Peek the current status. */
|
||||||
|
return sdmmc_device_send_status(device);
|
||||||
|
}
|
||||||
|
|
||||||
int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed)
|
int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
uint32_t cid[4] = {0};
|
uint32_t cid[4] = {0};
|
||||||
uint32_t csd[4] = {0};
|
uint32_t csd[4] = {0};
|
||||||
uint8_t ext_csd[512] = {0};
|
uint8_t *ext_csd = (uint8_t *)SDMMC_BOUNCE_BUFFER_ADDRESS; // TODO: Better way to do this.
|
||||||
|
|
||||||
/* Initialize our device's struct. */
|
/* Initialize our device's struct. */
|
||||||
memset(device, 0, sizeof(sdmmc_device_t));
|
memset(device, 0, sizeof(sdmmc_device_t));
|
||||||
|
@ -1376,6 +1388,9 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
/* Bind the underlying driver. */
|
/* Bind the underlying driver. */
|
||||||
device->sdmmc = sdmmc;
|
device->sdmmc = sdmmc;
|
||||||
|
|
||||||
|
/* Set RCA. */
|
||||||
|
device->rca = 0x01;
|
||||||
|
|
||||||
sdmmc_info(sdmmc, "SDMMC driver was successfully initialized for eMMC!");
|
sdmmc_info(sdmmc, "SDMMC driver was successfully initialized for eMMC!");
|
||||||
|
|
||||||
/* Apply at least 74 clock cycles. eMMC should be ready afterwards. */
|
/* Apply at least 74 clock cycles. eMMC should be ready afterwards. */
|
||||||
|
@ -1408,14 +1423,14 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
|
|
||||||
sdmmc_info(sdmmc, "Got CID from eMMC!");
|
sdmmc_info(sdmmc, "Got CID from eMMC!");
|
||||||
|
|
||||||
/* Get the eMMC's RCA. */
|
/* Set the eMMC's RCA. */
|
||||||
if (!sdmmc_mmc_set_relative_addr(device))
|
if (!sdmmc_mmc_set_relative_addr(device))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to get RCA!");
|
sdmmc_error(sdmmc, "Failed to set RCA!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdmmc_info(sdmmc, "Got RCA (0x%08x) from eMMC!", device->rca);
|
sdmmc_info(sdmmc, "RCA is now set in eMMC!");
|
||||||
|
|
||||||
/* Get the eMMC card's CSD. */
|
/* Get the eMMC card's CSD. */
|
||||||
if (!sdmmc_device_send_csd(device, csd))
|
if (!sdmmc_device_send_csd(device, csd))
|
||||||
|
|
|
@ -156,5 +156,6 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data);
|
int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data);
|
||||||
int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data);
|
int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data);
|
||||||
int sdmmc_device_finish(sdmmc_device_t *device);
|
int sdmmc_device_finish(sdmmc_device_t *device);
|
||||||
|
int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -14,8 +14,6 @@
|
||||||
#include "../lib/driver_utils.h"
|
#include "../lib/driver_utils.h"
|
||||||
#include "../hwinit/max7762x.h"
|
#include "../hwinit/max7762x.h"
|
||||||
|
|
||||||
#define SDMMC_BOUNCE_BUFFER_ADDRESS 0x90000000
|
|
||||||
|
|
||||||
static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE;
|
static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE;
|
||||||
|
|
||||||
void sdmmc_set_log_level(SdmmcLogLevel log_level)
|
void sdmmc_set_log_level(SdmmcLogLevel log_level)
|
||||||
|
@ -116,7 +114,7 @@ void sdmmc_dump_regs(sdmmc_t *sdmmc)
|
||||||
sdmmc_debug(sdmmc, "max_current: 0x%08" PRIX32, sdmmc->regs->max_current);
|
sdmmc_debug(sdmmc, "max_current: 0x%08" PRIX32, sdmmc->regs->max_current);
|
||||||
sdmmc_debug(sdmmc, "set_acmd12_error: 0x%04" PRIX16, sdmmc->regs->set_acmd12_error);
|
sdmmc_debug(sdmmc, "set_acmd12_error: 0x%04" PRIX16, sdmmc->regs->set_acmd12_error);
|
||||||
sdmmc_debug(sdmmc, "set_int_error: 0x%04" PRIX16, sdmmc->regs->set_int_error);
|
sdmmc_debug(sdmmc, "set_int_error: 0x%04" PRIX16, sdmmc->regs->set_int_error);
|
||||||
sdmmc_debug(sdmmc, "adma_error: 0x%02" PRIX16, sdmmc->regs->adma_error);
|
sdmmc_debug(sdmmc, "adma_error: 0x%02" PRIX8, sdmmc->regs->adma_error);
|
||||||
sdmmc_debug(sdmmc, "adma_address: 0x%08" PRIX32, sdmmc->regs->adma_address);
|
sdmmc_debug(sdmmc, "adma_address: 0x%08" PRIX32, sdmmc->regs->adma_address);
|
||||||
sdmmc_debug(sdmmc, "upper_adma_address: 0x%08" PRIX32, sdmmc->regs->upper_adma_address);
|
sdmmc_debug(sdmmc, "upper_adma_address: 0x%08" PRIX32, sdmmc->regs->upper_adma_address);
|
||||||
sdmmc_debug(sdmmc, "preset_for_init: 0x%04" PRIX16, sdmmc->regs->preset_for_init);
|
sdmmc_debug(sdmmc, "preset_for_init: 0x%04" PRIX16, sdmmc->regs->preset_for_init);
|
||||||
|
@ -700,10 +698,13 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc)
|
||||||
|
|
||||||
/* Change to ADMA if requested. */
|
/* Change to ADMA if requested. */
|
||||||
if (sdmmc->use_adma && (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)) {
|
if (sdmmc->use_adma && (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)) {
|
||||||
|
// TODO: Setting the ADMA flags breaks ADMA...
|
||||||
|
/*
|
||||||
if (sdmmc->regs->capabilities & SDHCI_CAN_64BIT)
|
if (sdmmc->regs->capabilities & SDHCI_CAN_64BIT)
|
||||||
sdmmc->regs->host_control |= SDHCI_CTRL_ADMA64;
|
sdmmc->regs->host_control |= SDHCI_CTRL_ADMA64;
|
||||||
else
|
else
|
||||||
sdmmc->regs->host_control |= SDHCI_CTRL_ADMA32;
|
sdmmc->regs->host_control |= SDHCI_CTRL_ADMA32;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the timeout to be the maximum value. */
|
/* Set the timeout to be the maximum value. */
|
||||||
|
@ -1092,7 +1093,7 @@ static int sdmmc_init_controller(sdmmc_t *sdmmc, SdmmcControllerNum controller)
|
||||||
sdmmc->is_clk_running = false;
|
sdmmc->is_clk_running = false;
|
||||||
sdmmc->is_sd_clk_enabled = false;
|
sdmmc->is_sd_clk_enabled = false;
|
||||||
sdmmc->is_tuning_tap_val_set = false;
|
sdmmc->is_tuning_tap_val_set = false;
|
||||||
sdmmc->use_adma = false;
|
sdmmc->use_adma = true;
|
||||||
sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS;
|
sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS;
|
||||||
sdmmc->tap_val = 0;
|
sdmmc->tap_val = 0;
|
||||||
sdmmc->internal_divider = 0;
|
sdmmc->internal_divider = 0;
|
||||||
|
@ -1201,13 +1202,23 @@ void sdmmc_finish(sdmmc_t *sdmmc)
|
||||||
/* Disable the SD clock. */
|
/* Disable the SD clock. */
|
||||||
sdmmc_disable_sd_clock(sdmmc);
|
sdmmc_disable_sd_clock(sdmmc);
|
||||||
|
|
||||||
/* Disable SD power. */
|
/* Disable SDMMC power. */
|
||||||
sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE);
|
sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE);
|
||||||
|
|
||||||
|
/* Disable the SD card power. */
|
||||||
|
if (sdmmc->controller == SDMMC_1)
|
||||||
|
{
|
||||||
|
/* Disable GPIO output. */
|
||||||
|
gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_INPUT);
|
||||||
|
|
||||||
|
/* Power cycle for 100ms without power. */
|
||||||
|
mdelay(100);
|
||||||
|
}
|
||||||
|
|
||||||
/* Force a register read to refresh the clock control value. */
|
/* Force a register read to refresh the clock control value. */
|
||||||
sdmmc_get_sd_clock_control(sdmmc);
|
sdmmc_get_sd_clock_control(sdmmc);
|
||||||
|
|
||||||
/* Stop the SD clock. */
|
/* Stop the SDMMC clock. */
|
||||||
sdmmc_clk_stop(sdmmc->controller);
|
sdmmc_clk_stop(sdmmc->controller);
|
||||||
|
|
||||||
/* Clock is no longer running by now. */
|
/* Clock is no longer running by now. */
|
||||||
|
@ -1307,7 +1318,8 @@ static int sdmmc_wait_busy(sdmmc_t *sdmmc)
|
||||||
static void sdmmc_intr_enable(sdmmc_t *sdmmc)
|
static void sdmmc_intr_enable(sdmmc_t *sdmmc)
|
||||||
{
|
{
|
||||||
/* Set all error bits and enable the relevant interrupts. */
|
/* Set all error bits and enable the relevant interrupts. */
|
||||||
sdmmc->regs->int_enable |= (0x017F0000 | (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT));
|
sdmmc->regs->int_enable |= 0x017F0000;
|
||||||
|
sdmmc->regs->int_enable |= (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT);
|
||||||
|
|
||||||
/* Refresh status. */
|
/* Refresh status. */
|
||||||
sdmmc->regs->int_status = sdmmc->regs->int_status;
|
sdmmc->regs->int_status = sdmmc->regs->int_status;
|
||||||
|
@ -1315,11 +1327,15 @@ static void sdmmc_intr_enable(sdmmc_t *sdmmc)
|
||||||
|
|
||||||
static void sdmmc_intr_disable(sdmmc_t *sdmmc)
|
static void sdmmc_intr_disable(sdmmc_t *sdmmc)
|
||||||
{
|
{
|
||||||
/* Clear the interrupt bits. */
|
/* Clear all error bits and the interrupts. */
|
||||||
sdmmc->regs->int_enable &= ~(0x017F0000 | (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT));
|
sdmmc->regs->int_enable &= ~(0x017F0000);
|
||||||
|
sdmmc->regs->int_enable &= ~(TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT);
|
||||||
|
|
||||||
|
/* Refresh status. */
|
||||||
|
sdmmc->regs->int_status = sdmmc->regs->int_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sdmmc_intr_check_status(sdmmc_t *sdmmc, u16 status_mask)
|
static bool sdmmc_intr_check_status(sdmmc_t *sdmmc, uint16_t status_mask)
|
||||||
{
|
{
|
||||||
bool is_masked = (sdmmc->regs->int_status & status_mask);
|
bool is_masked = (sdmmc->regs->int_status & status_mask);
|
||||||
|
|
||||||
|
@ -1353,8 +1369,8 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req)
|
||||||
if (blkcnt >= 0xFFFF)
|
if (blkcnt >= 0xFFFF)
|
||||||
blkcnt = 0xFFFF;
|
blkcnt = 0xFFFF;
|
||||||
|
|
||||||
/* Point to our bounce buffer. */
|
/* Use our bounce buffer for SDMA or the request data buffer for ADMA. */
|
||||||
uint32_t dma_base_addr = (uint32_t)sdmmc->dma_bounce_buf;
|
uint32_t dma_base_addr = sdmmc->use_adma ? (uint32_t)req->data : (uint32_t)sdmmc->dma_bounce_buf;
|
||||||
|
|
||||||
/* DMA buffer address must be aligned to 4 bytes. */
|
/* DMA buffer address must be aligned to 4 bytes. */
|
||||||
if ((4 - (dma_base_addr & 0x03)) & 0x03)
|
if ((4 - (dma_base_addr & 0x03)) & 0x03)
|
||||||
|
@ -1408,7 +1424,7 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req)
|
||||||
|
|
||||||
static int sdmmc_dma_update(sdmmc_t *sdmmc)
|
static int sdmmc_dma_update(sdmmc_t *sdmmc)
|
||||||
{
|
{
|
||||||
u16 blkcnt = 0;
|
uint16_t blkcnt = 0;
|
||||||
|
|
||||||
/* Loop until all blocks have been consumed. */
|
/* Loop until all blocks have been consumed. */
|
||||||
do
|
do
|
||||||
|
@ -1464,7 +1480,7 @@ static int sdmmc_dma_update(sdmmc_t *sdmmc)
|
||||||
|
|
||||||
static void sdmmc_set_cmd_flags(sdmmc_t *sdmmc, sdmmc_command_t *cmd, bool is_dma)
|
static void sdmmc_set_cmd_flags(sdmmc_t *sdmmc, sdmmc_command_t *cmd, bool is_dma)
|
||||||
{
|
{
|
||||||
u16 cmd_reg_flags = 0;
|
uint16_t cmd_reg_flags = 0;
|
||||||
|
|
||||||
/* Select length flags based on response type. */
|
/* Select length flags based on response type. */
|
||||||
if (!(cmd->flags & SDMMC_RSP_PRESENT))
|
if (!(cmd->flags & SDMMC_RSP_PRESENT))
|
||||||
|
@ -1629,8 +1645,8 @@ int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, u
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a write operation, copy the data into our bounce buffer. */
|
/* If this is a SDMA write operation, copy the data into our bounce buffer. */
|
||||||
if (!req->is_read)
|
if (!sdmmc->use_adma && !req->is_read)
|
||||||
memcpy((void *)sdmmc->dma_bounce_buf, (void *)req->data, req->blksz * req->num_blocks);
|
memcpy((void *)sdmmc->dma_bounce_buf, (void *)req->data, req->blksz * req->num_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1659,8 +1675,8 @@ int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, u
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a read operation, copy the data from our bounce buffer. */
|
/* If this is a SDMA read operation, copy the data from our bounce buffer. */
|
||||||
if (req->is_read)
|
if (!sdmmc->use_adma && req->is_read)
|
||||||
{
|
{
|
||||||
uint32_t dma_data_size = (sdmmc->regs->dma_address - (uint32_t)sdmmc->dma_bounce_buf);
|
uint32_t dma_data_size = (sdmmc->regs->dma_address - (uint32_t)sdmmc->dma_bounce_buf);
|
||||||
memcpy((void *)req->data, (void *)sdmmc->dma_bounce_buf, dma_data_size);
|
memcpy((void *)req->data, (void *)sdmmc->dma_bounce_buf, dma_data_size);
|
||||||
|
@ -1853,7 +1869,7 @@ static int sdmmc_send_tuning(sdmmc_t *sdmmc, uint32_t opcode)
|
||||||
|
|
||||||
void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc)
|
void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc)
|
||||||
{
|
{
|
||||||
sdmmc->tap_val = ((sdmmc->regs->vendor_clock_cntrl & 0xFF0000) >> 16);
|
sdmmc->tap_val = (sdmmc->regs->vendor_clock_cntrl >> 16);
|
||||||
sdmmc->is_tuning_tap_val_set = true;
|
sdmmc->is_tuning_tap_val_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include "sdmmc_tegra.h"
|
#include "sdmmc_tegra.h"
|
||||||
|
|
||||||
|
/* Bounce buffer */
|
||||||
|
#define SDMMC_BOUNCE_BUFFER_ADDRESS 0x90000000
|
||||||
|
|
||||||
/* Present state */
|
/* Present state */
|
||||||
#define SDHCI_CMD_INHIBIT 0x00000001
|
#define SDHCI_CMD_INHIBIT 0x00000001
|
||||||
#define SDHCI_DATA_INHIBIT 0x00000002
|
#define SDHCI_DATA_INHIBIT 0x00000002
|
||||||
|
@ -177,6 +180,14 @@ typedef enum {
|
||||||
SDMMC_4 = 3
|
SDMMC_4 = 3
|
||||||
} SdmmcControllerNum;
|
} SdmmcControllerNum;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SDMMC_PARTITION_INVALID = -1,
|
||||||
|
SDMMC_PARTITION_USER = 0,
|
||||||
|
SDMMC_PARTITION_BOOT0 = 1,
|
||||||
|
SDMMC_PARTITION_BOOT1 = 2,
|
||||||
|
SDMMC_PARTITION_RPMB = 3
|
||||||
|
} SdmmcPartitionNum;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDMMC_VOLTAGE_NONE = 0,
|
SDMMC_VOLTAGE_NONE = 0,
|
||||||
SDMMC_VOLTAGE_1V8 = 1,
|
SDMMC_VOLTAGE_1V8 = 1,
|
||||||
|
|
|
@ -21,7 +21,6 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
sdmmc_t sd_sdmmc;
|
|
||||||
bool display_initialized;
|
bool display_initialized;
|
||||||
char bct0[BCTO_MAX_SIZE];
|
char bct0[BCTO_MAX_SIZE];
|
||||||
} stage2_args_t;
|
} stage2_args_t;
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
|
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
|
||||||
#define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10)
|
#define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10)
|
||||||
|
|
||||||
|
#define RTC_BASE 0x7000E000
|
||||||
|
#define RTC_SECONDS MAKE_REG32(RTC_BASE + 0x08)
|
||||||
|
#define RTC_SHADOW_SECONDS MAKE_REG32(RTC_BASE + 0x0C)
|
||||||
|
#define RTC_MILLI_SECONDS MAKE_REG32(RTC_BASE + 0x10)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t CONFIG;
|
uint32_t CONFIG;
|
||||||
uint32_t STATUS;
|
uint32_t STATUS;
|
||||||
|
@ -20,23 +25,46 @@ typedef struct {
|
||||||
|
|
||||||
void wait(uint32_t microseconds);
|
void wait(uint32_t microseconds);
|
||||||
|
|
||||||
static inline uint32_t get_time(void) {
|
static inline uint32_t get_time_s(void) {
|
||||||
|
return RTC_SECONDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_time_ms(void) {
|
||||||
|
return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_time_us(void) {
|
||||||
return TIMERUS_CNTR_1US_0;
|
return TIMERUS_CNTR_1US_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time in microseconds.
|
||||||
|
*/
|
||||||
|
static inline uint32_t get_time(void) {
|
||||||
|
return get_time_us();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of microseconds that have passed since a given get_time().
|
* Returns the number of microseconds that have passed since a given get_time().
|
||||||
*/
|
*/
|
||||||
static inline uint32_t get_time_since(uint32_t base) {
|
static inline uint32_t get_time_since(uint32_t base) {
|
||||||
return get_time() - base;
|
return get_time_us() - base;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delays for a given number of microseconds.
|
* Delays for a given number of microseconds.
|
||||||
*/
|
*/
|
||||||
static inline void udelay(unsigned usecs) {
|
static inline void udelay(uint32_t usecs) {
|
||||||
uint32_t start = get_time();
|
uint32_t start = get_time_us();
|
||||||
while (get_time() - start < usecs);
|
while (get_time_us() - start < usecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delays for a given number of milliseconds.
|
||||||
|
*/
|
||||||
|
static inline void mdelay(uint32_t msecs) {
|
||||||
|
uint32_t start = get_time_ms();
|
||||||
|
while (get_time_ms() - start < msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
||||||
|
|
|
@ -21,7 +21,7 @@ include $(DEVKITARM)/base_rules
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
TARGET := $(notdir $(CURDIR))
|
TARGET := $(notdir $(CURDIR))
|
||||||
BUILD := build
|
BUILD := build
|
||||||
SOURCES := src src/lib src/lib/fatfs src/display src/hwinit
|
SOURCES := src src/sdmmc src/hwinit src/lib src/lib/fatfs src/display
|
||||||
DATA := data
|
DATA := data
|
||||||
INCLUDES := include
|
INCLUDES := include
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
#ifndef __APB_MISC_H__
|
#ifndef FUSEE_APB_MISC_H
|
||||||
#define __APB_MISC_H__
|
#define FUSEE_APB_MISC_H
|
||||||
|
|
||||||
/* FIXME: clean up */
|
|
||||||
|
|
||||||
#define MISC_BASE (0x70000000UL)
|
|
||||||
#define PINMUX_BASE (MISC_BASE + 0x3000)
|
|
||||||
#define PINMUX_AUX_GPIO_PZ1_0 (*(volatile uint32_t *)(PINMUX_BASE + 0x280))
|
|
||||||
|
|
||||||
#define APB_MISC_GP_VGPIO_GPIO_MUX_SEL_0 MAKE_REG32(MISC_BASE + 0xb74)
|
|
||||||
#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL_0 MAKE_REG32(MISC_BASE + 0xa98)
|
|
||||||
#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL_0 MAKE_REG32(MISC_BASE + 0xab4)
|
|
||||||
|
|
||||||
#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20)
|
#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20)
|
||||||
#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12)
|
#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12)
|
||||||
|
@ -21,4 +11,44 @@
|
||||||
#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT)
|
#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT)
|
||||||
#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT)
|
#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT)
|
||||||
|
|
||||||
|
#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0)
|
||||||
|
#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0)
|
||||||
|
#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8)
|
||||||
|
#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4)
|
||||||
|
#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0)
|
||||||
|
#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8)
|
||||||
|
#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4)
|
||||||
|
#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0)
|
||||||
|
#define PADCTL_SDMMC1_CD_SOURCE (1 << 0)
|
||||||
|
#define PADCTL_SDMMC1_WP_SOURCE (1 << 1)
|
||||||
|
#define PADCTL_SDMMC3_CD_SOURCE (1 << 2)
|
||||||
|
#define PADCTL_SDMMC3_WP_SOURCE (1 << 3)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t asdbgreg; /* 0x810 */
|
||||||
|
uint32_t reserved0[0x31];
|
||||||
|
uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */
|
||||||
|
uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */
|
||||||
|
uint32_t emmc2_pad_cfg_control; /* 0x8DC */
|
||||||
|
uint32_t emmc4_pad_cfg_control; /* 0x8E0 */
|
||||||
|
uint32_t _todo0[0x6E];
|
||||||
|
uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */
|
||||||
|
uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */
|
||||||
|
uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */
|
||||||
|
uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */
|
||||||
|
uint32_t _todo1[0x03];
|
||||||
|
uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */
|
||||||
|
uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */
|
||||||
|
uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */
|
||||||
|
uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */
|
||||||
|
uint32_t _todo2[0x2E];
|
||||||
|
uint32_t vgpio_gpio_mux_sel; /* 0xB74 */
|
||||||
|
uint32_t qspi_sck_lpbk_control; /* 0xB78 */
|
||||||
|
} tegra_padctl_t;
|
||||||
|
|
||||||
|
static inline volatile tegra_padctl_t *padctl_get_regs(void)
|
||||||
|
{
|
||||||
|
return (volatile tegra_padctl_t *)0x70000810;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,93 +1,66 @@
|
||||||
|
#ifndef FUSEE_CAR_H
|
||||||
|
#define FUSEE_CAR_H
|
||||||
|
|
||||||
#ifndef __FUSEE_CLOCK_H__
|
#define CLK_SOURCE_SDMMC1 20
|
||||||
#define __FUSEE_CLOCK_H__
|
#define CLK_SOURCE_SDMMC2 21
|
||||||
|
#define CLK_SOURCE_SDMMC3 47
|
||||||
|
#define CLK_SOURCE_SDMMC4 25
|
||||||
|
#define CLK_SOURCE_SDMMC_LEGACY 0
|
||||||
|
|
||||||
#include "utils.h"
|
#define CLK_L_SDMMC1 (1 << 14)
|
||||||
|
#define CLK_L_SDMMC2 (1 << 9)
|
||||||
|
#define CLK_U_SDMMC3 (1 << 5)
|
||||||
|
#define CLK_L_SDMMC4 (1 << 15)
|
||||||
|
|
||||||
/**
|
#define TEGRA_CLK_PLLS 6 /* Number of normal PLLs */
|
||||||
* Struct definition yanked from u-boot.
|
#define TEGRA_CLK_SIMPLE_PLLS 3 /* Number of simple PLLs */
|
||||||
*/
|
#define TEGRA_CLK_SOURCES 64 /* Number of ppl clock sources L/H/U */
|
||||||
|
#define TEGRA_CLK_SOURCES_VW 32 /* Number of ppl clock sources V/W */
|
||||||
|
#define TEGRA_CLK_SOURCES_X 32 /* Number of ppl clock sources X */
|
||||||
|
#define TEGRA_CLK_SOURCES_Y 18 /* Number of ppl clock sources Y */
|
||||||
|
|
||||||
|
#define CLK_SOURCE_MASK (0b111 << 29)
|
||||||
|
#define CLK_SOURCE_FIRST (0b000 << 29)
|
||||||
|
#define CLK_DIVIDER_MASK (0xff << 0)
|
||||||
|
#define CLK_DIVIDER_UNITY (0x00 << 0)
|
||||||
|
|
||||||
|
#define CAR_CONTROL_SDMMC1 (1 << 14)
|
||||||
|
#define CAR_CONTROL_SDMMC4 (1 << 15)
|
||||||
|
#define CAR_CONTROL_SDMMC_LEGACY (1 << 1)
|
||||||
|
|
||||||
/* PLL registers - there are several PLLs in the clock controller */
|
/* PLL registers - there are several PLLs in the clock controller */
|
||||||
struct clk_pll {
|
typedef struct {
|
||||||
uint32_t pll_base; /* the control register */
|
uint32_t pll_base; /* the control register */
|
||||||
|
|
||||||
/* pll_out[0] is output A control, pll_out[1] is output B control */
|
/* pll_out[0] is output A control, pll_out[1] is output B control */
|
||||||
uint32_t pll_out[2];
|
uint32_t pll_out[2];
|
||||||
uint32_t pll_misc; /* other misc things */
|
uint32_t pll_misc; /* other misc things */
|
||||||
};
|
} clk_pll_t;
|
||||||
|
|
||||||
/* PLL registers - there are several PLLs in the clock controller */
|
/* PLL registers - there are several PLLs in the clock controller */
|
||||||
struct clk_pll_simple {
|
typedef struct {
|
||||||
uint32_t pll_base; /* the control register */
|
uint32_t pll_base; /* the control register */
|
||||||
uint32_t pll_misc; /* other misc things */
|
uint32_t pll_misc; /* other misc things */
|
||||||
};
|
} clk_pll_simple_t;
|
||||||
|
|
||||||
struct clk_pllm {
|
typedef struct {
|
||||||
uint32_t pllm_base; /* the control register */
|
uint32_t pllm_base; /* the control register */
|
||||||
uint32_t pllm_out; /* output control */
|
uint32_t pllm_out; /* output control */
|
||||||
uint32_t pllm_misc1; /* misc1 */
|
uint32_t pllm_misc1; /* misc1 */
|
||||||
uint32_t pllm_misc2; /* misc2 */
|
uint32_t pllm_misc2; /* misc2 */
|
||||||
};
|
} clk_pllm_t;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Most PLLs use the clk_pll structure, but some have a simpler two-member
|
|
||||||
* structure for which we use clk_pll_simple. The reason for this non-
|
|
||||||
* othogonal setup is not stated.
|
|
||||||
*/
|
|
||||||
enum {
|
|
||||||
TEGRA_CLK_PLLS = 6, /* Number of normal PLLs */
|
|
||||||
TEGRA_CLK_SIMPLE_PLLS = 3, /* Number of simple PLLs */
|
|
||||||
TEGRA_CLK_SOURCES = 64, /* Number of ppl clock sources L/H/U */
|
|
||||||
TEGRA_CLK_SOURCES_VW = 32, /* Number of ppl clock sources V/W */
|
|
||||||
TEGRA_CLK_SOURCES_X = 32, /* Number of ppl clock sources X */
|
|
||||||
TEGRA_CLK_SOURCES_Y = 18, /* Number of ppl clock sources Y */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Masks for TEGRA_CLK_SOURCE elements.
|
|
||||||
*/
|
|
||||||
enum {
|
|
||||||
CLK_SOURCE_MASK = (0b111 << 29),
|
|
||||||
CLK_SOURCE_SDMMC1_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */
|
|
||||||
CLK_SOURCE_SDMMC4_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */
|
|
||||||
CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ = (0b001 << 29), /* 199.68 MHz */
|
|
||||||
CLK_SOURCE_SDMMC_LEGACY_PLLP_OUT0 = (0b100 << 29), /* Fixed 408 MHz */
|
|
||||||
|
|
||||||
CLK_DIVIDER_MASK = (0xff << 0),
|
|
||||||
CLK_DIVIDER_UNITY = (0x00 << 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset bits for relevant registers.
|
|
||||||
*/
|
|
||||||
enum {
|
|
||||||
CAR_CONTROL_SDMMC1 = (1 << 14),
|
|
||||||
CAR_CONTROL_SDMMC4 = (1 << 15),
|
|
||||||
CAR_CONTROL_SDMMC_LEGACY = (1 << 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
CLK_SOURCE_SDMMC1 = 20,
|
|
||||||
CLK_SOURCE_SDMMC4 = 25, /* 0x54 into the the main source block */
|
|
||||||
|
|
||||||
CLK_SOURCE_SDMMC_LEGACY = 0, /* first in block Y */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
|
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
|
||||||
struct tegra_car {
|
typedef struct {
|
||||||
uint32_t rst_src; /* _RST_SOURCE_0,0x00 */
|
uint32_t rst_src; /* _RST_SOURCE_0,0x00 */
|
||||||
|
|
||||||
uint32_t rst_dev_l;
|
uint32_t rst_dev_l;
|
||||||
uint32_t rst_dev_h;
|
uint32_t rst_dev_h;
|
||||||
uint32_t rst_dev_u;
|
uint32_t rst_dev_u;
|
||||||
|
|
||||||
uint32_t clk_out_dev_l;
|
uint32_t clk_out_enb_l;
|
||||||
uint32_t clk_out_dev_h;
|
uint32_t clk_out_enb_h;
|
||||||
uint32_t clk_out_dev_u;
|
uint32_t clk_out_enb_u;
|
||||||
|
|
||||||
uint32_t reserved0; /* reserved_0, 0x1C */
|
uint32_t reserved0; /* reserved_0, 0x1C */
|
||||||
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
|
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
|
||||||
|
@ -108,10 +81,10 @@ struct tegra_car {
|
||||||
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0,0x5C */
|
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0,0x5C */
|
||||||
uint32_t reserved2[8]; /* reserved_2[8], 0x60-7C */
|
uint32_t reserved2[8]; /* reserved_2[8], 0x60-7C */
|
||||||
|
|
||||||
struct clk_pll pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */
|
clk_pll_t pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */
|
||||||
|
|
||||||
/* PLLs from 0xe0 to 0xf4 */
|
/* PLLs from 0xe0 to 0xf4 */
|
||||||
struct clk_pll_simple pll_simple[TEGRA_CLK_SIMPLE_PLLS];
|
clk_pll_simple_t pll_simple[TEGRA_CLK_SIMPLE_PLLS];
|
||||||
|
|
||||||
uint32_t reserved10; /* _reserved_10, 0xF8 */
|
uint32_t reserved10; /* _reserved_10, 0xF8 */
|
||||||
uint32_t reserved11; /* _reserved_11, 0xFC */
|
uint32_t reserved11; /* _reserved_11, 0xFC */
|
||||||
|
@ -270,7 +243,7 @@ struct tegra_car {
|
||||||
uint32_t _rsv32[4]; /* 0x560-0x56c */
|
uint32_t _rsv32[4]; /* 0x560-0x56c */
|
||||||
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */
|
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */
|
||||||
uint32_t _rsv32_1[7]; /* 0x574-58c */
|
uint32_t _rsv32_1[7]; /* 0x574-58c */
|
||||||
struct clk_pll_simple plldp; /* _PLLDP_BASE, 0x590 _PLLDP_MISC */
|
clk_pll_simple_t plldp; /* _PLLDP_BASE, 0x590 _PLLDP_MISC */
|
||||||
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
|
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
|
||||||
|
|
||||||
/* Tegra124+ - skip to 0x600 here for new CLK_SOURCE_ regs */
|
/* Tegra124+ - skip to 0x600 here for new CLK_SOURCE_ regs */
|
||||||
|
@ -279,20 +252,17 @@ struct tegra_car {
|
||||||
|
|
||||||
/* Tegra210 - skip to 0x694 here for new CLK_SOURCE_ regs */
|
/* Tegra210 - skip to 0x694 here for new CLK_SOURCE_ regs */
|
||||||
uint32_t reserved61[5]; /* _reserved_61, 0x680 - 0x690 */
|
uint32_t reserved61[5]; /* _reserved_61, 0x680 - 0x690 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: PLLA1 regs are in the middle of this Y region. Break this in
|
* NOTE: PLLA1 regs are in the middle of this Y region. Break this in
|
||||||
* two later if PLLA1 is needed, but for now this is cleaner.
|
* two later if PLLA1 is needed, but for now this is cleaner.
|
||||||
*/
|
*/
|
||||||
uint32_t clk_src_y[TEGRA_CLK_SOURCES_Y]; /* SPARE1, etc, 0x694-0x6D8 */
|
uint32_t clk_src_y[TEGRA_CLK_SOURCES_Y]; /* SPARE1, etc, 0x694-0x6D8 */
|
||||||
};
|
} tegra_car_t;
|
||||||
|
|
||||||
|
static inline volatile tegra_car_t *car_get_regs(void)
|
||||||
/**
|
|
||||||
* Utility function that grabs the Tegra CAR registers.
|
|
||||||
*/
|
|
||||||
static inline struct tegra_car *car_get_regs(void)
|
|
||||||
{
|
{
|
||||||
return (struct tegra_car *)0x60006000UL;
|
return (volatile tegra_car_t *)0x60006000;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "device_partition.h"
|
#include "device_partition.h"
|
||||||
|
|
||||||
int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) {
|
int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors)
|
||||||
|
{
|
||||||
int rc;
|
int rc;
|
||||||
if (!devpart->initialized) {
|
if (!devpart->initialized) {
|
||||||
rc = devpart->initializer(devpart);
|
rc = devpart->initializer(devpart);
|
||||||
|
@ -28,16 +29,15 @@ int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) {
|
int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors)
|
||||||
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!devpart->initialized) {
|
if (!devpart->initialized) {
|
||||||
rc = devpart->initializer(devpart);
|
rc = devpart->initializer(devpart);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (devpart->read_cipher != NULL && devpart->crypto_mode != DevicePartitionCryptoMode_None) {
|
if (devpart->read_cipher != NULL && devpart->crypto_mode != DevicePartitionCryptoMode_None) {
|
||||||
for (uint64_t i = 0; i < num_sectors; i += devpart->crypto_work_buffer_num_sectors) {
|
for (uint64_t i = 0; i < num_sectors; i += devpart->crypto_work_buffer_num_sectors) {
|
||||||
uint64_t n = (i + devpart->crypto_work_buffer_num_sectors > num_sectors) ? (num_sectors - i) : devpart->crypto_work_buffer_num_sectors;
|
uint64_t n = (i + devpart->crypto_work_buffer_num_sectors > num_sectors) ? (num_sectors - i) : devpart->crypto_work_buffer_num_sectors;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "hwinit.h"
|
|
||||||
#include "sdmmc.h"
|
|
||||||
|
|
||||||
size_t get_file_size(const char *filename) {
|
size_t get_file_size(const char *filename) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define FUSEE_FS_UTILS_H
|
#define FUSEE_FS_UTILS_H
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "sdmmc.h"
|
#include "sdmmc/sdmmc.h"
|
||||||
|
|
||||||
size_t get_file_size(const char *filename);
|
size_t get_file_size(const char *filename);
|
||||||
size_t read_from_file(void *dst, size_t dst_size, const char *filename);
|
size_t read_from_file(void *dst, size_t dst_size, const char *filename);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "hwinit.h"
|
#include "hwinit.h"
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#ifndef FUSEE_FUSE_H
|
#ifndef FUSEE_FUSE_H
|
||||||
#define FUSEE_FUSE_H
|
#define FUSEE_FUSE_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t FUSE_CTRL;
|
uint32_t FUSE_CTRL;
|
||||||
uint32_t FUSE_REG_ADDR;
|
uint32_t FUSE_REG_ADDR;
|
||||||
|
|
|
@ -1,19 +1,9 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
|
#include "utils.h"
|
||||||
enum tegra_gpio_shifts {
|
|
||||||
GPIO_BANK_SHIFT = 5,
|
|
||||||
GPIO_PORT_SHIFT = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum tegra_gpio_masks {
|
|
||||||
GPIO_PORT_MASK = 0x3,
|
|
||||||
GPIO_PIN_MASK = 0x7,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a GPIO bank object that corresponds to the given GPIO pin,
|
* Returns a GPIO bank object that corresponds to the given GPIO pin,
|
||||||
|
@ -22,35 +12,31 @@ enum tegra_gpio_masks {
|
||||||
* @param pin The GPIO to get the bank for.
|
* @param pin The GPIO to get the bank for.
|
||||||
* @return The GPIO bank object to use for working with the given bank.
|
* @return The GPIO bank object to use for working with the given bank.
|
||||||
*/
|
*/
|
||||||
static volatile struct tegra_gpio_bank *gpio_get_bank(enum tegra_named_gpio pin)
|
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin)
|
||||||
{
|
{
|
||||||
volatile struct tegra_gpio *gpio = gpio_get_regs();
|
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
||||||
int bank_number = pin >> GPIO_BANK_SHIFT;
|
uint32_t bank_number = pin >> GPIO_BANK_SHIFT;
|
||||||
|
|
||||||
return &gpio->bank[bank_number];
|
return &gpio->bank[bank_number];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the port number for working with the given GPIO.
|
* @return the port number for working with the given GPIO.
|
||||||
*/
|
*/
|
||||||
static volatile int gpio_get_port(enum tegra_named_gpio pin)
|
static volatile uint32_t gpio_get_port(uint32_t pin)
|
||||||
{
|
{
|
||||||
return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK;
|
return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a mask to be used to work with the given GPIO
|
* @return a mask to be used to work with the given GPIO
|
||||||
*/
|
*/
|
||||||
static volatile uint32_t gpio_get_mask(enum tegra_named_gpio pin)
|
static volatile uint32_t gpio_get_mask(uint32_t pin)
|
||||||
{
|
{
|
||||||
uint32_t pin_number = pin & GPIO_PIN_MASK;
|
uint32_t pin_number = pin & GPIO_PIN_MASK;
|
||||||
return (1 << pin_number);
|
return (1 << pin_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a simple GPIO configuration operation.
|
* Performs a simple GPIO configuration operation.
|
||||||
*
|
*
|
||||||
|
@ -58,7 +44,7 @@ static volatile uint32_t gpio_get_mask(enum tegra_named_gpio pin)
|
||||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
||||||
* @param offset The offset into a gpio_bank structure
|
* @param offset The offset into a gpio_bank structure
|
||||||
*/
|
*/
|
||||||
static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_set, size_t offset)
|
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset)
|
||||||
{
|
{
|
||||||
// Retrieve the register set that corresponds to the given pin and offset.
|
// Retrieve the register set that corresponds to the given pin and offset.
|
||||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||||
|
@ -66,10 +52,9 @@ static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_s
|
||||||
|
|
||||||
// Figure out the offset into the cluster,
|
// Figure out the offset into the cluster,
|
||||||
// and the mask to be used.
|
// and the mask to be used.
|
||||||
int port = gpio_get_port(pin);
|
uint32_t port = gpio_get_port(pin);
|
||||||
uint32_t mask = gpio_get_mask(pin);
|
uint32_t mask = gpio_get_mask(pin);
|
||||||
|
|
||||||
|
|
||||||
// Set or clear the bit, as appropriate.
|
// Set or clear the bit, as appropriate.
|
||||||
if (should_be_set)
|
if (should_be_set)
|
||||||
cluster[port] |= mask;
|
cluster[port] |= mask;
|
||||||
|
@ -77,7 +62,6 @@ static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_s
|
||||||
cluster[port] &= ~mask;
|
cluster[port] &= ~mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a simple GPIO configuration operation.
|
* Performs a simple GPIO configuration operation.
|
||||||
*
|
*
|
||||||
|
@ -85,7 +69,7 @@ static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_s
|
||||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
||||||
* @param offset The offset into a gpio_bank structure
|
* @param offset The offset into a gpio_bank structure
|
||||||
*/
|
*/
|
||||||
static bool gpio_simple_register_get(enum tegra_named_gpio pin, size_t offset)
|
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset)
|
||||||
{
|
{
|
||||||
// Retrieve the register set that corresponds to the given pin and offset.
|
// Retrieve the register set that corresponds to the given pin and offset.
|
||||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||||
|
@ -93,57 +77,53 @@ static bool gpio_simple_register_get(enum tegra_named_gpio pin, size_t offset)
|
||||||
|
|
||||||
// Figure out the offset into the cluster,
|
// Figure out the offset into the cluster,
|
||||||
// and the mask to be used.
|
// and the mask to be used.
|
||||||
int port = gpio_get_port(pin);
|
uint32_t port = gpio_get_port(pin);
|
||||||
uint32_t mask = gpio_get_mask(pin);
|
uint32_t mask = gpio_get_mask(pin);
|
||||||
|
|
||||||
// Convert the given value to a boolean.
|
// Convert the given value to a boolean.
|
||||||
return !!(cluster[port] & mask);
|
return !!(cluster[port] & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures a given pin as either GPIO or SFIO.
|
* Configures a given pin as either GPIO or SFIO.
|
||||||
*
|
*
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||||
* @param mode The relevant mode.
|
* @param mode The relevant mode.
|
||||||
*/
|
*/
|
||||||
void gpio_configure_mode(enum tegra_named_gpio pin, enum tegra_gpio_mode mode)
|
void gpio_configure_mode(uint32_t pin, uint32_t mode)
|
||||||
{
|
{
|
||||||
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(struct tegra_gpio_bank, config));
|
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures a given pin as either INPUT or OUPUT.
|
* Configures a given pin as either INPUT or OUPUT.
|
||||||
*
|
*
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||||
* @param direction The relevant direction.
|
* @param direction The relevant direction.
|
||||||
*/
|
*/
|
||||||
void gpio_configure_direction(enum tegra_named_gpio pin, enum tegra_gpio_direction dir)
|
void gpio_configure_direction(uint32_t pin, uint32_t dir)
|
||||||
{
|
{
|
||||||
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(struct tegra_gpio_bank, direction));
|
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
* Drives a relevant GPIO pin as either HIGH or LOW.
|
||||||
*
|
*
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||||
* @param mode The relevant mode.
|
* @param mode The relevant mode.
|
||||||
*/
|
*/
|
||||||
void gpio_write(enum tegra_named_gpio pin, enum tegra_gpio_value value)
|
void gpio_write(uint32_t pin, uint32_t value)
|
||||||
{
|
{
|
||||||
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(struct tegra_gpio_bank, out));
|
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
* Drives a relevant GPIO pin as either HIGH or LOW.
|
||||||
*
|
*
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||||
* @param mode The relevant mode.
|
* @param mode The relevant mode.
|
||||||
*/
|
*/
|
||||||
enum tegra_gpio_value gpio_read(enum tegra_named_gpio pin)
|
uint32_t gpio_read(uint32_t pin)
|
||||||
{
|
{
|
||||||
return gpio_simple_register_get(pin, offsetof(struct tegra_gpio_bank, in));
|
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
/*
|
#ifndef FUSEE_GPIO_H
|
||||||
* Struct defintiions lifted from NVIDIA sample code.
|
#define FUSEE_GPIO_H
|
||||||
* (C) Copyright 2013-2015 NVIDIA Corporation <www.nvidia.com>
|
|
||||||
*
|
|
||||||
* adapted for Fusée by Kate Temkin <k@ktemkin.com.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
#define TEGRA_GPIO_PORTS 4
|
||||||
|
#define TEGRA_GPIO_BANKS 8
|
||||||
|
#define GPIO_BANK_SHIFT 5
|
||||||
|
#define GPIO_PORT_SHIFT 3
|
||||||
|
#define GPIO_PORT_MASK 0x03
|
||||||
|
#define GPIO_PIN_MASK 0x07
|
||||||
|
|
||||||
#ifndef __FUSEE_GPIO_H__
|
typedef enum {
|
||||||
#define __FUSEE_GPIO_H__
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
enum tegra_gpio_port {
|
|
||||||
TEGRA_GPIO_PORT_A = 0,
|
TEGRA_GPIO_PORT_A = 0,
|
||||||
TEGRA_GPIO_PORT_B = 1,
|
TEGRA_GPIO_PORT_B = 1,
|
||||||
TEGRA_GPIO_PORT_C = 2,
|
TEGRA_GPIO_PORT_C = 2,
|
||||||
|
@ -46,25 +41,9 @@ enum tegra_gpio_port {
|
||||||
TEGRA_GPIO_PORT_DD = 29,
|
TEGRA_GPIO_PORT_DD = 29,
|
||||||
TEGRA_GPIO_PORT_EE = 30,
|
TEGRA_GPIO_PORT_EE = 30,
|
||||||
TEGRA_GPIO_PORT_FF = 31,
|
TEGRA_GPIO_PORT_FF = 31,
|
||||||
};
|
} tegra_gpio_port;
|
||||||
|
|
||||||
/**
|
typedef struct {
|
||||||
* Convenince macro for computing a GPIO port number.
|
|
||||||
*/
|
|
||||||
#define TEGRA_GPIO(port, offset) \
|
|
||||||
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The Tegra210 GPIO controller has 256 GPIOS in 8 banks of 4 ports,
|
|
||||||
* each with 8 GPIOs.
|
|
||||||
*/
|
|
||||||
enum {
|
|
||||||
TEGRA_GPIO_PORTS = 4, /* number of ports per bank */
|
|
||||||
TEGRA_GPIO_BANKS = 8, /* number of banks */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* GPIO Controller registers for a single bank */
|
|
||||||
struct tegra_gpio_bank {
|
|
||||||
uint32_t config[TEGRA_GPIO_PORTS];
|
uint32_t config[TEGRA_GPIO_PORTS];
|
||||||
uint32_t direction[TEGRA_GPIO_PORTS];
|
uint32_t direction[TEGRA_GPIO_PORTS];
|
||||||
uint32_t out[TEGRA_GPIO_PORTS];
|
uint32_t out[TEGRA_GPIO_PORTS];
|
||||||
|
@ -81,94 +60,40 @@ struct tegra_gpio_bank {
|
||||||
uint32_t masked_int_enable[TEGRA_GPIO_PORTS];
|
uint32_t masked_int_enable[TEGRA_GPIO_PORTS];
|
||||||
uint32_t masked_int_level[TEGRA_GPIO_PORTS];
|
uint32_t masked_int_level[TEGRA_GPIO_PORTS];
|
||||||
uint32_t masked_int_clear[TEGRA_GPIO_PORTS];
|
uint32_t masked_int_clear[TEGRA_GPIO_PORTS];
|
||||||
};
|
} tegra_gpio_bank_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
tegra_gpio_bank_t bank[TEGRA_GPIO_BANKS];
|
||||||
|
} tegra_gpio_t;
|
||||||
|
|
||||||
/**
|
static inline volatile tegra_gpio_t *gpio_get_regs(void)
|
||||||
* Representation of Tegra GPIO controllers.
|
|
||||||
*/
|
|
||||||
struct tegra_gpio {
|
|
||||||
struct tegra_gpio_bank bank[TEGRA_GPIO_BANKS];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GPIO pins that have a more detailed functional name,
|
|
||||||
* specialized for the Switch.
|
|
||||||
*/
|
|
||||||
enum tegra_named_gpio {
|
|
||||||
GPIO_MICROSD_CARD_DETECT = TEGRA_GPIO(Z, 1),
|
|
||||||
GPIO_MICROSD_WRITE_PROTECT = TEGRA_GPIO(Z, 4),
|
|
||||||
GPIO_MICROSD_SUPPLY_ENABLE = TEGRA_GPIO(E, 4),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mode select for GPIO or SFIO.
|
|
||||||
*/
|
|
||||||
enum tegra_gpio_mode {
|
|
||||||
GPIO_MODE_GPIO = 0,
|
|
||||||
GPIO_MODE_SFIO = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GPIO direction values
|
|
||||||
*/
|
|
||||||
enum tegra_gpio_direction {
|
|
||||||
GPIO_DIRECTION_INPUT = 0,
|
|
||||||
GPIO_DIRECTION_OUTPUT = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Active-high GPIO logic
|
|
||||||
*/
|
|
||||||
enum tegra_gpio_value {
|
|
||||||
GPIO_LEVEL_LOW = 0,
|
|
||||||
GPIO_LEVEL_HIGH = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility function that grabs the Tegra pinmux registers.
|
|
||||||
*/
|
|
||||||
static inline struct tegra_gpio *gpio_get_regs(void)
|
|
||||||
{
|
{
|
||||||
return (struct tegra_gpio *)0x6000d000;
|
return (volatile tegra_gpio_t *)0x6000D000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#define TEGRA_GPIO(port, offset) \
|
||||||
* Configures a given pin as either GPIO or SFIO.
|
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
void gpio_configure_mode(enum tegra_named_gpio pin, enum tegra_gpio_mode mode);
|
|
||||||
|
|
||||||
|
/* Mode select */
|
||||||
|
#define GPIO_MODE_GPIO 0
|
||||||
|
#define GPIO_MODE_SFIO 1
|
||||||
|
|
||||||
/**
|
/* Direction */
|
||||||
* Configures a given pin as either INPUT or OUPUT.
|
#define GPIO_DIRECTION_INPUT 0
|
||||||
*
|
#define GPIO_DIRECTION_OUTPUT 1
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param direction The relevant direction.
|
|
||||||
*/
|
|
||||||
void gpio_configure_direction(enum tegra_named_gpio pin, enum tegra_gpio_direction dir);
|
|
||||||
|
|
||||||
|
/* Level */
|
||||||
|
#define GPIO_LEVEL_LOW 0
|
||||||
|
#define GPIO_LEVEL_HIGH 1
|
||||||
|
|
||||||
/**
|
/* Named GPIOs */
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
#define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1)
|
||||||
*
|
#define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4)
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
#define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4)
|
||||||
* @param mode The relevant value.
|
|
||||||
*/
|
|
||||||
void gpio_write(enum tegra_named_gpio pin, enum tegra_gpio_value value);
|
|
||||||
|
|
||||||
/**
|
void gpio_configure_mode(uint32_t pin, uint32_t mode);
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
void gpio_configure_direction(uint32_t pin, uint32_t dir);
|
||||||
*
|
void gpio_write(uint32_t pin, uint32_t value);
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
uint32_t gpio_read(uint32_t pin);
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
enum tegra_gpio_value gpio_read(enum tegra_named_gpio pin);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,11 +25,10 @@ DSTATUS disk_status (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
if (devpart == NULL) {
|
if (devpart)
|
||||||
|
return devpart->initialized ? RES_OK : STA_NOINIT;
|
||||||
|
else
|
||||||
return STA_NODISK;
|
return STA_NODISK;
|
||||||
} else {
|
|
||||||
return devpart->initialized ? 0 : STA_NOINIT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,14 +43,12 @@ DSTATUS disk_initialize (
|
||||||
{
|
{
|
||||||
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
if (devpart == NULL) {
|
if (!devpart)
|
||||||
return STA_NODISK;
|
return STA_NODISK;
|
||||||
} else if (devpart->initializer != NULL) {
|
else if (devpart->initializer)
|
||||||
int rc = devpart->initializer(devpart);
|
return devpart->initializer(devpart) ? STA_NOINIT : RES_OK;
|
||||||
return rc == 0 ? 0 : STA_NOINIT;
|
else
|
||||||
} else {
|
return RES_OK;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,15 +66,13 @@ DRESULT disk_read (
|
||||||
{
|
{
|
||||||
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
if (devpart == NULL) {
|
if (!devpart)
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
} else if (devpart->reader != NULL) {
|
else if (devpart->reader)
|
||||||
int rc = device_partition_read_data(devpart, buff, sector, count);
|
return device_partition_read_data(devpart, buff, sector, count) ? RES_ERROR : RES_OK;
|
||||||
return rc == 0 ? 0 : RES_ERROR;
|
else
|
||||||
} else {
|
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,15 +89,13 @@ DRESULT disk_write (
|
||||||
{
|
{
|
||||||
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
if (devpart == NULL) {
|
if (!devpart)
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
} else if (devpart->writer != NULL) {
|
else if (devpart->writer)
|
||||||
int rc = device_partition_write_data(devpart, buff, sector, count);
|
return device_partition_write_data(devpart, buff, sector, count) ? RES_ERROR : RES_OK;
|
||||||
return rc == 0 ? 0 : RES_ERROR;
|
else
|
||||||
} else {
|
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,10 +112,10 @@ DRESULT disk_ioctl (
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case GET_SECTOR_SIZE:
|
case GET_SECTOR_SIZE:
|
||||||
*(WORD *)buff = devpart != NULL ? (WORD)devpart->sector_size : 512;
|
*(WORD *)buff = devpart ? (WORD)devpart->sector_size : 512;
|
||||||
return 0;
|
return RES_OK;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,10 @@
|
||||||
#include "nxboot.h"
|
#include "nxboot.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "switch_fs.h"
|
#include "nxfs.h"
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
#include "display/video_fb.h"
|
#include "display/video_fb.h"
|
||||||
|
#include "sdmmc/sdmmc.h"
|
||||||
|
|
||||||
extern void (*__program_exit_callback)(int rc);
|
extern void (*__program_exit_callback)(int rc);
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ static void setup_env(void) {
|
||||||
/* Set up exception handlers. */
|
/* Set up exception handlers. */
|
||||||
setup_exception_handlers();
|
setup_exception_handlers();
|
||||||
|
|
||||||
if(/*switchfs_import_mmc_structs(&g_stage2_args->sd_mmc, NULL) == -1 ||*/ switchfs_mount_all() == -1) {
|
if (nxfs_mount_all() < 0) {
|
||||||
fatal_error("Failed to mount at least one parition: %s\n", strerror(errno));
|
fatal_error("Failed to mount at least one parition: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ static void setup_env(void) {
|
||||||
|
|
||||||
static void cleanup_env(void) {
|
static void cleanup_env(void) {
|
||||||
/* Unmount everything (this causes all open files to be flushed and closed) */
|
/* Unmount everything (this causes all open files to be flushed and closed) */
|
||||||
switchfs_unmount_all();
|
nxfs_unmount_all();
|
||||||
//console_end();
|
//console_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,12 +62,16 @@ int main(int argc, void **argv) {
|
||||||
if (argc != STAGE2_ARGC) {
|
if (argc != STAGE2_ARGC) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_stage2_args = (stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT];
|
g_stage2_args = (stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT];
|
||||||
|
|
||||||
if (g_stage2_args->version != 0) {
|
if (g_stage2_args->version != 0) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the SDMMC's driver logging level. */
|
||||||
|
sdmmc_set_log_level(SDMMC_LOG_INFO);
|
||||||
|
|
||||||
/* Initialize the display, console, FS, etc. */
|
/* Initialize the display, console, FS, etc. */
|
||||||
setup_env();
|
setup_env();
|
||||||
|
|
||||||
|
|
|
@ -2,28 +2,37 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "switch_fs.h"
|
#include <string.h>
|
||||||
|
#include "nxfs.h"
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
#include "sdmmc.h"
|
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "hwinit.h"
|
#include "hwinit.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "sdmmc/sdmmc.h"
|
||||||
|
|
||||||
static bool g_ahb_redirect_enabled = false;
|
static bool g_ahb_redirect_enabled = false;
|
||||||
static bool g_sd_mmc_initialized = false;
|
static bool g_sd_device_initialized = false;
|
||||||
static bool g_nand_mmc_initialized = false;
|
static bool g_emmc_device_initialized = false;
|
||||||
|
|
||||||
static bool g_sd_mmc_imported = false;
|
static sdmmc_t g_sd_sdmmc = {0};
|
||||||
static bool g_nand_mmc_imported = false;
|
static sdmmc_t g_emmc_sdmmc = {0};
|
||||||
|
|
||||||
static struct mmc g_sd_mmc = {0};
|
static sdmmc_device_t g_sd_device = {0};
|
||||||
static struct mmc g_nand_mmc = {0};
|
static sdmmc_device_t g_emmc_device = {0};
|
||||||
|
|
||||||
typedef struct mmc_partition_info_t {
|
typedef struct mmc_partition_info_t {
|
||||||
struct mmc *mmc;
|
sdmmc_device_t *device;
|
||||||
enum sdmmc_controller controller;
|
SdmmcControllerNum controller;
|
||||||
enum sdmmc_partition mmc_partition;
|
SdmmcPartitionNum partition;
|
||||||
} mmc_partition_info_t;
|
} mmc_partition_info_t;
|
||||||
|
|
||||||
|
static mmc_partition_info_t g_sd_mmcpart = {&g_sd_device, SDMMC_1, SDMMC_PARTITION_USER};
|
||||||
|
static mmc_partition_info_t g_emmc_boot0_mmcpart = {&g_emmc_device, SDMMC_4, SDMMC_PARTITION_BOOT0};
|
||||||
|
static mmc_partition_info_t g_emmc_boot1_mmcpart = {&g_emmc_device, SDMMC_4, SDMMC_PARTITION_BOOT1};
|
||||||
|
static mmc_partition_info_t g_emmc_user_mmcpart = {&g_emmc_device, SDMMC_4, SDMMC_PARTITION_USER};
|
||||||
|
|
||||||
|
SdmmcPartitionNum g_current_emmc_partition = SDMMC_PARTITION_INVALID;
|
||||||
|
|
||||||
static int mmc_partition_initialize(device_partition_t *devpart) {
|
static int mmc_partition_initialize(device_partition_t *devpart) {
|
||||||
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
|
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
|
||||||
|
|
||||||
|
@ -44,27 +53,21 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
|
||||||
g_ahb_redirect_enabled = true;
|
g_ahb_redirect_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mmcpart->mmc == &g_sd_mmc) {
|
if (mmcpart->device == &g_sd_device) {
|
||||||
if (!g_sd_mmc_initialized) {
|
if (!g_sd_device_initialized) {
|
||||||
int rc = g_sd_mmc_imported ? 0 : sdmmc_init(mmcpart->mmc, mmcpart->controller, true);
|
int rc = sdmmc_device_sd_init(mmcpart->device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SDR104) ? 0 : EIO;
|
||||||
if (rc == 0) {
|
if (rc)
|
||||||
sdmmc_set_write_enable(mmcpart->mmc, SDMMC_WRITE_ENABLED);
|
|
||||||
g_sd_mmc_initialized = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
g_sd_device_initialized = true;
|
||||||
}
|
}
|
||||||
devpart->initialized = true;
|
devpart->initialized = true;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (mmcpart->mmc == &g_nand_mmc) {
|
} else if (mmcpart->device == &g_emmc_device) {
|
||||||
if (!g_nand_mmc_initialized) {
|
if (!g_emmc_device_initialized) {
|
||||||
int rc = g_nand_mmc_imported ? 0 : sdmmc_init(mmcpart->mmc, mmcpart->controller, true);
|
int rc = sdmmc_device_mmc_init(mmcpart->device, &g_emmc_sdmmc, SDMMC_BUS_WIDTH_8BIT, SDMMC_SPEED_HS400) ? 0 : EIO;
|
||||||
if (rc == 0) {
|
if (rc)
|
||||||
g_nand_mmc_initialized = true;
|
|
||||||
} else {
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
g_emmc_device_initialized = true;
|
||||||
}
|
}
|
||||||
devpart->initialized = true;
|
devpart->initialized = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -77,34 +80,31 @@ static void mmc_partition_finalize(device_partition_t *devpart) {
|
||||||
free(devpart->crypto_work_buffer);
|
free(devpart->crypto_work_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum sdmmc_partition g_current_emmc_partition = (enum sdmmc_partition)-1;
|
|
||||||
|
|
||||||
static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) {
|
static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) {
|
||||||
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
|
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
|
||||||
if (mmcpart->mmc == &g_nand_mmc && g_current_emmc_partition != mmcpart->mmc_partition) {
|
|
||||||
int rc = sdmmc_select_partition(mmcpart->mmc, mmcpart->mmc_partition);
|
if ((mmcpart->device == &g_emmc_device) && (g_current_emmc_partition != mmcpart->partition)) {
|
||||||
if (rc != 0 && rc != ENOTTY) {
|
if (!sdmmc_mmc_select_partition(mmcpart->device, mmcpart->partition))
|
||||||
return rc;
|
return EIO;
|
||||||
|
g_current_emmc_partition = mmcpart->partition;
|
||||||
}
|
}
|
||||||
g_current_emmc_partition = mmcpart->mmc_partition;
|
|
||||||
}
|
return sdmmc_device_read(mmcpart->device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, dst) ? 0 : EIO;
|
||||||
return sdmmc_read(mmcpart->mmc, dst, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmc_partition_write(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) {
|
static int mmc_partition_write(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) {
|
||||||
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
|
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
|
||||||
if (mmcpart->mmc == &g_nand_mmc && g_current_emmc_partition != mmcpart->mmc_partition) {
|
|
||||||
int rc = sdmmc_select_partition(mmcpart->mmc, mmcpart->mmc_partition);
|
if ((mmcpart->device == &g_emmc_device) && (g_current_emmc_partition != mmcpart->partition)) {
|
||||||
if (rc != 0 && rc != ENOTTY) {
|
if (!sdmmc_mmc_select_partition(mmcpart->device, mmcpart->partition))
|
||||||
return rc;
|
return EIO;
|
||||||
}
|
g_current_emmc_partition = mmcpart->partition;
|
||||||
g_current_emmc_partition = mmcpart->mmc_partition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sdmmc_write(mmcpart->mmc, src, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors);
|
return sdmmc_device_write(mmcpart->device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, (void *)src) ? 0 : EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int switchfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) {
|
static int nxfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) {
|
||||||
unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */
|
unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */
|
||||||
unsigned int keyslot_b = 5;
|
unsigned int keyslot_b = 5;
|
||||||
size_t size = num_sectors * devpart->sector_size;
|
size_t size = num_sectors * devpart->sector_size;
|
||||||
|
@ -124,7 +124,7 @@ static int switchfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int switchfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) {
|
static int nxfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) {
|
||||||
unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */
|
unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */
|
||||||
unsigned int keyslot_b = 5;
|
unsigned int keyslot_b = 5;
|
||||||
size_t size = num_sectors * devpart->sector_size;
|
size_t size = num_sectors * devpart->sector_size;
|
||||||
|
@ -144,11 +144,6 @@ static int switchfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mmc_partition_info_t g_sd_mmcpart = { &g_sd_mmc, SWITCH_MICROSD, SDMMC_PARTITION_USER };
|
|
||||||
static mmc_partition_info_t g_nand_boot0_mmcpart = { &g_nand_mmc, SWITCH_EMMC, SDMMC_PARTITION_BOOT0 };
|
|
||||||
static mmc_partition_info_t g_nand_boot1_mmcpart = { &g_nand_mmc, SWITCH_EMMC, SDMMC_PARTITION_BOOT1 };
|
|
||||||
static mmc_partition_info_t g_nand_user_mmcpart = { &g_nand_mmc, SWITCH_EMMC, SDMMC_PARTITION_USER };
|
|
||||||
|
|
||||||
static const device_partition_t g_mmc_devpart_template = {
|
static const device_partition_t g_mmc_devpart_template = {
|
||||||
.sector_size = 512,
|
.sector_size = 512,
|
||||||
.initializer = mmc_partition_initialize,
|
.initializer = mmc_partition_initialize,
|
||||||
|
@ -157,7 +152,7 @@ static const device_partition_t g_mmc_devpart_template = {
|
||||||
.writer = mmc_partition_write,
|
.writer = mmc_partition_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk) {
|
static int nxfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk) {
|
||||||
(void)entry_offset;
|
(void)entry_offset;
|
||||||
(void)disk;
|
(void)disk;
|
||||||
device_partition_t *parent = (device_partition_t *)param;
|
device_partition_t *parent = (device_partition_t *)param;
|
||||||
|
@ -204,8 +199,8 @@ static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void
|
||||||
}
|
}
|
||||||
|
|
||||||
if (known_partitions[i].is_encrypted) {
|
if (known_partitions[i].is_encrypted) {
|
||||||
devpart.read_cipher = switchfs_bis_crypto_decrypt;
|
devpart.read_cipher = nxfs_bis_crypto_decrypt;
|
||||||
devpart.write_cipher = switchfs_bis_crypto_encrypt;
|
devpart.write_cipher = nxfs_bis_crypto_encrypt;
|
||||||
devpart.crypto_mode = DevicePartitionCryptoMode_Xts;
|
devpart.crypto_mode = DevicePartitionCryptoMode_Xts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,37 +233,7 @@ static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int switchfs_import_mmc_structs(void *sd, void *nand) {
|
int nxfs_mount_all(void) {
|
||||||
if (sd != NULL) {
|
|
||||||
int rc = 0;
|
|
||||||
memcpy(&g_sd_mmc, sd, sizeof(g_sd_mmc));
|
|
||||||
rc = sdmmc_import_struct(&g_sd_mmc);
|
|
||||||
if (rc != 0) {
|
|
||||||
memset(&g_sd_mmc, 0, sizeof(g_sd_mmc));
|
|
||||||
errno = rc;
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
g_sd_mmc_imported = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nand != NULL) {
|
|
||||||
int rc = 0;
|
|
||||||
memcpy(&g_nand_mmc, nand, sizeof(g_nand_mmc));
|
|
||||||
rc = sdmmc_import_struct(&g_nand_mmc);
|
|
||||||
if (rc != 0) {
|
|
||||||
memset(&g_nand_mmc, 0, sizeof(g_nand_mmc));
|
|
||||||
errno = rc;
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
g_nand_mmc_imported = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int switchfs_mount_all(void) {
|
|
||||||
device_partition_t model;
|
device_partition_t model;
|
||||||
int rc;
|
int rc;
|
||||||
FILE *rawnand;
|
FILE *rawnand;
|
||||||
|
@ -278,63 +243,80 @@ int switchfs_mount_all(void) {
|
||||||
model.device_struct = &g_sd_mmcpart;
|
model.device_struct = &g_sd_mmcpart;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = 1u << 30; /* arbitrary numbers of sectors. TODO: find the size of the SD in sectors. */
|
model.num_sectors = 1u << 30; /* arbitrary numbers of sectors. TODO: find the size of the SD in sectors. */
|
||||||
|
|
||||||
rc = fsdev_mount_device("sdmc", &model, true);
|
rc = fsdev_mount_device("sdmc", &model, true);
|
||||||
|
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fsdev_register_device("sdmc");
|
rc = fsdev_register_device("sdmc");
|
||||||
|
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Boot0. */
|
/* Boot0. */
|
||||||
model = g_mmc_devpart_template;
|
model = g_mmc_devpart_template;
|
||||||
model.device_struct = &g_nand_boot0_mmcpart;
|
model.device_struct = &g_emmc_boot0_mmcpart;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = 0x184000 / model.sector_size;
|
model.num_sectors = 0x184000 / model.sector_size;
|
||||||
|
|
||||||
rc = rawdev_mount_device("boot0", &model, true);
|
rc = rawdev_mount_device("boot0", &model, true);
|
||||||
|
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = rawdev_register_device("boot0");
|
rc = rawdev_register_device("boot0");
|
||||||
|
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Boot1. */
|
/* Boot1. */
|
||||||
model = g_mmc_devpart_template;
|
model = g_mmc_devpart_template;
|
||||||
model.device_struct = &g_nand_boot1_mmcpart;
|
model.device_struct = &g_emmc_boot1_mmcpart;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = 0x80000 / model.sector_size;
|
model.num_sectors = 0x80000 / model.sector_size;
|
||||||
|
|
||||||
rc = rawdev_mount_device("boot1", &model, false);
|
rc = rawdev_mount_device("boot1", &model, false);
|
||||||
|
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't register boot1 for now. */
|
/* Don't register boot1 for now. */
|
||||||
|
|
||||||
/* Raw NAND (excluding boot partitions), and its partitions. */
|
/* Raw NAND (excluding boot partitions), and its partitions. */
|
||||||
model = g_mmc_devpart_template;
|
model = g_mmc_devpart_template;
|
||||||
model = g_mmc_devpart_template;
|
model = g_mmc_devpart_template;
|
||||||
model.device_struct = &g_nand_user_mmcpart;
|
model.device_struct = &g_emmc_user_mmcpart;
|
||||||
model.start_sector = 0;
|
model.start_sector = 0;
|
||||||
model.num_sectors = (32ull << 30) / model.sector_size;
|
model.num_sectors = (32ull << 30) / model.sector_size;
|
||||||
|
|
||||||
rc = rawdev_mount_device("rawnand", &model, false);
|
rc = rawdev_mount_device("rawnand", &model, false);
|
||||||
|
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = rawdev_register_device("rawnand");
|
rc = rawdev_register_device("rawnand");
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rawnand = fopen("rawnand:/", "rb");
|
rawnand = fopen("rawnand:/", "rb");
|
||||||
rc = gpt_iterate_through_entries(rawnand, model.sector_size, switchfs_mount_partition_gpt_callback, &model);
|
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
|
||||||
fclose(rawnand);
|
fclose(rawnand);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = fsdev_set_default_device("sdmc");
|
rc = fsdev_set_default_device("sdmc");
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int switchfs_unmount_all(void) {
|
int nxfs_unmount_all(void) {
|
||||||
return fsdev_unmount_all() != 0 || rawdev_unmount_all() != 0 ? -1 : 0;
|
return ((fsdev_unmount_all() || rawdev_unmount_all()) ? -1 : 0);
|
||||||
}
|
}
|
10
fusee/fusee-secondary/src/nxfs.h
Normal file
10
fusee/fusee-secondary/src/nxfs.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef FUSEE_NX_FS_H
|
||||||
|
#define FUSEE_NX_FS_H
|
||||||
|
|
||||||
|
#include "fs_dev.h"
|
||||||
|
#include "raw_dev.h"
|
||||||
|
|
||||||
|
int nxfs_mount_all(void);
|
||||||
|
int nxfs_unmount_all(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,67 +0,0 @@
|
||||||
/**
|
|
||||||
* Fusée pad control code
|
|
||||||
* ~ktemkin
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __FUSEE_PADCTL_H__
|
|
||||||
#define __FUSEE_PADCTL_H__
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers in the Misc Pad control region
|
|
||||||
*/
|
|
||||||
struct tegra_padctl {
|
|
||||||
/* TODO: support registers before? */
|
|
||||||
uint32_t sdmmc1_control;
|
|
||||||
uint32_t sdmmc3_control;
|
|
||||||
uint32_t sdmmc2_control;
|
|
||||||
uint32_t sdmmc4_control;
|
|
||||||
|
|
||||||
/* TODO: support registers after? */
|
|
||||||
uint8_t _todo[656];
|
|
||||||
|
|
||||||
uint32_t vgpio_gpio_mux_sel;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Masks for Pad Control registers
|
|
||||||
*/
|
|
||||||
enum tegra_padctl_masks {
|
|
||||||
|
|
||||||
/* SDMMC1 */
|
|
||||||
PADCTL_SDMMC1_DEEP_LOOPBACK = (1 << 0),
|
|
||||||
|
|
||||||
/* SDMMC3 */
|
|
||||||
PADCTL_SDMMC3_DEEP_LOOPBACK = (1 << 0),
|
|
||||||
|
|
||||||
/* SDMMC2 */
|
|
||||||
PADCTL_SDMMC2_ENABLE_DATA_IN = (0xFF << 8),
|
|
||||||
PADCTL_SDMMC2_ENABLE_CLK_IN = (0x3 << 4),
|
|
||||||
PADCTL_SDMMC2_DEEP_LOOPBACK = (1 << 0),
|
|
||||||
|
|
||||||
/* SDMMC4 */
|
|
||||||
PADCTL_SDMMC4_ENABLE_DATA_IN = (0xFF << 8),
|
|
||||||
PADCTL_SDMMC4_ENABLE_CLK_IN = (0x3 << 4),
|
|
||||||
PADCTL_SDMMC4_DEEP_LOOPBACK = (1 << 0),
|
|
||||||
|
|
||||||
/* VGPIO/GPIO */
|
|
||||||
PADCTL_SDMMC1_CD_SOURCE = (1 << 0),
|
|
||||||
PADCTL_SDMMC1_WP_SOURCE = (1 << 1),
|
|
||||||
PADCTL_SDMMC3_CD_SOURCE = (1 << 2),
|
|
||||||
PADCTL_SDMMC3_WP_SOURCE = (1 << 3),
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility function that grabs the Tegra PADCTL registers.
|
|
||||||
*/
|
|
||||||
static inline struct tegra_padctl *padctl_get_regs(void)
|
|
||||||
{
|
|
||||||
return (struct tegra_padctl *)0x700008d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef EXOSPHERE_PANIC_COLOR_H
|
#ifndef FUSEE_PANIC_COLOR_H
|
||||||
#define EXOSPHERE_PANIC_COLOR_H
|
#define FUSEE_PANIC_COLOR_H
|
||||||
|
|
||||||
#define COLOR_0 0x00F00003
|
#define COLOR_0 0x00F00003
|
||||||
#define COLOR_1 0x0F000003
|
#define COLOR_1 0x0F000003
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
#ifndef __FUSEE_PINMUX_H__
|
#ifndef FUSEE_PINMUX_H
|
||||||
#define __FUSEE_PINMUX_H__
|
#define FUSEE_PINMUX_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#define PINMUX_TRISTATE (1 << 4)
|
||||||
#include <stdint.h>
|
#define PINMUX_PARKED (1 << 5)
|
||||||
#include "utils.h"
|
#define PINMUX_INPUT (1 << 6)
|
||||||
|
#define PINMUX_PULL_NONE (0 << 2)
|
||||||
|
#define PINMUX_PULL_DOWN (1 << 2)
|
||||||
|
#define PINMUX_PULL_UP (2 << 2)
|
||||||
|
#define PINMUX_SELECT_FUNCTION0 0
|
||||||
|
#define PINMUX_SELECT_FUNCTION1 1
|
||||||
|
#define PINMUX_SELECT_FUNCTION2 2
|
||||||
|
#define PINMUX_SELECT_FUNCTION3 3
|
||||||
|
#define PINMUX_DRIVE_1X (0 << 13)
|
||||||
|
#define PINMUX_DRIVE_2X (1 << 13)
|
||||||
|
#define PINMUX_DRIVE_3X (2 << 13)
|
||||||
|
#define PINMUX_DRIVE_4X (3 << 13)
|
||||||
|
|
||||||
/**
|
typedef struct {
|
||||||
* Pinmux structures.
|
|
||||||
*/
|
|
||||||
struct tegra_pinmux {
|
|
||||||
uint32_t sdmmc1_clk;
|
uint32_t sdmmc1_clk;
|
||||||
uint32_t sdmmc1_cmd;
|
uint32_t sdmmc1_cmd;
|
||||||
uint32_t sdmmc1_dat3;
|
uint32_t sdmmc1_dat3;
|
||||||
|
@ -174,48 +182,11 @@ struct tegra_pinmux {
|
||||||
uint32_t pz3;
|
uint32_t pz3;
|
||||||
uint32_t pz4;
|
uint32_t pz4;
|
||||||
uint32_t pz5;
|
uint32_t pz5;
|
||||||
};
|
} tegra_pinmux_t;
|
||||||
|
|
||||||
/**
|
static inline volatile tegra_pinmux_t *pinmux_get_regs(void)
|
||||||
* Constants for use of the Tegra Pinmux.
|
|
||||||
*/
|
|
||||||
enum tegra_pinmux_constants {
|
|
||||||
|
|
||||||
/* Tristate (output buffer) control */
|
|
||||||
PINMUX_TRISTATE = (1 << 4),
|
|
||||||
|
|
||||||
/* Park control */
|
|
||||||
PINMUX_PARKED = (1 << 5),
|
|
||||||
|
|
||||||
/* Input control */
|
|
||||||
PINMUX_INPUT = (1 << 6),
|
|
||||||
|
|
||||||
/* Pull resistors */
|
|
||||||
PINMUX_PULL_NONE = (0 << 2),
|
|
||||||
PINMUX_PULL_DOWN = (1 << 2),
|
|
||||||
PINMUX_PULL_UP = (2 << 2),
|
|
||||||
|
|
||||||
/* Function select */
|
|
||||||
PINMUX_SELECT_FUNCTION0 = 0,
|
|
||||||
PINMUX_SELECT_FUNCTION1 = 1,
|
|
||||||
PINMUX_SELECT_FUNCTION2 = 2,
|
|
||||||
PINMUX_SELECT_FUNCTION3 = 3,
|
|
||||||
|
|
||||||
/* Drive */
|
|
||||||
PINMUX_DRIVE_1X = (0x0 << 13),
|
|
||||||
PINMUX_DRIVE_2X = (0x1 << 13),
|
|
||||||
PINMUX_DRIVE_3X = (0x2 << 13),
|
|
||||||
PINMUX_DRIVE_4X = (0x3 << 13),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility function that grabs the Tegra pinmux registers.
|
|
||||||
*/
|
|
||||||
static inline struct tegra_pinmux *pinmux_get_regs(void)
|
|
||||||
{
|
{
|
||||||
return (struct tegra_pinmux *)0x70003000;
|
return (volatile tegra_pinmux_t *)0x70003000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,37 +1,27 @@
|
||||||
#ifndef __FUSEE_PMC_H__
|
#ifndef FUSEE_PMC_H
|
||||||
#define __FUSEE_PMC_H__
|
#define FUSEE_PMC_H
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#define PMC_BASE 0x7000E400
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO: get rid of these defines; use the struct instead */
|
/* TODO: get rid of these defines; use the struct instead */
|
||||||
|
#define PMC_BASE 0x7000E400
|
||||||
|
|
||||||
|
#define PMC_CONTROL_SDMMC1 (1 << 12)
|
||||||
|
#define PMC_CONTROL_SDMMC3 (1 << 13)
|
||||||
|
#define PMC_CONTROL_SDMMC4 (1 << 14)
|
||||||
|
|
||||||
#define APBDEV_PMC_CONTROL MAKE_REG32(PMC_BASE + 0x00)
|
#define APBDEV_PMC_CONTROL MAKE_REG32(PMC_BASE + 0x00)
|
||||||
|
|
||||||
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24)
|
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24)
|
||||||
|
|
||||||
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30)
|
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30)
|
||||||
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_REG32(PMC_BASE + 0x38)
|
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_REG32(PMC_BASE + 0x38)
|
||||||
|
|
||||||
#define APBDEV_PMC_SCRATCH0_0 MAKE_REG32(PMC_BASE + 0x50)
|
#define APBDEV_PMC_SCRATCH0_0 MAKE_REG32(PMC_BASE + 0x50)
|
||||||
|
|
||||||
#define APBDEV_PMC_CRYPTO_OP_0 MAKE_REG32(PMC_BASE + 0xF4)
|
#define APBDEV_PMC_CRYPTO_OP_0 MAKE_REG32(PMC_BASE + 0xF4)
|
||||||
|
|
||||||
#define APBDEV_PM_0 MAKE_REG32(PMC_BASE + 0x14)
|
#define APBDEV_PM_0 MAKE_REG32(PMC_BASE + 0x14)
|
||||||
#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_REG32(PMC_BASE + 0x168)
|
#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_REG32(PMC_BASE + 0x168)
|
||||||
#define APBDEV_PMC_RST_STATUS_0 MAKE_REG32(PMC_BASE + 0x1B4)
|
#define APBDEV_PMC_RST_STATUS_0 MAKE_REG32(PMC_BASE + 0x1B4)
|
||||||
#define APBDEV_PMC_CNTRL2_0 MAKE_REG32(PMC_BASE + 0x440)
|
#define APBDEV_PMC_CNTRL2_0 MAKE_REG32(PMC_BASE + 0x440)
|
||||||
|
|
||||||
#define APBDEV_PMC_SCRATCH43_0 MAKE_REG32(PMC_BASE + 0x22C)
|
#define APBDEV_PMC_SCRATCH43_0 MAKE_REG32(PMC_BASE + 0x22C)
|
||||||
|
|
||||||
#define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840)
|
#define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840)
|
||||||
|
|
||||||
/**
|
typedef struct {
|
||||||
* Definitions of the Tegra PMC.
|
|
||||||
* NOTE: Incomplete, do not use
|
|
||||||
*/
|
|
||||||
struct tegra_pmc {
|
|
||||||
uint32_t cntrl;
|
uint32_t cntrl;
|
||||||
uint32_t sec_disable;
|
uint32_t sec_disable;
|
||||||
uint32_t pmc_swrst;
|
uint32_t pmc_swrst;
|
||||||
|
@ -297,23 +287,11 @@ struct tegra_pmc {
|
||||||
uint32_t scratch118;
|
uint32_t scratch118;
|
||||||
uint32_t scratch119;
|
uint32_t scratch119;
|
||||||
uint32_t scratch1_eco;
|
uint32_t scratch1_eco;
|
||||||
};
|
} tegra_pmc_t;
|
||||||
|
|
||||||
enum tegra_pmc_masks {
|
static inline volatile tegra_pmc_t *pmc_get_regs(void)
|
||||||
/* NO_IOPOWER, power detect, ect. */
|
|
||||||
PMC_CONTROL_SDMMC1 = (1 << 12),
|
|
||||||
PMC_CONTROL_SDMMC3 = (1 << 13),
|
|
||||||
PMC_CONTROL_SDMMC4 = (1 << 14),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility function that grabs the Tegra PMC registers.
|
|
||||||
*/
|
|
||||||
static inline volatile struct tegra_pmc *pmc_get_regs(void)
|
|
||||||
{
|
{
|
||||||
return (volatile struct tegra_pmc *)0x7000E400;
|
return (volatile tegra_pmc_t *)0x7000E400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,313 +0,0 @@
|
||||||
/**
|
|
||||||
* Fusée SD/MMC driver for the Switch
|
|
||||||
* ~ktemkin
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __FUSEE_SDMMC_H__
|
|
||||||
#define __FUSEE_SDMMC_H__
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "utils.h"
|
|
||||||
#include "gpio.h"
|
|
||||||
|
|
||||||
/* Opaque pointer to the Tegra SDMMC registers */
|
|
||||||
struct tegra_sdmmc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bus widths supported by the SD/MMC cards.
|
|
||||||
*/
|
|
||||||
enum sdmmc_bus_width {
|
|
||||||
MMC_BUS_WIDTH_1BIT = 0,
|
|
||||||
MMC_BUS_WIDTH_4BIT = 1,
|
|
||||||
MMC_BUS_WIDTH_8BIT = 2,
|
|
||||||
|
|
||||||
SD_BUS_WIDTH_1BIT = 0,
|
|
||||||
SD_BUS_WIDTH_4BIT = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Describes the voltages that the host will use to drive the SD card.
|
|
||||||
* CAUTION: getting these wrong can damage (especially embedded) cards!
|
|
||||||
*/
|
|
||||||
enum sdmmc_bus_voltage {
|
|
||||||
MMC_VOLTAGE_3V3 = 0b111,
|
|
||||||
MMC_VOLTAGE_1V8 = 0b101,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the different types of devices an MMC object
|
|
||||||
* can represent.
|
|
||||||
*/
|
|
||||||
enum sdmmc_card_type {
|
|
||||||
MMC_CARD_EMMC,
|
|
||||||
MMC_CARD_MMC,
|
|
||||||
MMC_CARD_SD,
|
|
||||||
MMC_CARD_CART,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specification versions for SD/MMC cards.
|
|
||||||
*/
|
|
||||||
enum sdmmc_spec_version {
|
|
||||||
|
|
||||||
/* MMC card versions */
|
|
||||||
MMC_VERSION_4 = 0,
|
|
||||||
|
|
||||||
/* SD card versions */
|
|
||||||
SD_VERSION_1_0 = 0,
|
|
||||||
SD_VERSION_1_1 = 1,
|
|
||||||
SD_VERSION_2_0 = 2,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SDMMC controllers
|
|
||||||
*/
|
|
||||||
enum sdmmc_controller {
|
|
||||||
SWITCH_MICROSD = 0,
|
|
||||||
SWITCH_EMMC = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write permission modes for SD cards.
|
|
||||||
*/
|
|
||||||
enum sdmmc_write_permission {
|
|
||||||
SDMMC_WRITE_DISABLED,
|
|
||||||
SDMMC_WRITE_ENABLED,
|
|
||||||
|
|
||||||
/* use this with the utmost caution so you don't wind up with a brick */
|
|
||||||
SDMMC_WRITE_ENABLED_INCLUDING_EMMC,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Methods by which we can touch registers accessed via.
|
|
||||||
* CMD_SWITCH_MODE.
|
|
||||||
*/
|
|
||||||
enum sdmmc_switch_access_mode {
|
|
||||||
|
|
||||||
/* Normal commands */
|
|
||||||
MMC_SWITCH_MODE_CMD_SET = 0,
|
|
||||||
MMC_SWITCH_MODE_SET_BITS = 1,
|
|
||||||
MMC_SWITCH_MODE_CLEAR_BITS = 2,
|
|
||||||
MMC_SWITCH_MODE_WRITE_BYTE = 3,
|
|
||||||
|
|
||||||
/* EXTCSD access */
|
|
||||||
MMC_SWITCH_EXTCSD_NORMAL = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Offsets into the SWITCH_MODE argument.
|
|
||||||
*/
|
|
||||||
enum sdmmc_switch_argument_offsets {
|
|
||||||
MMC_SWITCH_VALUE_SHIFT = 8,
|
|
||||||
MMC_SWITCH_FIELD_SHIFT = 16,
|
|
||||||
MMC_SWITCH_ACCESS_MODE_SHIFT = 24,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bus speeds possible for an SDMMC controller.
|
|
||||||
*/
|
|
||||||
enum sdmmc_bus_speed {
|
|
||||||
/* SD card speeds */
|
|
||||||
SDMMC_SPEED_SDR12 = 0,
|
|
||||||
SDMMC_SPEED_SDR25 = 1,
|
|
||||||
SDMMC_SPEED_SDR50 = 2,
|
|
||||||
SDMMC_SPEED_SDR104 = 3,
|
|
||||||
SDMMC_SPEED_DDR50 = 4,
|
|
||||||
|
|
||||||
/* Other speed: non-spec-compliant value used for e.g. HS400 */
|
|
||||||
SDMMC_SPEED_OTHER = 5,
|
|
||||||
|
|
||||||
/* eMMC card speeds */
|
|
||||||
/* note: to avoid an enum clash, we add ten to these */
|
|
||||||
SDMMC_SPEED_HS26 = 10 ,
|
|
||||||
SDMMC_SPEED_HS52 = 11 ,
|
|
||||||
SDMMC_SPEED_HS200 = 12 ,
|
|
||||||
SDMMC_SPEED_HS400 = 13 ,
|
|
||||||
|
|
||||||
/* special speeds */
|
|
||||||
SDMMC_SPEED_INIT = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Primary data structure describing a Fusée MMC driver.
|
|
||||||
*/
|
|
||||||
struct mmc {
|
|
||||||
enum sdmmc_controller controller;
|
|
||||||
|
|
||||||
/* Controller properties */
|
|
||||||
const char *name;
|
|
||||||
bool use_dma;
|
|
||||||
bool allow_voltage_switching;
|
|
||||||
unsigned int timeout;
|
|
||||||
enum tegra_named_gpio card_detect_gpio;
|
|
||||||
enum sdmmc_write_permission write_enable;
|
|
||||||
|
|
||||||
/* Per-controller operations. */
|
|
||||||
int (*set_up_clock_and_io)(struct mmc *mmc);
|
|
||||||
void (*configure_clock)(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor);
|
|
||||||
int (*enable_supplies)(struct mmc *mmc);
|
|
||||||
int (*switch_to_low_voltage)(struct mmc *mmc);
|
|
||||||
bool (*card_present)(struct mmc *mmc);
|
|
||||||
|
|
||||||
/* Per-card-type operations */
|
|
||||||
int (*card_init)(struct mmc *mmc);
|
|
||||||
int (*establish_relative_address)(struct mmc *mmc);
|
|
||||||
int (*switch_mode)(struct mmc *mmc, int a, int b, int c, uint32_t timeout, void *response);
|
|
||||||
int (*switch_bus_width)(struct mmc *mmc, enum sdmmc_bus_width width);
|
|
||||||
int (*optimize_speed)(struct mmc *mmc);
|
|
||||||
int (*card_switch_bus_speed)(struct mmc *mmc, enum sdmmc_bus_speed speed);
|
|
||||||
|
|
||||||
/* Card properties */
|
|
||||||
enum sdmmc_card_type card_type;
|
|
||||||
uint32_t mmc_card_type;
|
|
||||||
|
|
||||||
uint8_t cid[15];
|
|
||||||
uint32_t relative_address;
|
|
||||||
uint8_t partitioned;
|
|
||||||
enum sdmmc_spec_version spec_version;
|
|
||||||
enum sdmmc_bus_width max_bus_width;
|
|
||||||
enum sdmmc_bus_voltage operating_voltage;
|
|
||||||
enum sdmmc_bus_speed operating_speed;
|
|
||||||
|
|
||||||
uint8_t partition_support;
|
|
||||||
uint8_t partition_config;
|
|
||||||
uint8_t partition_attribute;
|
|
||||||
uint32_t partition_switch_time;
|
|
||||||
|
|
||||||
uint8_t read_block_order;
|
|
||||||
uint8_t write_block_order;
|
|
||||||
uint8_t tuning_block_order;
|
|
||||||
bool uses_block_addressing;
|
|
||||||
|
|
||||||
/* Current operation status flags */
|
|
||||||
uint32_t active_data_buffer;
|
|
||||||
|
|
||||||
/* Pointers to hardware structures */
|
|
||||||
volatile struct tegra_sdmmc *regs;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Primary data structure describing a Fusée MMC driver.
|
|
||||||
*/
|
|
||||||
struct mmc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parititions supported by the Switch eMMC.
|
|
||||||
*/
|
|
||||||
enum sdmmc_partition {
|
|
||||||
SDMMC_PARTITION_USER = 0,
|
|
||||||
SDMMC_PARTITION_BOOT0 = 1,
|
|
||||||
SDMMC_PARTITION_BOOT1 = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the current SDMMC debugging loglevel.
|
|
||||||
*
|
|
||||||
* @param loglevel Current log level. A higher value prints more logs.
|
|
||||||
* @return The loglevel prior to when this was applied, for easy restoration.
|
|
||||||
*/
|
|
||||||
int sdmmc_set_loglevel(int loglevel);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up a new SDMMC driver.
|
|
||||||
*
|
|
||||||
* @param mmc The SDMMC structure to be initiailized with the device state.
|
|
||||||
* @param controler The controller description to be used; usually SWITCH_EMMC
|
|
||||||
* or SWITCH_MICROSD.
|
|
||||||
* @param allow_voltage_switching True if we should allow voltage switching,
|
|
||||||
* which may not make sense if we're about to chainload to another component without
|
|
||||||
* preseving the overall structure.
|
|
||||||
*/
|
|
||||||
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports a SDMMC driver struct from another program. This mainly intended for stage2,
|
|
||||||
* so that it can reuse stage1's SDMMC struct instance(s).
|
|
||||||
*
|
|
||||||
* @param mmc The SDMMC structure to be imported.
|
|
||||||
*/
|
|
||||||
int sdmmc_import_struct(struct mmc *mmc);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects the active MMC partition. Can be used to select
|
|
||||||
* boot partitions for access. Affects all operations going forward.
|
|
||||||
*
|
|
||||||
* @param mmc The MMC controller whose card is to be used.
|
|
||||||
* @param partition The partition number to be selected.
|
|
||||||
*
|
|
||||||
* @return 0 on success, or an error code on failure.
|
|
||||||
*/
|
|
||||||
int sdmmc_select_partition(struct mmc *mmc, enum sdmmc_partition partition);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a sector or sectors from a given SD card.
|
|
||||||
*
|
|
||||||
* @param mmc The MMC device to work with.
|
|
||||||
* @param buffer The output buffer to target.
|
|
||||||
* @param sector The sector number to read.
|
|
||||||
* @param count The number of sectors to read.
|
|
||||||
*/
|
|
||||||
int sdmmc_read(struct mmc *mmc, void *buffer, uint32_t sector, unsigned int count);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases the SDMMC write lockout, enabling access to the card.
|
|
||||||
* Note that by default, setting this to WRITE_ENABLED will not allow access to eMMC.
|
|
||||||
* Check the source for a third constant that can be used to enable eMMC writes.
|
|
||||||
*
|
|
||||||
* @param perms The permissions to apply-- typically WRITE_DISABLED or WRITE_ENABLED.
|
|
||||||
*/
|
|
||||||
void sdmmc_set_write_enable(struct mmc *mmc, enum sdmmc_write_permission perms);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a sector or sectors to a given SD/MMC card.
|
|
||||||
*
|
|
||||||
* @param mmc The MMC device to work with.
|
|
||||||
* @param buffer The input buffer to write.
|
|
||||||
* @param block The sector number to write from.
|
|
||||||
* @param count The number of sectors to write.
|
|
||||||
*
|
|
||||||
* @return 0 on success, or an error code on failure.
|
|
||||||
*/
|
|
||||||
int sdmmc_write(struct mmc *mmc, const void *buffer, uint32_t block, unsigned int count);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks to see whether an SD card is present.
|
|
||||||
*
|
|
||||||
* @mmc mmc The controller with which to check for card presence.
|
|
||||||
* @return true iff a card is present
|
|
||||||
*/
|
|
||||||
bool sdmmc_card_present(struct mmc *mmc);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints out all of the tegra_mmc struct fields
|
|
||||||
*
|
|
||||||
* @mmc mmc The controller with which to dump registers.
|
|
||||||
*/
|
|
||||||
void sdmmc_dump_regs(struct mmc *mmc);
|
|
||||||
|
|
||||||
#endif
|
|
448
fusee/fusee-secondary/src/sdmmc/mmc.h
Normal file
448
fusee/fusee-secondary/src/sdmmc/mmc.h
Normal file
|
@ -0,0 +1,448 @@
|
||||||
|
/*
|
||||||
|
* Header for MultiMediaCard (MMC)
|
||||||
|
*
|
||||||
|
* Copyright 2002 Hewlett-Packard Company
|
||||||
|
*
|
||||||
|
* Use consistent with the GNU GPL is permitted,
|
||||||
|
* provided that this copyright notice is
|
||||||
|
* preserved in its entirety in all copies and derived works.
|
||||||
|
*
|
||||||
|
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
|
||||||
|
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
|
||||||
|
* FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* Many thanks to Alessandro Rubini and Jonathan Corbet!
|
||||||
|
*
|
||||||
|
* Based strongly on code by:
|
||||||
|
*
|
||||||
|
* Author: Yong-iL Joh <tolkien@mizi.com>
|
||||||
|
*
|
||||||
|
* Author: Andrew Christian
|
||||||
|
* 15 May 2002
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LINUX_MMC_MMC_H
|
||||||
|
#define LINUX_MMC_MMC_H
|
||||||
|
|
||||||
|
/* Standard MMC commands (4.1) type argument response */
|
||||||
|
/* class 1 */
|
||||||
|
#define MMC_GO_IDLE_STATE 0 /* bc */
|
||||||
|
#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
|
||||||
|
#define MMC_ALL_SEND_CID 2 /* bcr R2 */
|
||||||
|
#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
|
||||||
|
#define MMC_SET_DSR 4 /* bc [31:16] RCA */
|
||||||
|
#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */
|
||||||
|
#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
|
||||||
|
#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
|
||||||
|
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
|
||||||
|
#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
|
||||||
|
#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
|
||||||
|
#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
|
||||||
|
#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
|
||||||
|
#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
|
||||||
|
#define MMC_BUS_TEST_R 14 /* adtc R1 */
|
||||||
|
#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
|
||||||
|
#define MMC_BUS_TEST_W 19 /* adtc R1 */
|
||||||
|
#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */
|
||||||
|
#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */
|
||||||
|
|
||||||
|
/* class 2 */
|
||||||
|
#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
|
||||||
|
#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
|
||||||
|
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
|
||||||
|
#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */
|
||||||
|
#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */
|
||||||
|
|
||||||
|
/* class 3 */
|
||||||
|
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
|
||||||
|
|
||||||
|
/* class 4 */
|
||||||
|
#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
|
||||||
|
#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
|
||||||
|
#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
|
||||||
|
#define MMC_PROGRAM_CID 26 /* adtc R1 */
|
||||||
|
#define MMC_PROGRAM_CSD 27 /* adtc R1 */
|
||||||
|
|
||||||
|
/* class 6 */
|
||||||
|
#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
|
||||||
|
#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
|
||||||
|
#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
|
||||||
|
|
||||||
|
/* class 5 */
|
||||||
|
#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
|
||||||
|
#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
|
||||||
|
#define MMC_ERASE 38 /* ac R1b */
|
||||||
|
|
||||||
|
/* class 9 */
|
||||||
|
#define MMC_FAST_IO 39 /* ac <Complex> R4 */
|
||||||
|
#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
|
||||||
|
|
||||||
|
/* class 7 */
|
||||||
|
#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
|
||||||
|
|
||||||
|
/* class 8 */
|
||||||
|
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
||||||
|
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
||||||
|
|
||||||
|
/* class 11 */
|
||||||
|
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
|
||||||
|
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
|
||||||
|
#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */
|
||||||
|
#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */
|
||||||
|
#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MMC_SWITCH argument format:
|
||||||
|
*
|
||||||
|
* [31:26] Always 0
|
||||||
|
* [25:24] Access Mode
|
||||||
|
* [23:16] Location of target Byte in EXT_CSD
|
||||||
|
* [15:08] Value Byte
|
||||||
|
* [07:03] Always 0
|
||||||
|
* [02:00] Command Set
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
MMC status in R1, for native mode (SPI bits are different)
|
||||||
|
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 must poll
|
||||||
|
the card by sending status command in order to read these bits.
|
||||||
|
Clear condition
|
||||||
|
a : according to the card state
|
||||||
|
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 R1_OUT_OF_RANGE (1 << 31) /* er, c */
|
||||||
|
#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
|
||||||
|
#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
|
||||||
|
#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
|
||||||
|
#define R1_ERASE_PARAM (1 << 27) /* ex, c */
|
||||||
|
#define R1_WP_VIOLATION (1 << 26) /* erx, c */
|
||||||
|
#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
|
||||||
|
#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
|
||||||
|
#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
|
||||||
|
#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
|
||||||
|
#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
|
||||||
|
#define R1_CC_ERROR (1 << 20) /* erx, c */
|
||||||
|
#define R1_ERROR (1 << 19) /* erx, c */
|
||||||
|
#define R1_UNDERRUN (1 << 18) /* ex, c */
|
||||||
|
#define R1_OVERRUN (1 << 17) /* ex, c */
|
||||||
|
#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
|
||||||
|
#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
|
||||||
|
#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
|
||||||
|
#define R1_ERASE_RESET (1 << 13) /* sr, c */
|
||||||
|
#define R1_STATUS(x) (x & 0xFFFFE000)
|
||||||
|
#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
|
||||||
|
#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
|
||||||
|
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */
|
||||||
|
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */
|
||||||
|
#define R1_APP_CMD (1 << 5) /* sr, c */
|
||||||
|
|
||||||
|
#define R1_STATE_IDLE 0
|
||||||
|
#define R1_STATE_READY 1
|
||||||
|
#define R1_STATE_IDENT 2
|
||||||
|
#define R1_STATE_STBY 3
|
||||||
|
#define R1_STATE_TRAN 4
|
||||||
|
#define R1_STATE_DATA 5
|
||||||
|
#define R1_STATE_RCV 6
|
||||||
|
#define R1_STATE_PRG 7
|
||||||
|
#define R1_STATE_DIS 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
|
||||||
|
* R1 is the low order byte; R2 is the next highest byte, when present.
|
||||||
|
*/
|
||||||
|
#define R1_SPI_IDLE (1 << 0)
|
||||||
|
#define R1_SPI_ERASE_RESET (1 << 1)
|
||||||
|
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
|
||||||
|
#define R1_SPI_COM_CRC (1 << 3)
|
||||||
|
#define R1_SPI_ERASE_SEQ (1 << 4)
|
||||||
|
#define R1_SPI_ADDRESS (1 << 5)
|
||||||
|
#define R1_SPI_PARAMETER (1 << 6)
|
||||||
|
/* R1 bit 7 is always zero */
|
||||||
|
#define R2_SPI_CARD_LOCKED (1 << 8)
|
||||||
|
#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */
|
||||||
|
#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP
|
||||||
|
#define R2_SPI_ERROR (1 << 10)
|
||||||
|
#define R2_SPI_CC_ERROR (1 << 11)
|
||||||
|
#define R2_SPI_CARD_ECC_ERROR (1 << 12)
|
||||||
|
#define R2_SPI_WP_VIOLATION (1 << 13)
|
||||||
|
#define R2_SPI_ERASE_PARAM (1 << 14)
|
||||||
|
#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */
|
||||||
|
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OCR bits are mostly in host.h
|
||||||
|
*/
|
||||||
|
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
|
||||||
|
#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
|
||||||
|
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
|
||||||
|
#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
|
||||||
|
#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
|
||||||
|
#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
|
||||||
|
#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
|
||||||
|
#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
|
||||||
|
#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
|
||||||
|
#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
|
||||||
|
#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
|
||||||
|
#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
|
||||||
|
#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
|
||||||
|
#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
|
||||||
|
#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
|
||||||
|
#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
|
||||||
|
#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
|
||||||
|
#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Card Command Classes (CCC)
|
||||||
|
*/
|
||||||
|
#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
|
||||||
|
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
|
||||||
|
/* (and for SPI, CMD58,59) */
|
||||||
|
#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
|
||||||
|
/* (CMD11) */
|
||||||
|
#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
|
||||||
|
/* (CMD16,17,18) */
|
||||||
|
#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
|
||||||
|
/* (CMD20) */
|
||||||
|
#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
|
||||||
|
/* (CMD16,24,25,26,27) */
|
||||||
|
#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
|
||||||
|
/* (CMD32,33,34,35,36,37,38,39) */
|
||||||
|
#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
|
||||||
|
/* (CMD28,29,30) */
|
||||||
|
#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
|
||||||
|
/* (CMD16,CMD42) */
|
||||||
|
#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
|
||||||
|
/* (CMD55,56,57,ACMD*) */
|
||||||
|
#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
|
||||||
|
/* (CMD5,39,40,52,53) */
|
||||||
|
#define CCC_SWITCH (1<<10) /* (10) High speed switch */
|
||||||
|
/* (CMD6,34,35,36,37,50) */
|
||||||
|
/* (11) Reserved */
|
||||||
|
/* (CMD?) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CSD field definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
|
||||||
|
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
|
||||||
|
#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
|
||||||
|
#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
|
||||||
|
|
||||||
|
#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
|
||||||
|
#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
|
||||||
|
#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
|
||||||
|
#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
|
||||||
|
#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EXT_CSD fields
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */
|
||||||
|
#define EXT_CSD_FLUSH_CACHE 32 /* W */
|
||||||
|
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
|
||||||
|
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
|
||||||
|
#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */
|
||||||
|
#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */
|
||||||
|
#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */
|
||||||
|
#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */
|
||||||
|
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
|
||||||
|
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
||||||
|
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
|
||||||
|
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
|
||||||
|
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
|
||||||
|
#define EXT_CSD_HPI_MGMT 161 /* R/W */
|
||||||
|
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
||||||
|
#define EXT_CSD_BKOPS_EN 163 /* R/W */
|
||||||
|
#define EXT_CSD_BKOPS_START 164 /* W */
|
||||||
|
#define EXT_CSD_SANITIZE_START 165 /* W */
|
||||||
|
#define EXT_CSD_WR_REL_PARAM 166 /* RO */
|
||||||
|
#define EXT_CSD_RPMB_MULT 168 /* RO */
|
||||||
|
#define EXT_CSD_FW_CONFIG 169 /* R/W */
|
||||||
|
#define EXT_CSD_BOOT_WP 173 /* R/W */
|
||||||
|
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
|
||||||
|
#define EXT_CSD_PART_CONFIG 179 /* R/W */
|
||||||
|
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
|
||||||
|
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
|
||||||
|
#define EXT_CSD_STROBE_SUPPORT 184 /* RO */
|
||||||
|
#define EXT_CSD_HS_TIMING 185 /* R/W */
|
||||||
|
#define EXT_CSD_POWER_CLASS 187 /* R/W */
|
||||||
|
#define EXT_CSD_REV 192 /* RO */
|
||||||
|
#define EXT_CSD_STRUCTURE 194 /* RO */
|
||||||
|
#define EXT_CSD_CARD_TYPE 196 /* RO */
|
||||||
|
#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */
|
||||||
|
#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */
|
||||||
|
#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */
|
||||||
|
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
|
||||||
|
#define EXT_CSD_PWR_CL_26_195 201 /* RO */
|
||||||
|
#define EXT_CSD_PWR_CL_52_360 202 /* RO */
|
||||||
|
#define EXT_CSD_PWR_CL_26_360 203 /* RO */
|
||||||
|
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
|
||||||
|
#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
|
||||||
|
#define EXT_CSD_REL_WR_SEC_C 222 /* RO */
|
||||||
|
#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */
|
||||||
|
#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
|
||||||
|
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
|
||||||
|
#define EXT_CSD_BOOT_MULT 226 /* RO */
|
||||||
|
#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
|
||||||
|
#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
|
||||||
|
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
|
||||||
|
#define EXT_CSD_TRIM_MULT 232 /* RO */
|
||||||
|
#define EXT_CSD_PWR_CL_200_195 236 /* RO */
|
||||||
|
#define EXT_CSD_PWR_CL_200_360 237 /* RO */
|
||||||
|
#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */
|
||||||
|
#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */
|
||||||
|
#define EXT_CSD_BKOPS_STATUS 246 /* RO */
|
||||||
|
#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
|
||||||
|
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
|
||||||
|
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
|
||||||
|
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
|
||||||
|
#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */
|
||||||
|
#define EXT_CSD_PRE_EOL_INFO 267 /* RO */
|
||||||
|
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */
|
||||||
|
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */
|
||||||
|
#define EXT_CSD_CMDQ_DEPTH 307 /* RO */
|
||||||
|
#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */
|
||||||
|
#define EXT_CSD_SUPPORTED_MODE 493 /* RO */
|
||||||
|
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
|
||||||
|
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
|
||||||
|
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
|
||||||
|
#define EXT_CSD_MAX_PACKED_READS 501 /* RO */
|
||||||
|
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
|
||||||
|
#define EXT_CSD_HPI_FEATURES 503 /* RO */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EXT_CSD field definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EXT_CSD_WR_REL_PARAM_EN (1<<2)
|
||||||
|
|
||||||
|
#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40)
|
||||||
|
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10)
|
||||||
|
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04)
|
||||||
|
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01)
|
||||||
|
|
||||||
|
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
|
||||||
|
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
|
||||||
|
#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3)
|
||||||
|
#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
|
||||||
|
|
||||||
|
#define EXT_CSD_PART_SETTING_COMPLETED (0x1)
|
||||||
|
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
|
||||||
|
|
||||||
|
#define EXT_CSD_CMD_SET_NORMAL (1<<0)
|
||||||
|
#define EXT_CSD_CMD_SET_SECURE (1<<1)
|
||||||
|
#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
|
||||||
|
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \
|
||||||
|
EXT_CSD_CARD_TYPE_HS_52)
|
||||||
|
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
|
||||||
|
/* DDR mode @1.8V or 3V I/O */
|
||||||
|
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
|
||||||
|
/* DDR mode @1.2V I/O */
|
||||||
|
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
|
||||||
|
| EXT_CSD_CARD_TYPE_DDR_1_2V)
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */
|
||||||
|
/* SDR mode @1.2V I/O */
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \
|
||||||
|
EXT_CSD_CARD_TYPE_HS200_1_2V)
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \
|
||||||
|
EXT_CSD_CARD_TYPE_HS400_1_2V)
|
||||||
|
#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */
|
||||||
|
|
||||||
|
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
|
||||||
|
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
|
||||||
|
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
|
||||||
|
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
|
||||||
|
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
|
||||||
|
#define EXT_CSD_BUS_WIDTH_STROBE BIT(7) /* Enhanced strobe mode */
|
||||||
|
|
||||||
|
#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */
|
||||||
|
#define EXT_CSD_TIMING_HS 1 /* High speed */
|
||||||
|
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
|
||||||
|
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
|
||||||
|
#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */
|
||||||
|
|
||||||
|
#define EXT_CSD_SEC_ER_EN BIT(0)
|
||||||
|
#define EXT_CSD_SEC_BD_BLK_EN BIT(2)
|
||||||
|
#define EXT_CSD_SEC_GB_CL_EN BIT(4)
|
||||||
|
#define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */
|
||||||
|
|
||||||
|
#define EXT_CSD_RST_N_EN_MASK 0x3
|
||||||
|
#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */
|
||||||
|
|
||||||
|
#define EXT_CSD_NO_POWER_NOTIFICATION 0
|
||||||
|
#define EXT_CSD_POWER_ON 1
|
||||||
|
#define EXT_CSD_POWER_OFF_SHORT 2
|
||||||
|
#define EXT_CSD_POWER_OFF_LONG 3
|
||||||
|
|
||||||
|
#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */
|
||||||
|
#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */
|
||||||
|
#define EXT_CSD_PWR_CL_8BIT_SHIFT 4
|
||||||
|
#define EXT_CSD_PWR_CL_4BIT_SHIFT 0
|
||||||
|
|
||||||
|
#define EXT_CSD_PACKED_EVENT_EN BIT(3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EXCEPTION_EVENT_STATUS field
|
||||||
|
*/
|
||||||
|
#define EXT_CSD_URGENT_BKOPS BIT(0)
|
||||||
|
#define EXT_CSD_DYNCAP_NEEDED BIT(1)
|
||||||
|
#define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2)
|
||||||
|
#define EXT_CSD_PACKED_FAILURE BIT(3)
|
||||||
|
|
||||||
|
#define EXT_CSD_PACKED_GENERIC_ERROR BIT(0)
|
||||||
|
#define EXT_CSD_PACKED_INDEXED_ERROR BIT(1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BKOPS status level
|
||||||
|
*/
|
||||||
|
#define EXT_CSD_BKOPS_LEVEL_2 0x2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BKOPS modes
|
||||||
|
*/
|
||||||
|
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01
|
||||||
|
#define EXT_CSD_AUTO_BKOPS_MASK 0x02
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command Queue
|
||||||
|
*/
|
||||||
|
#define EXT_CSD_CMDQ_MODE_ENABLED BIT(0)
|
||||||
|
#define EXT_CSD_CMDQ_DEPTH_MASK GENMASK(4, 0)
|
||||||
|
#define EXT_CSD_CMDQ_SUPPORTED BIT(0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MMC_SWITCH access modes
|
||||||
|
*/
|
||||||
|
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
|
||||||
|
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
|
||||||
|
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
|
||||||
|
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Erase/trim/discard
|
||||||
|
*/
|
||||||
|
#define MMC_ERASE_ARG 0x00000000
|
||||||
|
#define MMC_SECURE_ERASE_ARG 0x80000000
|
||||||
|
#define MMC_TRIM_ARG 0x00000001
|
||||||
|
#define MMC_DISCARD_ARG 0x00000003
|
||||||
|
#define MMC_SECURE_TRIM1_ARG 0x80000001
|
||||||
|
#define MMC_SECURE_TRIM2_ARG 0x80008000
|
||||||
|
#define MMC_SECURE_ARGS 0x80000000
|
||||||
|
#define MMC_TRIM_ARGS 0x00008001
|
||||||
|
|
||||||
|
#endif /* LINUX_MMC_MMC_H */
|
153
fusee/fusee-secondary/src/sdmmc/sd.h
Normal file
153
fusee/fusee-secondary/src/sdmmc/sd.h
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* include/linux/mmc/sd.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LINUX_MMC_SD_H
|
||||||
|
#define LINUX_MMC_SD_H
|
||||||
|
|
||||||
|
/* SD commands type argument response */
|
||||||
|
/* class 0 */
|
||||||
|
/* This is basically the same command as for MMC with some quirks. */
|
||||||
|
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||||
|
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||||
|
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
||||||
|
|
||||||
|
/* class 10 */
|
||||||
|
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
||||||
|
|
||||||
|
/* class 5 */
|
||||||
|
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
||||||
|
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
||||||
|
|
||||||
|
/* Application commands */
|
||||||
|
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||||
|
#define SD_APP_SD_STATUS 13 /* adtc R1 */
|
||||||
|
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
||||||
|
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||||
|
#define SD_APP_SET_CLR_CARD_DETECT 42 /* ac [0] set cd R1 */
|
||||||
|
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||||
|
|
||||||
|
/* OCR bit definitions */
|
||||||
|
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||||
|
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||||
|
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||||
|
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||||
|
#define SD_OCR_VDD_LOW (1 << 7) /* SD: Reserved for Low Voltage Range */
|
||||||
|
#define SD_OCR_VDD_20_21 (1 << 8)
|
||||||
|
#define SD_OCR_VDD_21_22 (1 << 9)
|
||||||
|
#define SD_OCR_VDD_22_23 (1 << 10)
|
||||||
|
#define SD_OCR_VDD_23_24 (1 << 11)
|
||||||
|
#define SD_OCR_VDD_24_25 (1 << 12)
|
||||||
|
#define SD_OCR_VDD_25_26 (1 << 13)
|
||||||
|
#define SD_OCR_VDD_26_27 (1 << 14)
|
||||||
|
#define SD_OCR_VDD_27_28 (1 << 15)
|
||||||
|
#define SD_OCR_VDD_28_29 (1 << 16)
|
||||||
|
#define SD_OCR_VDD_29_30 (1 << 17)
|
||||||
|
#define SD_OCR_VDD_30_31 (1 << 18)
|
||||||
|
#define SD_OCR_VDD_31_32 (1 << 19)
|
||||||
|
#define SD_OCR_VDD_32_33 (1 << 20)
|
||||||
|
#define SD_OCR_VDD_33_34 (1 << 21)
|
||||||
|
#define SD_OCR_VDD_34_35 (1 << 22)
|
||||||
|
#define SD_OCR_VDD_35_36 (1 << 23)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD_SWITCH argument format:
|
||||||
|
*
|
||||||
|
* [31] Check (0) or switch (1)
|
||||||
|
* [30:24] Reserved (0)
|
||||||
|
* [23:20] Function group 6
|
||||||
|
* [19:16] Function group 5
|
||||||
|
* [15:12] Function group 4
|
||||||
|
* [11:8] Function group 3
|
||||||
|
* [7:4] Function group 2
|
||||||
|
* [3:0] Function group 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD_SEND_IF_COND argument format:
|
||||||
|
*
|
||||||
|
* [31:12] Reserved (0)
|
||||||
|
* [11:8] Host Voltage Supply Flags
|
||||||
|
* [7:0] Check Pattern (0xAA)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SCR field definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SD_SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
|
||||||
|
#define SD_SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
|
||||||
|
#define SD_SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
|
||||||
|
#define SD_SCR_BUS_WIDTH_1 1
|
||||||
|
#define SD_SCR_BUS_WIDTH_4 4
|
||||||
|
#define SD_SCR_CMD20_SUPPORT 1
|
||||||
|
#define SD_SCR_CMD23_SUPPORT 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD bus widths
|
||||||
|
*/
|
||||||
|
#define SD_BUS_WIDTH_1 0
|
||||||
|
#define SD_BUS_WIDTH_4 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD bus speed modes
|
||||||
|
*/
|
||||||
|
#define UHS_SDR12_BUS_SPEED 0
|
||||||
|
#define HIGH_SPEED_BUS_SPEED 1
|
||||||
|
#define UHS_SDR25_BUS_SPEED 1
|
||||||
|
#define UHS_SDR50_BUS_SPEED 2
|
||||||
|
#define UHS_SDR104_BUS_SPEED 3
|
||||||
|
#define UHS_DDR50_BUS_SPEED 4
|
||||||
|
#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED)
|
||||||
|
#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED)
|
||||||
|
#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED)
|
||||||
|
#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED)
|
||||||
|
#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED)
|
||||||
|
#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD bus driver types
|
||||||
|
*/
|
||||||
|
#define SD_DRIVER_TYPE_B 0x01
|
||||||
|
#define SD_DRIVER_TYPE_A 0x02
|
||||||
|
#define SD_DRIVER_TYPE_C 0x04
|
||||||
|
#define SD_DRIVER_TYPE_D 0x08
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD bus current limits
|
||||||
|
*/
|
||||||
|
#define SD_SET_CURRENT_LIMIT_200 0
|
||||||
|
#define SD_SET_CURRENT_LIMIT_400 1
|
||||||
|
#define SD_SET_CURRENT_LIMIT_600 2
|
||||||
|
#define SD_SET_CURRENT_LIMIT_800 3
|
||||||
|
#define SD_SET_CURRENT_NO_CHANGE (-1)
|
||||||
|
#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200)
|
||||||
|
#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400)
|
||||||
|
#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600)
|
||||||
|
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD_SWITCH mode
|
||||||
|
*/
|
||||||
|
#define SD_SWITCH_CHECK 0
|
||||||
|
#define SD_SWITCH_SET 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD_SWITCH function groups
|
||||||
|
*/
|
||||||
|
#define SD_SWITCH_GRP_ACCESS 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD_SWITCH access modes
|
||||||
|
*/
|
||||||
|
#define SD_SWITCH_ACCESS_DEF 0
|
||||||
|
#define SD_SWITCH_ACCESS_HS 1
|
||||||
|
|
||||||
|
#endif /* LINUX_MMC_SD_H */
|
1528
fusee/fusee-secondary/src/sdmmc/sdmmc.c
Normal file
1528
fusee/fusee-secondary/src/sdmmc/sdmmc.c
Normal file
File diff suppressed because it is too large
Load diff
161
fusee/fusee-secondary/src/sdmmc/sdmmc.h
Normal file
161
fusee/fusee-secondary/src/sdmmc/sdmmc.h
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
#ifndef FUSEE_SDMMC_H
|
||||||
|
#define FUSEE_SDMMC_H
|
||||||
|
|
||||||
|
#include "sdmmc_core.h"
|
||||||
|
|
||||||
|
/* Structure for storing the MMC CID (adapted from Linux headers) */
|
||||||
|
typedef struct {
|
||||||
|
uint32_t manfid;
|
||||||
|
uint8_t prod_name[8];
|
||||||
|
uint8_t prv;
|
||||||
|
uint32_t serial;
|
||||||
|
uint16_t oemid;
|
||||||
|
uint16_t year;
|
||||||
|
uint8_t hwrev;
|
||||||
|
uint8_t fwrev;
|
||||||
|
uint8_t month;
|
||||||
|
} mmc_cid_t;
|
||||||
|
|
||||||
|
/* Structure for storing the MMC CSD (adapted from Linux headers) */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t structure;
|
||||||
|
uint8_t mmca_vsn;
|
||||||
|
uint16_t cmdclass;
|
||||||
|
uint16_t taac_clks;
|
||||||
|
uint32_t taac_ns;
|
||||||
|
uint32_t c_size;
|
||||||
|
uint32_t r2w_factor;
|
||||||
|
uint32_t max_dtr;
|
||||||
|
uint32_t erase_size; /* In sectors */
|
||||||
|
uint32_t read_blkbits;
|
||||||
|
uint32_t write_blkbits;
|
||||||
|
uint32_t capacity;
|
||||||
|
uint32_t read_partial:1,
|
||||||
|
read_misalign:1,
|
||||||
|
write_partial:1,
|
||||||
|
write_misalign:1,
|
||||||
|
dsr_imp:1;
|
||||||
|
} mmc_csd_t;
|
||||||
|
|
||||||
|
/* Structure for storing the MMC extended CSD (adapted from Linux headers) */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t rev;
|
||||||
|
uint8_t erase_group_def;
|
||||||
|
uint8_t sec_feature_support;
|
||||||
|
uint8_t rel_sectors;
|
||||||
|
uint8_t rel_param;
|
||||||
|
uint8_t part_config;
|
||||||
|
uint8_t cache_ctrl;
|
||||||
|
uint8_t rst_n_function;
|
||||||
|
uint8_t max_packed_writes;
|
||||||
|
uint8_t max_packed_reads;
|
||||||
|
uint8_t packed_event_en;
|
||||||
|
uint32_t part_time; /* Units: ms */
|
||||||
|
uint32_t sa_timeout; /* Units: 100ns */
|
||||||
|
uint32_t generic_cmd6_time; /* Units: 10ms */
|
||||||
|
uint32_t power_off_longtime; /* Units: ms */
|
||||||
|
uint8_t power_off_notification; /* state */
|
||||||
|
uint32_t hs_max_dtr;
|
||||||
|
uint32_t hs200_max_dtr;
|
||||||
|
uint32_t sectors;
|
||||||
|
uint32_t hc_erase_size; /* In sectors */
|
||||||
|
uint32_t hc_erase_timeout; /* In milliseconds */
|
||||||
|
uint32_t sec_trim_mult; /* Secure trim multiplier */
|
||||||
|
uint32_t sec_erase_mult; /* Secure erase multiplier */
|
||||||
|
uint32_t trim_timeout; /* In milliseconds */
|
||||||
|
uint32_t partition_setting_completed; /* enable bit */
|
||||||
|
uint64_t enhanced_area_offset; /* Units: Byte */
|
||||||
|
uint32_t enhanced_area_size; /* Units: KB */
|
||||||
|
uint32_t cache_size; /* Units: KB */
|
||||||
|
uint32_t hpi_en; /* HPI enablebit */
|
||||||
|
uint32_t hpi; /* HPI support bit */
|
||||||
|
uint32_t hpi_cmd; /* cmd used as HPI */
|
||||||
|
uint32_t bkops; /* background support bit */
|
||||||
|
uint32_t man_bkops_en; /* manual bkops enable bit */
|
||||||
|
uint32_t auto_bkops_en; /* auto bkops enable bit */
|
||||||
|
uint32_t data_sector_size; /* 512 bytes or 4KB */
|
||||||
|
uint32_t data_tag_unit_size; /* DATA TAG UNIT size */
|
||||||
|
uint32_t boot_ro_lock; /* ro lock support */
|
||||||
|
uint32_t boot_ro_lockable;
|
||||||
|
uint32_t ffu_capable; /* Firmware upgrade support */
|
||||||
|
uint32_t cmdq_en; /* Command Queue enabled */
|
||||||
|
uint32_t cmdq_support; /* Command Queue supported */
|
||||||
|
uint32_t cmdq_depth; /* Command Queue depth */
|
||||||
|
uint8_t fwrev[8]; /* FW version */
|
||||||
|
uint8_t raw_exception_status; /* 54 */
|
||||||
|
uint8_t raw_partition_support; /* 160 */
|
||||||
|
uint8_t raw_rpmb_size_mult; /* 168 */
|
||||||
|
uint8_t raw_erased_mem_count; /* 181 */
|
||||||
|
uint8_t strobe_support; /* 184 */
|
||||||
|
uint8_t raw_ext_csd_structure; /* 194 */
|
||||||
|
uint8_t raw_card_type; /* 196 */
|
||||||
|
uint8_t raw_driver_strength; /* 197 */
|
||||||
|
uint8_t out_of_int_time; /* 198 */
|
||||||
|
uint8_t raw_pwr_cl_52_195; /* 200 */
|
||||||
|
uint8_t raw_pwr_cl_26_195; /* 201 */
|
||||||
|
uint8_t raw_pwr_cl_52_360; /* 202 */
|
||||||
|
uint8_t raw_pwr_cl_26_360; /* 203 */
|
||||||
|
uint8_t raw_s_a_timeout; /* 217 */
|
||||||
|
uint8_t raw_hc_erase_gap_size; /* 221 */
|
||||||
|
uint8_t raw_erase_timeout_mult; /* 223 */
|
||||||
|
uint8_t raw_hc_erase_grp_size; /* 224 */
|
||||||
|
uint8_t raw_sec_trim_mult; /* 229 */
|
||||||
|
uint8_t raw_sec_erase_mult; /* 230 */
|
||||||
|
uint8_t raw_sec_feature_support; /* 231 */
|
||||||
|
uint8_t raw_trim_mult; /* 232 */
|
||||||
|
uint8_t raw_pwr_cl_200_195; /* 236 */
|
||||||
|
uint8_t raw_pwr_cl_200_360; /* 237 */
|
||||||
|
uint8_t raw_pwr_cl_ddr_52_195; /* 238 */
|
||||||
|
uint8_t raw_pwr_cl_ddr_52_360; /* 239 */
|
||||||
|
uint8_t raw_pwr_cl_ddr_200_360; /* 253 */
|
||||||
|
uint8_t raw_bkops_status; /* 246 */
|
||||||
|
uint8_t raw_sectors[4]; /* 212 - 4 bytes */
|
||||||
|
uint8_t pre_eol_info; /* 267 */
|
||||||
|
uint8_t device_life_time_est_typ_a; /* 268 */
|
||||||
|
uint8_t device_life_time_est_typ_b; /* 269 */
|
||||||
|
uint32_t feature_support;
|
||||||
|
} mmc_ext_csd_t;
|
||||||
|
|
||||||
|
/* Structure for storing the SD SCR (adapted from Linux headers) */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t sda_vsn;
|
||||||
|
uint8_t sda_spec3;
|
||||||
|
uint8_t bus_widths;
|
||||||
|
uint8_t cmds;
|
||||||
|
} sd_scr_t;
|
||||||
|
|
||||||
|
/* Structure for storing the SD SSR (adapted from Linux headers) */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t dat_bus_width;
|
||||||
|
uint8_t secured_mode;
|
||||||
|
uint16_t sd_card_type;
|
||||||
|
uint8_t speed_class;
|
||||||
|
uint8_t uhs_speed_grade;
|
||||||
|
uint8_t uhs_au_size;
|
||||||
|
uint8_t video_speed_class;
|
||||||
|
uint8_t app_perf_class;
|
||||||
|
} sd_ssr_t;
|
||||||
|
|
||||||
|
/* Structure describing a SDMMC device's context. */
|
||||||
|
typedef struct {
|
||||||
|
/* Underlying driver context. */
|
||||||
|
sdmmc_t *sdmmc;
|
||||||
|
|
||||||
|
bool is_180v;
|
||||||
|
bool is_block_sdhc;
|
||||||
|
uint32_t rca;
|
||||||
|
mmc_cid_t cid;
|
||||||
|
mmc_csd_t csd;
|
||||||
|
mmc_ext_csd_t ext_csd;
|
||||||
|
sd_scr_t scr;
|
||||||
|
sd_ssr_t ssr;
|
||||||
|
} sdmmc_device_t;
|
||||||
|
|
||||||
|
int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed);
|
||||||
|
int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed);
|
||||||
|
int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data);
|
||||||
|
int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data);
|
||||||
|
int sdmmc_device_finish(sdmmc_device_t *device);
|
||||||
|
int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition);
|
||||||
|
|
||||||
|
#endif
|
1987
fusee/fusee-secondary/src/sdmmc/sdmmc_core.c
Normal file
1987
fusee/fusee-secondary/src/sdmmc/sdmmc_core.c
Normal file
File diff suppressed because it is too large
Load diff
298
fusee/fusee-secondary/src/sdmmc/sdmmc_core.h
Normal file
298
fusee/fusee-secondary/src/sdmmc/sdmmc_core.h
Normal file
|
@ -0,0 +1,298 @@
|
||||||
|
#ifndef FUSEE_SDMMC_CORE_H
|
||||||
|
#define FUSEE_SDMMC_CORE_H
|
||||||
|
|
||||||
|
#include "sdmmc_tegra.h"
|
||||||
|
|
||||||
|
/* Bounce buffer */
|
||||||
|
#define SDMMC_BOUNCE_BUFFER_ADDRESS 0x90000000
|
||||||
|
|
||||||
|
/* Present state */
|
||||||
|
#define SDHCI_CMD_INHIBIT 0x00000001
|
||||||
|
#define SDHCI_DATA_INHIBIT 0x00000002
|
||||||
|
#define SDHCI_DOING_WRITE 0x00000100
|
||||||
|
#define SDHCI_DOING_READ 0x00000200
|
||||||
|
#define SDHCI_SPACE_AVAILABLE 0x00000400
|
||||||
|
#define SDHCI_DATA_AVAILABLE 0x00000800
|
||||||
|
#define SDHCI_CARD_PRESENT 0x00010000
|
||||||
|
#define SDHCI_WRITE_PROTECT 0x00080000
|
||||||
|
#define SDHCI_DATA_LVL_MASK 0x00F00000
|
||||||
|
#define SDHCI_DATA_LVL_SHIFT 20
|
||||||
|
#define SDHCI_DATA_0_LVL_MASK 0x00100000
|
||||||
|
#define SDHCI_CMD_LVL 0x01000000
|
||||||
|
|
||||||
|
/* SDHCI clock control */
|
||||||
|
#define SDHCI_DIVIDER_SHIFT 8
|
||||||
|
#define SDHCI_DIVIDER_HI_SHIFT 6
|
||||||
|
#define SDHCI_DIV_MASK 0xFF
|
||||||
|
#define SDHCI_DIV_MASK_LEN 8
|
||||||
|
#define SDHCI_DIV_HI_MASK 0x300
|
||||||
|
#define SDHCI_PROG_CLOCK_MODE 0x0020
|
||||||
|
#define SDHCI_CLOCK_CARD_EN 0x0004
|
||||||
|
#define SDHCI_CLOCK_INT_STABLE 0x0002
|
||||||
|
#define SDHCI_CLOCK_INT_EN 0x0001
|
||||||
|
|
||||||
|
/* SDHCI host control */
|
||||||
|
#define SDHCI_CTRL_LED 0x01
|
||||||
|
#define SDHCI_CTRL_4BITBUS 0x02
|
||||||
|
#define SDHCI_CTRL_HISPD 0x04
|
||||||
|
#define SDHCI_CTRL_DMA_MASK 0x18
|
||||||
|
#define SDHCI_CTRL_SDMA 0x00
|
||||||
|
#define SDHCI_CTRL_ADMA1 0x08
|
||||||
|
#define SDHCI_CTRL_ADMA32 0x10
|
||||||
|
#define SDHCI_CTRL_ADMA64 0x18
|
||||||
|
#define SDHCI_CTRL_8BITBUS 0x20
|
||||||
|
#define SDHCI_CTRL_CDTEST_INS 0x40
|
||||||
|
#define SDHCI_CTRL_CDTEST_EN 0x80
|
||||||
|
|
||||||
|
/* SDHCI host control 2 */
|
||||||
|
#define SDHCI_CTRL_UHS_MASK 0x0007
|
||||||
|
#define SDHCI_CTRL_UHS_SDR12 0x0000
|
||||||
|
#define SDHCI_CTRL_UHS_SDR25 0x0001
|
||||||
|
#define SDHCI_CTRL_UHS_SDR50 0x0002
|
||||||
|
#define SDHCI_CTRL_UHS_SDR104 0x0003
|
||||||
|
#define SDHCI_CTRL_UHS_DDR50 0x0004
|
||||||
|
#define SDHCI_CTRL_HS400 0x0005
|
||||||
|
#define SDHCI_CTRL_VDD_180 0x0008
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_A 0x0010
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_C 0x0020
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_D 0x0030
|
||||||
|
#define SDHCI_CTRL_EXEC_TUNING 0x0040
|
||||||
|
#define SDHCI_CTRL_TUNED_CLK 0x0080
|
||||||
|
#define SDHCI_UHS2_IF_EN 0x0100
|
||||||
|
#define SDHCI_HOST_VERSION_4_EN 0x1000
|
||||||
|
#define SDHCI_ADDRESSING_64BIT_EN 0x2000
|
||||||
|
#define SDHCI_ASYNC_INTR_EN 0x4000
|
||||||
|
#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
|
||||||
|
|
||||||
|
/* SDHCI capabilities */
|
||||||
|
#define SDHCI_CAN_DO_8BIT 0x00040000
|
||||||
|
#define SDHCI_CAN_DO_ADMA2 0x00080000
|
||||||
|
#define SDHCI_CAN_DO_ADMA1 0x00100000
|
||||||
|
#define SDHCI_CAN_DO_HISPD 0x00200000
|
||||||
|
#define SDHCI_CAN_DO_SDMA 0x00400000
|
||||||
|
#define SDHCI_CAN_VDD_330 0x01000000
|
||||||
|
#define SDHCI_CAN_VDD_300 0x02000000
|
||||||
|
#define SDHCI_CAN_VDD_180 0x04000000
|
||||||
|
#define SDHCI_CAN_64BIT 0x10000000
|
||||||
|
#define SDHCI_ASYNC_INTR 0x20000000
|
||||||
|
|
||||||
|
/* Vendor clock control */
|
||||||
|
#define SDMMC_CLOCK_TAP_MASK (0xFF << 16)
|
||||||
|
#define SDMMC_CLOCK_TAP_SDMMC1 (0x04 << 16)
|
||||||
|
#define SDMMC_CLOCK_TAP_SDMMC2 (0x00 << 16)
|
||||||
|
#define SDMMC_CLOCK_TAP_SDMMC3 (0x03 << 16)
|
||||||
|
#define SDMMC_CLOCK_TAP_SDMMC4 (0x00 << 16)
|
||||||
|
#define SDMMC_CLOCK_TRIM_MASK (0xFF << 24)
|
||||||
|
#define SDMMC_CLOCK_TRIM_SDMMC1 (0x02 << 24)
|
||||||
|
#define SDMMC_CLOCK_TRIM_SDMMC2 (0x08 << 24)
|
||||||
|
#define SDMMC_CLOCK_TRIM_SDMMC3 (0x03 << 24)
|
||||||
|
#define SDMMC_CLOCK_TRIM_SDMMC4 (0x08 << 24)
|
||||||
|
#define SDMMC_CLOCK_PADPIPE_CLKEN_OVERRIDE (1 << 3)
|
||||||
|
|
||||||
|
/* Autocal configuration */
|
||||||
|
#define SDMMC_AUTOCAL_PDPU_CONFIG_MASK 0x7F7F
|
||||||
|
#define SDMMC_AUTOCAL_PDPU_SDMMC1_1V8 0x7B7B
|
||||||
|
#define SDMMC_AUTOCAL_PDPU_SDMMC1_3V3 0x7D00
|
||||||
|
#define SDMMC_AUTOCAL_PDPU_SDMMC4_1V8 0x0505
|
||||||
|
#define SDMMC_AUTOCAL_START (1 << 31)
|
||||||
|
#define SDMMC_AUTOCAL_ENABLE (1 << 29)
|
||||||
|
|
||||||
|
/* Autocal status */
|
||||||
|
#define SDMMC_AUTOCAL_ACTIVE (1 << 31)
|
||||||
|
|
||||||
|
/* Vendor tuning control 0*/
|
||||||
|
#define SDMMC_VENDOR_TUNING_TRIES_MASK (0x7 << 13)
|
||||||
|
#define SDMMC_VENDOR_TUNING_TRIES_SHIFT 13
|
||||||
|
#define SDMMC_VENDOR_TUNING_MULTIPLIER_MASK (0x7F << 6)
|
||||||
|
#define SDMMC_VENDOR_TUNING_MULTIPLIER_UNITY (1 << 6)
|
||||||
|
#define SDMMC_VENDOR_TUNING_DIVIDER_MASK (0x7 << 3)
|
||||||
|
#define SDMMC_VENDOR_TUNING_SET_BY_HW (1 << 17)
|
||||||
|
|
||||||
|
/* Vendor tuning control 1*/
|
||||||
|
#define SDMMC_VENDOR_TUNING_STEP_SIZE_SDR50_DEFAULT (0 << 0)
|
||||||
|
#define SDMMC_VENDOR_TUNING_STEP_SIZE_SDR104_DEFAULT (0 << 4)
|
||||||
|
|
||||||
|
/* Vendor capability overrides */
|
||||||
|
#define SDMMC_VENDOR_CAPABILITY_DQS_TRIM_MASK (0x3F << 8)
|
||||||
|
#define SDMMC_VENDOR_CAPABILITY_DQS_TRIM_HS400 (0x11 << 8)
|
||||||
|
|
||||||
|
/* Timeouts */
|
||||||
|
#define SDMMC_AUTOCAL_TIMEOUT (10 * 1000)
|
||||||
|
#define SDMMC_TUNING_TIMEOUT (150 * 1000)
|
||||||
|
|
||||||
|
/* Command response flags */
|
||||||
|
#define SDMMC_RSP_PRESENT (1 << 0)
|
||||||
|
#define SDMMC_RSP_136 (1 << 1)
|
||||||
|
#define SDMMC_RSP_CRC (1 << 2)
|
||||||
|
#define SDMMC_RSP_BUSY (1 << 3)
|
||||||
|
#define SDMMC_RSP_OPCODE (1 << 4)
|
||||||
|
|
||||||
|
/* Command types */
|
||||||
|
#define SDMMC_CMD_MASK (3 << 5)
|
||||||
|
#define SDMMC_CMD_AC (0 << 5)
|
||||||
|
#define SDMMC_CMD_ADTC (1 << 5)
|
||||||
|
#define SDMMC_CMD_BC (2 << 5)
|
||||||
|
#define SDMMC_CMD_BCR (3 << 5)
|
||||||
|
|
||||||
|
/* SPI command response flags */
|
||||||
|
#define SDMMC_RSP_SPI_S1 (1 << 7)
|
||||||
|
#define SDMMC_RSP_SPI_S2 (1 << 8)
|
||||||
|
#define SDMMC_RSP_SPI_B4 (1 << 9)
|
||||||
|
#define SDMMC_RSP_SPI_BUSY (1 << 10)
|
||||||
|
|
||||||
|
/* Native response types for commands */
|
||||||
|
#define SDMMC_RSP_NONE (0)
|
||||||
|
#define SDMMC_RSP_R1 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE)
|
||||||
|
#define SDMMC_RSP_R1B (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE|SDMMC_RSP_BUSY)
|
||||||
|
#define SDMMC_RSP_R2 (SDMMC_RSP_PRESENT|SDMMC_RSP_136|SDMMC_RSP_CRC)
|
||||||
|
#define SDMMC_RSP_R3 (SDMMC_RSP_PRESENT)
|
||||||
|
#define SDMMC_RSP_R4 (SDMMC_RSP_PRESENT)
|
||||||
|
#define SDMMC_RSP_R5 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE)
|
||||||
|
#define SDMMC_RSP_R6 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE)
|
||||||
|
#define SDMMC_RSP_R7 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE)
|
||||||
|
#define SDMMC_RSP_R1_NO_CRC (SDMMC_RSP_PRESENT|SDMMC_RSP_OPCODE)
|
||||||
|
|
||||||
|
/* SPI response types for commands */
|
||||||
|
#define SDMMC_RSP_SPI_R1 (SDMMC_RSP_SPI_S1)
|
||||||
|
#define SDMMC_RSP_SPI_R1B (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_BUSY)
|
||||||
|
#define SDMMC_RSP_SPI_R2 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2)
|
||||||
|
#define SDMMC_RSP_SPI_R3 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4)
|
||||||
|
#define SDMMC_RSP_SPI_R4 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4)
|
||||||
|
#define SDMMC_RSP_SPI_R5 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2)
|
||||||
|
#define SDMMC_RSP_SPI_R7 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4)
|
||||||
|
|
||||||
|
/* Internal logging */
|
||||||
|
typedef enum {
|
||||||
|
SDMMC_LOG_NONE = 0,
|
||||||
|
SDMMC_LOG_ERROR = 1,
|
||||||
|
SDMMC_LOG_WARN = 2,
|
||||||
|
SDMMC_LOG_INFO = 3,
|
||||||
|
SDMMC_LOG_DEBUG = 4
|
||||||
|
} SdmmcLogLevel;
|
||||||
|
|
||||||
|
/* SDMMC controllers */
|
||||||
|
typedef enum {
|
||||||
|
SDMMC_1 = 0,
|
||||||
|
SDMMC_2 = 1,
|
||||||
|
SDMMC_3 = 2,
|
||||||
|
SDMMC_4 = 3
|
||||||
|
} SdmmcControllerNum;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SDMMC_PARTITION_INVALID = -1,
|
||||||
|
SDMMC_PARTITION_USER = 0,
|
||||||
|
SDMMC_PARTITION_BOOT0 = 1,
|
||||||
|
SDMMC_PARTITION_BOOT1 = 2,
|
||||||
|
SDMMC_PARTITION_RPMB = 3
|
||||||
|
} SdmmcPartitionNum;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SDMMC_VOLTAGE_NONE = 0,
|
||||||
|
SDMMC_VOLTAGE_1V8 = 1,
|
||||||
|
SDMMC_VOLTAGE_3V3 = 2
|
||||||
|
} SdmmcBusVoltage;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SDMMC_BUS_WIDTH_1BIT = 0,
|
||||||
|
SDMMC_BUS_WIDTH_4BIT = 1,
|
||||||
|
SDMMC_BUS_WIDTH_8BIT = 2
|
||||||
|
} SdmmcBusWidth;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SDMMC_SPEED_INIT_HS = 0,
|
||||||
|
SDMMC_SPEED_HS26 = 1,
|
||||||
|
SDMMC_SPEED_HS52 = 2,
|
||||||
|
SDMMC_SPEED_HS200 = 3,
|
||||||
|
SDMMC_SPEED_HS400 = 4,
|
||||||
|
SDMMC_SPEED_INIT_SDR = 5,
|
||||||
|
SDMMC_SPEED_UNK6 = 6,
|
||||||
|
SDMMC_SPEED_SDR25 = 7,
|
||||||
|
SDMMC_SPEED_SDR12 = 8,
|
||||||
|
SDMMC_SPEED_UNK9 = 9,
|
||||||
|
SDMMC_SPEED_SDR50 = 10,
|
||||||
|
SDMMC_SPEED_SDR104 = 11,
|
||||||
|
SDMMC_SPEED_UNK12 = 12,
|
||||||
|
SDMMC_SPEED_DDR50 = 13,
|
||||||
|
SDMMC_SPEED_UNK14 = 14,
|
||||||
|
} SdmmcBusSpeed;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SDMMC_CAR_DIVIDER_SDR12 = 31, // (16.5 * 2) - 2
|
||||||
|
SDMMC_CAR_DIVIDER_SDR25 = 15, // (8.5 * 2) - 2
|
||||||
|
SDMMC_CAR_DIVIDER_SDR50 = 7, // (4.5 * 2) - 2
|
||||||
|
SDMMC_CAR_DIVIDER_SDR104 = 2, // (2 * 2) - 2
|
||||||
|
SDMMC_CAR_DIVIDER_DDR50 = 18, // (5 * 2 * 2) - 2
|
||||||
|
SDMMC_CAR_DIVIDER_HS26 = 30, // (16 * 2) - 2
|
||||||
|
SDMMC_CAR_DIVIDER_HS52 = 14, // (8 * 2) - 2
|
||||||
|
SDMMC_CAR_DIVIDER_HS200 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0)
|
||||||
|
SDMMC_CAR_DIVIDER_HS400 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0)
|
||||||
|
} SdmmcCarDivider;
|
||||||
|
|
||||||
|
/* Structure for describing a SDMMC device. */
|
||||||
|
typedef struct {
|
||||||
|
/* Controller number */
|
||||||
|
SdmmcControllerNum controller;
|
||||||
|
|
||||||
|
/* Backing register space */
|
||||||
|
volatile tegra_sdmmc_t *regs;
|
||||||
|
|
||||||
|
/* Controller properties */
|
||||||
|
const char *name;
|
||||||
|
bool has_sd;
|
||||||
|
bool is_clk_running;
|
||||||
|
bool is_sd_clk_enabled;
|
||||||
|
bool is_tuning_tap_val_set;
|
||||||
|
bool use_adma;
|
||||||
|
uint32_t tap_val;
|
||||||
|
uint32_t internal_divider;
|
||||||
|
uint32_t resp[4];
|
||||||
|
uint32_t resp_auto_cmd12;
|
||||||
|
uint32_t next_dma_addr;
|
||||||
|
uint8_t* dma_bounce_buf;
|
||||||
|
SdmmcBusVoltage bus_voltage;
|
||||||
|
SdmmcBusWidth bus_width;
|
||||||
|
|
||||||
|
/* Per-controller operations. */
|
||||||
|
int (*sdmmc_config)();
|
||||||
|
} sdmmc_t;
|
||||||
|
|
||||||
|
/* Structure for describing a SDMMC command. */
|
||||||
|
typedef struct {
|
||||||
|
uint32_t opcode;
|
||||||
|
uint32_t arg;
|
||||||
|
uint32_t resp[4];
|
||||||
|
uint32_t flags; /* expected response type */
|
||||||
|
} sdmmc_command_t;
|
||||||
|
|
||||||
|
/* Structure for describing a SDMMC request. */
|
||||||
|
typedef struct {
|
||||||
|
void* data;
|
||||||
|
uint32_t blksz;
|
||||||
|
uint32_t num_blocks;
|
||||||
|
bool is_multi_block;
|
||||||
|
bool is_read;
|
||||||
|
bool is_auto_cmd12;
|
||||||
|
} sdmmc_request_t;
|
||||||
|
|
||||||
|
int sdmmc_init(sdmmc_t *sdmmc, SdmmcControllerNum controller, SdmmcBusVoltage bus_voltage, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed);
|
||||||
|
void sdmmc_finish(sdmmc_t *sdmmc);
|
||||||
|
int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed);
|
||||||
|
void sdmmc_select_bus_width(sdmmc_t *sdmmc, SdmmcBusWidth width);
|
||||||
|
void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage);
|
||||||
|
void sdmmc_adjust_sd_clock(sdmmc_t *sdmmc);
|
||||||
|
int sdmmc_switch_voltage(sdmmc_t *sdmmc);
|
||||||
|
void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc);
|
||||||
|
int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcode);
|
||||||
|
int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t *num_blocks_out);
|
||||||
|
int sdmmc_load_response(sdmmc_t *sdmmc, uint32_t flags, uint32_t *resp);
|
||||||
|
int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode);
|
||||||
|
void sdmmc_set_log_level(SdmmcLogLevel log_level);
|
||||||
|
void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...);
|
||||||
|
void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...);
|
||||||
|
void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...);
|
||||||
|
void sdmmc_debug(sdmmc_t *sdmmc, char *fmt, ...);
|
||||||
|
void sdmmc_dump_regs(sdmmc_t *sdmmc);
|
||||||
|
|
||||||
|
#endif
|
154
fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h
Normal file
154
fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
#ifndef FUSEE_SDMMC_TEGRA_H
|
||||||
|
#define FUSEE_SDMMC_TEGRA_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define TEGRA_MMC_PWRCTL_SD_BUS_POWER (1 << 0)
|
||||||
|
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 (5 << 1)
|
||||||
|
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 (6 << 1)
|
||||||
|
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 (7 << 1)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_HOSTCTL_DMASEL_MASK (3 << 3)
|
||||||
|
#define TEGRA_MMC_HOSTCTL_DMASEL_SDMA (0 << 3)
|
||||||
|
#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_32BIT (2 << 3)
|
||||||
|
#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_64BIT (3 << 3)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_TRNMOD_DMA_ENABLE (1 << 0)
|
||||||
|
#define TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE (1 << 1)
|
||||||
|
#define TEGRA_MMC_TRNMOD_AUTO_CMD12 (1 << 2)
|
||||||
|
#define TEGRA_MMC_TRNMOD_AUTO_CMD23 (1 << 3)
|
||||||
|
#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_WRITE (0 << 4)
|
||||||
|
#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ (1 << 4)
|
||||||
|
#define TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT (1 << 5)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_MASK (3 << 0)
|
||||||
|
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE (0 << 0)
|
||||||
|
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136 (1 << 0)
|
||||||
|
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48 (2 << 0)
|
||||||
|
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY (3 << 0)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_TRNMOD_CMD_CRC_CHECK (1 << 3)
|
||||||
|
#define TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK (1 << 4)
|
||||||
|
#define TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER (1 << 5)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD (1 << 0)
|
||||||
|
#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT (1 << 1)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE (1 << 0)
|
||||||
|
#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE (1 << 1)
|
||||||
|
#define TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE (1 << 2)
|
||||||
|
#define TEGRA_MMC_CLKCON_PROG_CLOCK_MODE (1 << 5)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_SHIFT 8
|
||||||
|
#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_MASK (0xff << 8)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_SWRST_SW_RESET_FOR_ALL (1 << 0)
|
||||||
|
#define TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE (1 << 1)
|
||||||
|
#define TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE (1 << 2)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_NORINTSTS_CMD_COMPLETE (1 << 0)
|
||||||
|
#define TEGRA_MMC_NORINTSTS_XFER_COMPLETE (1 << 1)
|
||||||
|
#define TEGRA_MMC_NORINTSTS_DMA_INTERRUPT (1 << 3)
|
||||||
|
#define TEGRA_MMC_NORINTSTS_ERR_INTERRUPT (1 << 15)
|
||||||
|
#define TEGRA_MMC_NORINTSTS_CMD_TIMEOUT (1 << 16)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE (1 << 0)
|
||||||
|
#define TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE (1 << 1)
|
||||||
|
#define TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT (1 << 3)
|
||||||
|
#define TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY (1 << 4)
|
||||||
|
#define TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY (1 << 5)
|
||||||
|
|
||||||
|
#define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE (1 << 1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* SDHCI standard registers */
|
||||||
|
uint32_t dma_address;
|
||||||
|
uint16_t block_size;
|
||||||
|
uint16_t block_count;
|
||||||
|
uint32_t argument;
|
||||||
|
uint16_t transfer_mode;
|
||||||
|
uint16_t command;
|
||||||
|
uint32_t response[0x4];
|
||||||
|
uint32_t buffer;
|
||||||
|
uint32_t present_state;
|
||||||
|
uint8_t host_control;
|
||||||
|
uint8_t power_control;
|
||||||
|
uint8_t block_gap_control;
|
||||||
|
uint8_t wake_up_control;
|
||||||
|
uint16_t clock_control;
|
||||||
|
uint8_t timeout_control;
|
||||||
|
uint8_t software_reset;
|
||||||
|
uint32_t int_status;
|
||||||
|
uint32_t int_enable;
|
||||||
|
uint32_t signal_enable;
|
||||||
|
uint16_t acmd12_err;
|
||||||
|
uint16_t host_control2;
|
||||||
|
uint32_t capabilities;
|
||||||
|
uint32_t capabilities_1;
|
||||||
|
uint32_t max_current;
|
||||||
|
uint32_t _0x4c;
|
||||||
|
uint16_t set_acmd12_error;
|
||||||
|
uint16_t set_int_error;
|
||||||
|
uint8_t adma_error;
|
||||||
|
uint8_t _0x56[0x3];
|
||||||
|
uint32_t adma_address;
|
||||||
|
uint32_t upper_adma_address;
|
||||||
|
uint16_t preset_for_init;
|
||||||
|
uint16_t preset_for_default;
|
||||||
|
uint16_t preset_for_high;
|
||||||
|
uint16_t preset_for_sdr12;
|
||||||
|
uint16_t preset_for_sdr25;
|
||||||
|
uint16_t preset_for_sdr50;
|
||||||
|
uint16_t preset_for_sdr104;
|
||||||
|
uint16_t preset_for_ddr50;
|
||||||
|
uint32_t _0x70[0x23];
|
||||||
|
uint16_t slot_int_status;
|
||||||
|
uint16_t host_version;
|
||||||
|
|
||||||
|
/* vendor specific registers */
|
||||||
|
uint32_t vendor_clock_cntrl;
|
||||||
|
uint32_t vendor_sys_sw_cntrl;
|
||||||
|
uint32_t vendor_err_intr_status;
|
||||||
|
uint32_t vendor_cap_overrides;
|
||||||
|
uint32_t vendor_boot_cntrl;
|
||||||
|
uint32_t vendor_boot_ack_timeout;
|
||||||
|
uint32_t vendor_boot_dat_timeout;
|
||||||
|
uint32_t vendor_debounce_count;
|
||||||
|
uint32_t vendor_misc_cntrl;
|
||||||
|
uint32_t max_current_override;
|
||||||
|
uint32_t max_current_override_hi;
|
||||||
|
uint32_t _0x12c[0x20];
|
||||||
|
uint32_t vendor_io_trim_cntrl;
|
||||||
|
|
||||||
|
/* start of sdmmc2/sdmmc4 only */
|
||||||
|
uint32_t vendor_dllcal_cfg;
|
||||||
|
uint32_t vendor_dll_ctrl0;
|
||||||
|
uint32_t vendor_dll_ctrl1;
|
||||||
|
uint32_t vendor_dllcal_cfg_sta;
|
||||||
|
/* end of sdmmc2/sdmmc4 only */
|
||||||
|
|
||||||
|
uint32_t vendor_tuning_cntrl0;
|
||||||
|
uint32_t vendor_tuning_cntrl1;
|
||||||
|
uint32_t vendor_tuning_status0;
|
||||||
|
uint32_t vendor_tuning_status1;
|
||||||
|
uint32_t vendor_clk_gate_hysteresis_count;
|
||||||
|
uint32_t vendor_preset_val0;
|
||||||
|
uint32_t vendor_preset_val1;
|
||||||
|
uint32_t vendor_preset_val2;
|
||||||
|
uint32_t sdmemcomppadctrl;
|
||||||
|
uint32_t auto_cal_config;
|
||||||
|
uint32_t auto_cal_interval;
|
||||||
|
uint32_t auto_cal_status;
|
||||||
|
uint32_t io_spare;
|
||||||
|
uint32_t sdmmca_mccif_fifoctrl;
|
||||||
|
uint32_t timeout_wcoal_sdmmca;
|
||||||
|
uint32_t _0x1fc;
|
||||||
|
} tegra_sdmmc_t;
|
||||||
|
|
||||||
|
static inline volatile tegra_sdmmc_t *sdmmc_get_regs(uint32_t idx)
|
||||||
|
{
|
||||||
|
return (volatile tegra_sdmmc_t *)(0x700B0000 + (idx * 0x200));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -438,7 +438,7 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys
|
||||||
SECURITY_ENGINE->CRYPTO_REG = keyslot_1 << 24;
|
SECURITY_ENGINE->CRYPTO_REG = keyslot_1 << 24;
|
||||||
}
|
}
|
||||||
SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1;
|
SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1;
|
||||||
trigger_se_blocking_op(OP_START, dst, size, dst, size);
|
trigger_se_blocking_op(OP_START, dst, size, src, size);
|
||||||
|
|
||||||
/* XOR. */
|
/* XOR. */
|
||||||
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size);
|
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#ifndef FUSEE_SE_H
|
#ifndef FUSEE_SE_H
|
||||||
#define FUSEE_SE_H
|
#define FUSEE_SE_H
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
|
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
|
||||||
|
@ -206,4 +205,4 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v
|
||||||
void se_initialize_rng(unsigned int keyslot);
|
void se_initialize_rng(unsigned int keyslot);
|
||||||
void se_generate_random(unsigned int keyslot, void *dst, size_t size);
|
void se_generate_random(unsigned int keyslot, void *dst, size_t size);
|
||||||
|
|
||||||
#endif /* EXOSPHERE_SE_H */
|
#endif
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define FUSEE_STAGE2_H
|
#define FUSEE_STAGE2_H
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "sdmmc.h"
|
#include "sdmmc/sdmmc.h"
|
||||||
|
|
||||||
/* TODO: Is there a more concise way to do this? */
|
/* TODO: Is there a more concise way to do this? */
|
||||||
#define STAGE2_ARGV_PROGRAM_PATH 0
|
#define STAGE2_ARGV_PROGRAM_PATH 0
|
||||||
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
//struct mmc sd_mmc;
|
|
||||||
bool display_initialized;
|
bool display_initialized;
|
||||||
char bct0[BCTO_MAX_SIZE];
|
char bct0[BCTO_MAX_SIZE];
|
||||||
} stage2_args_t;
|
} stage2_args_t;
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
/**
|
|
||||||
* Fusée power supply control code
|
|
||||||
* ~ktemkin
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lib/driver_utils.h"
|
|
||||||
#include "supplies.h"
|
|
||||||
|
|
||||||
// FIXME: replace hwinit with our own code
|
|
||||||
#include "hwinit/max7762x.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables a given power supply.
|
|
||||||
*
|
|
||||||
* @param supply The power domain on the Switch that is to be enabled.
|
|
||||||
* @param use_low_voltage If the supply supports multiple voltages, use the lower one.
|
|
||||||
* Some devices start in a high power mode, but an can be switched to a lower one.
|
|
||||||
* Set this to false unless you know what you're doing.
|
|
||||||
*/
|
|
||||||
void supply_enable(enum switch_power_supply supply, bool use_low_voltage)
|
|
||||||
{
|
|
||||||
uint32_t voltage = 0;
|
|
||||||
|
|
||||||
switch(supply) {
|
|
||||||
case SUPPLY_MICROSD:
|
|
||||||
voltage = use_low_voltage ? SUPPLY_MICROSD_LOW_VOLTAGE : SUPPLY_MICROSD_VOLTAGE;
|
|
||||||
|
|
||||||
max77620_regulator_set_voltage(SUPPLY_MICROSD_REGULATOR, voltage);
|
|
||||||
max77620_regulator_enable(SUPPLY_MICROSD_REGULATOR, true);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printk("ERROR: could not enable unknown supply %d!\n", supply);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
/**
|
|
||||||
* Fusée power supply control code
|
|
||||||
* ~ktemkin
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __FUSEE_SUPPLIES_H__
|
|
||||||
#define __FUSEE_SUPPLIES_H__
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
enum switch_power_supply {
|
|
||||||
SUPPLY_MICROSD,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum switch_power_constants {
|
|
||||||
|
|
||||||
/* MicroSD card */
|
|
||||||
SUPPLY_MICROSD_REGULATOR = 6,
|
|
||||||
SUPPLY_MICROSD_VOLTAGE = 3300000,
|
|
||||||
SUPPLY_MICROSD_LOW_VOLTAGE = 1800000,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables a given power supply.
|
|
||||||
*
|
|
||||||
* @param supply The power domain on the Switch that is to be enabled.
|
|
||||||
* @param use_low_voltage If the supply supports multiple voltages, use the lower one.
|
|
||||||
* Some devices start in a high power mode, but an can be switched to a lower one.
|
|
||||||
* Set this to false unless you know what you're doing.
|
|
||||||
*/
|
|
||||||
void supply_enable(enum switch_power_supply supply, bool use_low_voltage);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,12 +0,0 @@
|
||||||
#ifndef FUSEE_SWITCH_FS_H
|
|
||||||
#define FUSEE_SWITCH_FS_H
|
|
||||||
|
|
||||||
#include "fs_dev.h"
|
|
||||||
#include "raw_dev.h"
|
|
||||||
|
|
||||||
int switchfs_import_mmc_structs(void *sd, void *nand);
|
|
||||||
|
|
||||||
int switchfs_mount_all(void);
|
|
||||||
int switchfs_unmount_all(void);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -4,11 +4,14 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define TIMERS_BASE 0x60005000
|
#define TIMERS_BASE 0x60005000
|
||||||
|
|
||||||
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
|
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
|
||||||
|
|
||||||
#define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10)
|
#define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10)
|
||||||
|
|
||||||
|
#define RTC_BASE 0x7000E000
|
||||||
|
#define RTC_SECONDS MAKE_REG32(RTC_BASE + 0x08)
|
||||||
|
#define RTC_SHADOW_SECONDS MAKE_REG32(RTC_BASE + 0x0C)
|
||||||
|
#define RTC_MILLI_SECONDS MAKE_REG32(RTC_BASE + 0x10)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t CONFIG;
|
uint32_t CONFIG;
|
||||||
uint32_t STATUS;
|
uint32_t STATUS;
|
||||||
|
@ -22,24 +25,46 @@ typedef struct {
|
||||||
|
|
||||||
void wait(uint32_t microseconds);
|
void wait(uint32_t microseconds);
|
||||||
|
|
||||||
static inline uint32_t get_time(void) {
|
static inline uint32_t get_time_s(void) {
|
||||||
|
return RTC_SECONDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_time_ms(void) {
|
||||||
|
return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_time_us(void) {
|
||||||
return TIMERUS_CNTR_1US_0;
|
return TIMERUS_CNTR_1US_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time in microseconds.
|
||||||
|
*/
|
||||||
|
static inline uint32_t get_time(void) {
|
||||||
|
return get_time_us();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of microseconds that have passed since a given get_time().
|
* Returns the number of microseconds that have passed since a given get_time().
|
||||||
*/
|
*/
|
||||||
static inline uint32_t get_time_since(uint32_t base) {
|
static inline uint32_t get_time_since(uint32_t base) {
|
||||||
return get_time() - base;
|
return get_time_us() - base;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delays for a given number of microseconds.
|
* Delays for a given number of microseconds.
|
||||||
*/
|
*/
|
||||||
static inline void udelay(unsigned usecs)
|
static inline void udelay(uint32_t usecs) {
|
||||||
{
|
uint32_t start = get_time_us();
|
||||||
uint32_t start = get_time();
|
while (get_time_us() - start < usecs);
|
||||||
while (get_time() - start < usecs) ;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delays for a given number of milliseconds.
|
||||||
|
*/
|
||||||
|
static inline void mdelay(uint32_t msecs) {
|
||||||
|
uint32_t start = get_time_ms();
|
||||||
|
while (get_time_ms() - start < msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
||||||
|
|
Loading…
Reference in a new issue