Merge SD stuff into fusee-secondary. Switch diskio to single-sector reads temporarily

This commit is contained in:
Michael Scire 2018-05-04 11:47:05 -06:00
parent 299b020ecc
commit 4199be2460
42 changed files with 27485 additions and 172 deletions

View file

@ -51,7 +51,12 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */
)
{
return sdmmc_read(&sd_mmc, buff, sector, count) == 0 ? RES_OK : RES_ERROR;
for (unsigned int i = 0; i < count; i++) {
if (sdmmc_read(&sd_mmc, buff + 0x200 * i, sector + i, 1) != 0) {
return RES_ERROR;
}
}
return RES_OK;
}

View file

@ -18,6 +18,7 @@
/
/----------------------------------------------------------------------------*/
#pragma GCC diagnostic ignored "-Wunused-function"
#include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */

View file

@ -102,6 +102,7 @@ int main(void) {
args->lfb = (uint32_t *)lfb_base;
args->console_col = video_get_col();
args->console_row = video_get_row();
save_sd_state(&args->sd_mmc, &args->sd_fs);
/* Jump to Stage 2. */

View file

@ -10,6 +10,17 @@ FATFS sd_fs;
static int initialized_sd = 0;
static int mounted_sd = 0;
void save_sd_state(void **mmc, void **ff) {
*mmc = &sd_mmc;
*ff = &ff;
}
void resume_sd_state(void *mmc, void *ff) {
sd_mmc = *(struct mmc *)mmc;
sd_fs = *(FATFS *)ff;
initialized_sd = 1;
mounted_sd = 1;
}
int initialize_sd(void) {
if (initialized_sd) {
return 1;

View file

@ -2,6 +2,11 @@
#define FUSEE_SD_UTILS_H
#include "utils.h"
#include "sdmmc.h"
#include "ff.h"
void save_sd_state(void **mmc, void **ff);
void resume_sd_state(void *mmc, void *ff);
size_t read_sd_file(void *dst, size_t dst_size, const char *filename);

View file

@ -26,6 +26,8 @@ typedef struct {
uint32_t *lfb;
uint32_t console_row;
uint32_t console_col;
void *sd_mmc;
void *sd_fs;
} stage2_args_t;
const char *stage2_get_program_path(void);

View file

@ -26,7 +26,8 @@ CFLAGS = \
-fdata-sections \
-std=gnu11 \
-Werror \
-Wall
-Wall \
-fstrict-volatile-bitfields
LDFLAGS = -specs=linker.specs -g $(ARCH)

View file

@ -0,0 +1,14 @@
#ifndef __APB_MISC_H__
#define __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)
#endif

View file

@ -0,0 +1,295 @@
#ifndef __FUSEE_CLOCK_H___
#define __FUSEE_CLOCK_H__
#include "utils.h"
/**
* Struct definition yanked from u-boot.
*/
/* PLL registers - there are several PLLs in the clock controller */
struct clk_pll {
uint32_t pll_base; /* the control register */
/* pll_out[0] is output A control, pll_out[1] is output B control */
uint32_t pll_out[2];
uint32_t pll_misc; /* other misc things */
};
/* PLL registers - there are several PLLs in the clock controller */
struct clk_pll_simple {
uint32_t pll_base; /* the control register */
uint32_t pll_misc; /* other misc things */
};
struct clk_pllm {
uint32_t pllm_base; /* the control register */
uint32_t pllm_out; /* output control */
uint32_t pllm_misc1; /* misc1 */
uint32_t pllm_misc2; /* misc2 */
};
/*
* 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_FIRST = 0,
CLK_DIVIDER_UNITY = 0,
CLK_DIVIDER_32 = 32,
};
/**
* 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 = 19,
CLK_SOURCE_SDMMC4 = 21, /* 0x54 into the the main source block */
CLK_SOURCE_SDMMC_LEGACY = 0, /* first in block Y */
};
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
struct PACKED tegra_car {
uint32_t rst_src; /* _RST_SOURCE_0,0x00 */
uint32_t rst_dev_l;
uint32_t rst_dev_h;
uint32_t rst_dev_u;
uint32_t clk_out_dev_l;
uint32_t clk_out_dev_h;
uint32_t clk_out_dev_u;
uint32_t reserved0; /* reserved_0, 0x1C */
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0,0x24 */
uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */
uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0,0x2C */
uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */
uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */
uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0,0x38 */
uint32_t reserved1; /* reserved_1, 0x3C */
uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0,0x40 */
uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */
uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */
uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4C */
uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */
uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */
uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0,0x5C */
uint32_t reserved2[8]; /* reserved_2[8], 0x60-7C */
struct clk_pll pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */
/* PLLs from 0xe0 to 0xf4 */
struct clk_pll_simple pll_simple[TEGRA_CLK_SIMPLE_PLLS];
uint32_t reserved10; /* _reserved_10, 0xF8 */
uint32_t reserved11; /* _reserved_11, 0xFC */
uint32_t clk_src[TEGRA_CLK_SOURCES]; /*_I2S1_0... 0x100-1fc */
uint32_t reserved20[32]; /* _reserved_20, 0x200-27c */
uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */
uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */
uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */
uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */
uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */
uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */
uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */
uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */
uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */
uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */
uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */
uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */
uint32_t reserved21[17]; /* _reserved_21, 0x2b0-2f0 */
uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */
uint32_t reserved22[2]; /* _reserved_22, 0x2f8-2fc */
/* _RST_DEV_L/H/U_SET_0 0x300 ~ 0x314 */
uint32_t rst_dev_l_set;
uint32_t rst_dev_l_clr;
uint32_t rst_dev_h_set;
uint32_t rst_dev_h_clr;
uint32_t rst_dev_u_set;
uint32_t rst_dev_u_clr;
uint32_t reserved30[2]; /* _reserved_30, 0x318, 0x31c */
/* _CLK_ENB_L/H/U_CLR_0 0x320 ~ 0x334 */
uint32_t clk_enb_l_set;
uint32_t clk_enb_l_clr;
uint32_t clk_enb_h_set;
uint32_t clk_enb_h_clr;
uint32_t clk_enb_u_set;
uint32_t clk_enb_u_clr;
uint32_t reserved31[2]; /* _reserved_31, 0x338, 0x33c */
uint32_t cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */
uint32_t cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */
/* Additional (T30) registers */
uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
uint32_t reserved32[2]; /* _reserved_32, 0x350,0x354 */
uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */
uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
uint32_t reserved33[9]; /* _reserved_33, 0x38c-3ac */
uint32_t clk_src_v; /* 0x3B0-0x42C */
uint32_t clk_src_w; /* 0x3B0-0x42C */
/* _RST_DEV_V/W_SET_0 0x430 ~ 0x43c */
uint32_t rst_dev_v_set;
uint32_t rst_dev_v_clr;
uint32_t rst_dev_w_set;
uint32_t rst_dev_w_clr;
/* _CLK_ENB_V/W_CLR_0 0x440 ~ 0x44c */
uint32_t rst_clk_v_set;
uint32_t rst_clk_v_clr;
uint32_t rst_clk_w_set;
uint32_t rst_clk_w_clr;
/* Additional (T114+) registers */
uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */
uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */
uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */
uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45C */
uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */
uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */
uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */
uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46C */
uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */
uint32_t reserved40[1]; /* _reserved_40, 0x474 */
uint32_t intstatus; /* __INTSTATUS_0, 0x478 */
uint32_t intmask; /* __INTMASK_0, 0x47C */
uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */
uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */
uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */
uint32_t plle_aux; /* _PLLE_AUX_0, 0x48C */
uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */
uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */
uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */
uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49C */
uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4A0 */
uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4A4 */
uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4A8 */
uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4AC */
uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4B0 */
uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4B4 */
uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4B8 */
uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4BC */
uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4C0 */
uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4C4 */
uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4C8 */
uint32_t crs_reserved_50[7]; /* _reserved_50, 0x4CC-0x4E4 */
uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4E8 */
uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4EC */
uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4F0 */
uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4F4 */
uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4F8 */
uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4FC */
uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */
uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */
uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */
uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50C */
uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */
uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */
uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */
uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51C */
uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */
uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */
uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */
uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52C */
uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */
uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */
uint32_t reserved51[1]; /* _reserved_51, 0x538 */
uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53C */
uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */
uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */
uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */
uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54C */
uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */
uint32_t reserved52[1]; /* _reserved_52, 0x554 */
uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55C */
uint32_t _rsv32[4]; /* 0x560-0x56c */
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */
uint32_t _rsv32_1[7]; /* 0x574-58c */
struct clk_pll_simple plldp; /* _PLLDP_BASE, 0x590 _PLLDP_MISC */
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
/* Tegra124+ - skip to 0x600 here for new CLK_SOURCE_ regs */
uint32_t _rsrv32_2[25]; /* _0x59C - 0x5FC */
uint32_t clk_src_x[TEGRA_CLK_SOURCES_X]; /* XUSB, etc, 0x600-0x67C */
/* Tegra210 - skip to 0x694 here for new CLK_SOURCE_ regs */
uint32_t reserved61[5]; /* _reserved_61, 0x680 - 0x690 */
/*
* 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.
*/
uint32_t clk_src_y[TEGRA_CLK_SOURCES_Y]; /* SPARE1, etc, 0x694-0x6D8 */
};
/**
* Utility function that grabs the Tegra CAR registers.
*/
static inline struct tegra_car *car_get_regs(void)
{
return (struct tegra_car *)0x60006000UL;
}
#endif

View file

@ -0,0 +1,92 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include <string.h>
#include "diskio.h" /* FatFs lower layer API */
#include "sdmmc.h"
/* Global sd struct. */
extern struct mmc sd_mmc;
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
return 0;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
return 0;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
for (unsigned int i = 0; i < count; i++) {
if (sdmmc_read(&sd_mmc, buff + 0x200 * i, sector + i, 1) != 0) {
return RES_ERROR;
}
}
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
return RES_ERROR;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
return RES_OK;
}

View file

@ -0,0 +1,80 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,366 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.13a /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2017, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/
/----------------------------------------------------------------------------*/
#ifndef FF_DEFINED
#define FF_DEFINED 89352 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 2)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size variables */
#if FF_FS_EXFAT
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE fs_type; /* Filesystem type (0:N/A) */
BYTE pdrv; /* Physical drive number */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if FF_MAX_SS != FF_MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if FF_USE_LFN
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if FF_FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if FF_FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#if FF_FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (FFOBJID) */
typedef struct {
FATFS* fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if FF_FS_EXFAT
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */
#endif
#if FF_FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} FFOBJID;
/* File object structure (FIL) */
typedef struct {
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !FF_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
#endif
#if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FFOBJID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector (0:Read operation has terminated) */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if FF_USE_LFN
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if FF_USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
FRESULT f_setcp (WORD cp); /* Set current code page */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);
#endif
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
#endif
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#ifdef __cplusplus
}
#endif
#endif /* FF_DEFINED */

View file

@ -0,0 +1,283 @@
/*---------------------------------------------------------------------------/
/ FatFs - Configuration file
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 89352 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 3
/* This option defines minimization level to remove some basic API functions.
/
/ 0: Basic functions are fully enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 2
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define FF_USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define FF_USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
#define FF_USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define FF_USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 850
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
/ 0 - Include all code pages above and configured by f_setcp()
*/
#define FF_USE_LFN 1
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable LFN. FF_MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
/ specification.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree() in ffsystem.c, need to be added to the project. */
#define FF_LFN_UNICODE 0
/* This option switches the character encoding on the API when LFN is enabled.
/
/ 0: ANSI/OEM in current CP (TCHAR = char)
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
/ 2: Unicode in UTF-8 (TCHAR = char)
/
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO structure
/ which is used to read out directory items. These values should be suffcient for
/ the file names to read. The maximum possible length of the read file name depends
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_STRF_ENCODE 0
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#define FF_FS_RPATH 0
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 0
#define FF_VOLUME_STRS "sd"
/* FF_STR_VOLUME_ID switches string support for volume ID.
/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
#define FF_MULTI_PARTITION 0
/* This option switches support for multiple volumes on the physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
#define FF_MIN_SS 512
#define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
#define FF_USE_TRIM 0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#define FF_FS_EXFAT 1
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled.
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define FF_FS_NORTC 1
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2018
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */
#define FF_FS_LOCK 0
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
#define FF_FS_REENTRANT 0
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t HANDLE
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/* #include <windows.h> // O/S definitions */
/*--- End of configuration options ---*/

View file

@ -0,0 +1,171 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C)ChaN, 2017 */
/*------------------------------------------------------------------------*/
#include "ff.h"
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free (nothing to do for null) */
)
{
free(mblock); /* Free the memory block with POSIX API */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object for the volume, such as semaphore and mutex.
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
*/
//const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
FF_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
/* Win32 */
*sobj = CreateMutex(NULL, FALSE, NULL);
return (int)(*sobj != INVALID_HANDLE_VALUE);
/* uITRON */
// T_CSEM csem = {TA_TPRI,1,1};
// *sobj = acre_sem(&csem);
// return (int)(*sobj > 0);
/* uC/OS-II */
// OS_ERR err;
// *sobj = OSMutexCreate(0, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// *sobj = xSemaphoreCreateMutex();
// return (int)(*sobj != NULL);
/* CMSIS-RTOS */
// *sobj = osMutexCreate(Mutex + vol);
// return (int)(*sobj != NULL);
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */
FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
/* Win32 */
return (int)CloseHandle(sobj);
/* uITRON */
// return (int)(del_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// vSemaphoreDelete(sobj);
// return 1;
/* CMSIS-RTOS */
// return (int)(osMutexDelete(sobj) == osOK);
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
FF_SYNC_t sobj /* Sync object to wait */
)
{
/* Win32 */
return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
/* uITRON */
// return (int)(wai_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
/* CMSIS-RTOS */
// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
FF_SYNC_t sobj /* Sync object to be signaled */
)
{
/* Win32 */
ReleaseMutex(sobj);
/* uITRON */
// sig_sem(sobj);
/* uC/OS-II */
// OSMutexPost(sobj);
/* FreeRTOS */
// xSemaphoreGive(sobj);
/* CMSIS-RTOS */
// osMutexRelease(sobj);
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,149 @@
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include "gpio.h"
#include "lib/printk.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,
* which can be created using the TEGRA_GPIO macro or passed from the name macro.
*
* @param pin The GPIO to get the bank for.
* @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)
{
volatile struct tegra_gpio *gpio = gpio_get_regs();
int bank_number = pin >> GPIO_BANK_SHIFT;
return &gpio->bank[bank_number];
}
/**
* @return the port number for working with the given GPIO.
*/
static volatile int gpio_get_port(enum tegra_named_gpio pin)
{
return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK;
}
/**
* @return a mask to be used to work with the given GPIO
*/
static volatile uint32_t gpio_get_mask(enum tegra_named_gpio pin)
{
uint32_t pin_number = pin & GPIO_PIN_MASK;
return (1 << pin_number);
}
/**
* Performs a simple GPIO configuration operation.
*
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
* @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
*/
static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_set, size_t offset)
{
// Retrieve the register set that corresponds to the given pin and offset.
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
uint32_t *cluster = (uint32_t *)cluster_addr;
// Figure out the offset into the cluster,
// and the mask to be used.
int port = gpio_get_port(pin);
uint32_t mask = gpio_get_mask(pin);
// Set or clear the bit, as appropriate.
if (should_be_set)
cluster[port] |= mask;
else
cluster[port] &= ~mask;
}
/**
* Performs a simple GPIO configuration operation.
*
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
* @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
*/
static bool gpio_simple_register_get(enum tegra_named_gpio pin, size_t offset)
{
// Retrieve the register set that corresponds to the given pin and offset.
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
uint32_t *cluster = (uint32_t *)cluster_addr;
// Figure out the offset into the cluster,
// and the mask to be used.
int port = gpio_get_port(pin);
uint32_t mask = gpio_get_mask(pin);
// Convert the given value to a boolean.
return !!(cluster[port] & mask);
}
/**
* 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 mode The relevant mode.
*/
void gpio_configure_mode(enum tegra_named_gpio pin, enum tegra_gpio_mode mode)
{
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(struct tegra_gpio_bank, config));
}
/**
* 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 direction The relevant direction.
*/
void gpio_configure_direction(enum tegra_named_gpio pin, enum tegra_gpio_direction dir)
{
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(struct tegra_gpio_bank, direction));
}
/**
* 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 mode The relevant mode.
*/
void gpio_write(enum tegra_named_gpio pin, enum tegra_gpio_value value)
{
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(struct tegra_gpio_bank, out));
}
/**
* 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 mode The relevant mode.
*/
enum tegra_gpio_value gpio_read(enum tegra_named_gpio pin)
{
return gpio_simple_register_get(pin, offsetof(struct tegra_gpio_bank, in));
}

View file

@ -0,0 +1,174 @@
/*
* Struct defintiions lifted from NVIDIA sample code.
* (C) Copyright 2013-2015 NVIDIA Corporation <www.nvidia.com>
*
* adapted for Fusée by Kate Temkin <k@ktemkin.com.
*/
#ifndef __FUSEE_GPIO_H__
#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_B = 1,
TEGRA_GPIO_PORT_C = 2,
TEGRA_GPIO_PORT_D = 3,
TEGRA_GPIO_PORT_E = 4,
TEGRA_GPIO_PORT_F = 5,
TEGRA_GPIO_PORT_G = 6,
TEGRA_GPIO_PORT_H = 7,
TEGRA_GPIO_PORT_I = 8,
TEGRA_GPIO_PORT_J = 9,
TEGRA_GPIO_PORT_K = 10,
TEGRA_GPIO_PORT_L = 11,
TEGRA_GPIO_PORT_M = 12,
TEGRA_GPIO_PORT_N = 13,
TEGRA_GPIO_PORT_O = 14,
TEGRA_GPIO_PORT_P = 15,
TEGRA_GPIO_PORT_Q = 16,
TEGRA_GPIO_PORT_R = 17,
TEGRA_GPIO_PORT_S = 18,
TEGRA_GPIO_PORT_T = 19,
TEGRA_GPIO_PORT_U = 20,
TEGRA_GPIO_PORT_V = 21,
TEGRA_GPIO_PORT_W = 22,
TEGRA_GPIO_PORT_X = 23,
TEGRA_GPIO_PORT_Y = 24,
TEGRA_GPIO_PORT_Z = 25,
TEGRA_GPIO_PORT_AA = 26,
TEGRA_GPIO_PORT_BB = 27,
TEGRA_GPIO_PORT_CC = 28,
TEGRA_GPIO_PORT_DD = 29,
TEGRA_GPIO_PORT_EE = 30,
TEGRA_GPIO_PORT_FF = 31,
};
/**
* 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 direction[TEGRA_GPIO_PORTS];
uint32_t out[TEGRA_GPIO_PORTS];
uint32_t in[TEGRA_GPIO_PORTS];
uint32_t int_status[TEGRA_GPIO_PORTS];
uint32_t int_enable[TEGRA_GPIO_PORTS];
uint32_t int_level[TEGRA_GPIO_PORTS];
uint32_t int_clear[TEGRA_GPIO_PORTS];
uint32_t masked_config[TEGRA_GPIO_PORTS];
uint32_t masked_dir_out[TEGRA_GPIO_PORTS];
uint32_t masked_out[TEGRA_GPIO_PORTS];
uint32_t masked_in[TEGRA_GPIO_PORTS];
uint32_t masked_int_status[TEGRA_GPIO_PORTS];
uint32_t masked_int_enable[TEGRA_GPIO_PORTS];
uint32_t masked_int_level[TEGRA_GPIO_PORTS];
uint32_t masked_int_clear[TEGRA_GPIO_PORTS];
};
/**
* 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;
}
/**
* 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 mode The relevant mode.
*/
void gpio_configure_mode(enum tegra_named_gpio pin, enum tegra_gpio_mode mode);
/**
* 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 direction The relevant direction.
*/
void gpio_configure_direction(enum tegra_named_gpio pin, enum tegra_gpio_direction dir);
/**
* 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 mode The relevant value.
*/
void gpio_write(enum tegra_named_gpio pin, enum tegra_gpio_value value);
/**
* 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 mode The relevant mode.
*/
enum tegra_gpio_value gpio_read(enum tegra_named_gpio pin);
#endif

View file

@ -33,6 +33,6 @@ u32 *display_init_framebuffer();
/*! Enable or disable the backlight. Should only be called when the screen is completely set up, to avoid flickering. */
void display_enable_backlight(bool on);
void cluster_boot_cpu0(u64 entry, u32 ns_disable);
void cluster_enable_cpu0(u64 entry, u32 ns_disable);
#endif

View file

@ -52,7 +52,7 @@ int _cluster_pmc_enable_partition(u32 part, u32 toggle)
return 1;
}
void cluster_boot_cpu0(u64 entry, u32 ns_disable)
void cluster_enable_cpu0(u64 entry, u32 ns_disable)
{
//Set ACTIVE_CLUSER to FAST.
FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE;

View file

@ -7,6 +7,6 @@
#define FLOW_CTLR_RAM_REPAIR 0x40
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
void cluster_boot_cpu0(u64 entry, u32 ns_disable);
void cluster_enable_cpu0(u64 entry, u32 ns_disable);
#endif

View file

@ -1,15 +1,15 @@
/*
* Defining registers address and its bit definitions of MAX77620 and MAX20024
*
* Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
* Defining registers address and its bit definitions of MAX77620 and MAX20024
*
* Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#ifndef _MAX77620_H_
#define _MAX77620_H_
#ifndef _MFD_MAX77620_H_
#define _MFD_MAX77620_H_
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
#define MAX77620_REG_CNFGGLBL1 0x00
@ -72,7 +72,7 @@
#define MAX77620_LDO_SLEW_RATE_MASK 0x1
/* LDO Configuration 3 */
#define MAX77620_TRACK4_MASK BIT(5)
#define MAX77620_TRACK4_MASK (1 << 5)
#define MAX77620_TRACK4_SHIFT 5
/* Voltage */
@ -113,6 +113,29 @@
#define MAX77620_REG_FPS_SD2 0x51
#define MAX77620_REG_FPS_SD3 0x52
#define MAX77620_REG_FPS_SD4 0x53
#define MAX77620_REG_FPS_NONE 0
#define MAX77620_FPS_SRC_MASK 0xC0
#define MAX77620_FPS_SRC_SHIFT 6
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
#define MAX77620_FPS_EN_SRC_MASK 0x06
#define MAX77620_FPS_EN_SRC_SHIFT 1
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
#define MAX77620_FPS_ENFPS_SW 0x01
/* Minimum and maximum FPS period time (in microseconds) are
* different for MAX77620 and Max20024.
*/
#define MAX77620_FPS_PERIOD_MIN_US 40
#define MAX20024_FPS_PERIOD_MIN_US 20
#define MAX77620_FPS_PERIOD_MAX_US 2560
#define MAX20024_FPS_PERIOD_MAX_US 5120
#define MAX77620_REG_FPS_GPIO1 0x54
#define MAX77620_REG_FPS_GPIO2 0x55
@ -128,4 +151,174 @@
#define MAX77620_REG_DVSSD4 0x5E
#define MAX20024_REG_MAX_ADD 0x70
#endif
#define MAX77620_CID_DIDM_MASK 0xF0
#define MAX77620_CID_DIDM_SHIFT 4
/* CNCG2SD */
#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1)
#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2)
/* Device Identification Metal */
#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF)
/* Device Indentification OTP */
#define MAX77620_CID5_DIDO(n) ((n) & 0xF)
/* SD CNFG1 */
#define MAX77620_SD_SR_MASK 0xC0
#define MAX77620_SD_SR_SHIFT 6
#define MAX77620_SD_POWER_MODE_MASK 0x30
#define MAX77620_SD_POWER_MODE_SHIFT 4
#define MAX77620_SD_CFG1_ADE_MASK (1 << 3)
#define MAX77620_SD_CFG1_ADE_DISABLE 0
#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3)
#define MAX77620_SD_FPWM_MASK 0x04
#define MAX77620_SD_FPWM_SHIFT 2
#define MAX77620_SD_FSRADE_MASK 0x01
#define MAX77620_SD_FSRADE_SHIFT 0
#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2)
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2)
#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1)
#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0)
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0)
/* LDO_CNFG2 */
#define MAX77620_LDO_POWER_MODE_MASK 0xC0
#define MAX77620_LDO_POWER_MODE_SHIFT 6
#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2)
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
#define MAX77620_LDO_CFG2_ADE_DISABLE 0
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
#define MAX77620_LDO_CFG2_SS_FAST (1 << 0)
#define MAX77620_LDO_CFG2_SS_SLOW 0
#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7)
#define MAX77620_IRQ_TOP_SD_MASK (1 << 6)
#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5)
#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4)
#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3)
#define MAX77620_IRQ_TOP_32K_MASK (1 << 2)
#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1)
#define MAX77620_IRQ_LBM_MASK (1 << 3)
#define MAX77620_IRQ_TJALRM1_MASK (1 << 2)
#define MAX77620_IRQ_TJALRM2_MASK (1 << 1)
#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0
#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1)
#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1)
#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0
#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0
#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4)
#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4)
#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5)
#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6)
#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6)
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0)
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1)
#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2)
#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3)
#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4)
#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5)
#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6)
#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7)
#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2)
#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7)
#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2)
#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1)
#define MAX20024_ONOFFCNFG1_CLRSE 0x18
#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7)
#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6)
#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5)
#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2)
#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0)
#define MAX77620_GLBLM_MASK (1 << 0)
#define MAX77620_WDTC_MASK 0x3
#define MAX77620_WDTOFFC (1 << 4)
#define MAX77620_WDTSLPC (1 << 3)
#define MAX77620_WDTEN (1 << 2)
#define MAX77620_TWD_MASK 0x3
#define MAX77620_TWD_2s 0x0
#define MAX77620_TWD_16s 0x1
#define MAX77620_TWD_64s 0x2
#define MAX77620_TWD_128s 0x3
#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7)
#define MAX77620_CNFGGLBL1_MPPLD (1 << 6)
#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4))
#define MAX77620_CNFGGLBL1_LBDAC 0x0E
#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0)
/* CNFG BBC registers */
#define MAX77620_CNFGBBC_ENABLE (1 << 0)
#define MAX77620_CNFGBBC_CURRENT_MASK 0x06
#define MAX77620_CNFGBBC_CURRENT_SHIFT 1
#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18
#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3
#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5)
#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0
#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6
#define MAX77620_FPS_COUNT 3
/* Interrupts */
enum {
MAX77620_IRQ_TOP_GLBL, /* Low-Battery */
MAX77620_IRQ_TOP_SD, /* SD power fail */
MAX77620_IRQ_TOP_LDO, /* LDO power fail */
MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */
MAX77620_IRQ_TOP_RTC, /* RTC */
MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */
MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */
MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */
MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */
MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */
};
/* GPIOs */
enum {
MAX77620_GPIO0,
MAX77620_GPIO1,
MAX77620_GPIO2,
MAX77620_GPIO3,
MAX77620_GPIO4,
MAX77620_GPIO5,
MAX77620_GPIO6,
MAX77620_GPIO7,
MAX77620_GPIO_NR,
};
/* FPS Source */
enum max77620_fps_src {
MAX77620_FPS_SRC_0,
MAX77620_FPS_SRC_1,
MAX77620_FPS_SRC_2,
MAX77620_FPS_SRC_NONE,
MAX77620_FPS_SRC_DEF,
};
enum max77620_chip_id {
MAX77620,
MAX20024,
};
#endif /* _MFD_MAX77620_H_ */

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "max7762x.h"
#include "max77620.h"
#include "i2c.h"
#include "util.h"
#define REGULATOR_SD 0
#define REGULATOR_LDO 1
typedef struct _max77620_regulator_t
{
u8 type;
const char *name;
u8 reg_sd;
u32 mv_step;
u32 mv_min;
u32 mv_default;
u32 mv_max;
u8 volt_addr;
u8 cfg_addr;
u8 volt_mask;
u8 enable_mask;
u8 enable_shift;
u8 status_mask;
u8 fps_addr;
u8 fps_src;
u8 pd_period;
u8 pu_period;
} max77620_regulator_t;
static const max77620_regulator_t _pmic_regulators[] = {
{ REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, 0x3F, 0x30, 4, 0x80, 0x4F, 1, 7, 1 },
{ REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, 0x3F, 0x30, 4, 0x40, 0x50, 0, 1, 5 },
{ REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, 0xFF, 0x30, 4, 0x20, 0x51, 1, 5, 2 },
{ REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, 0xFF, 0x30, 4, 0x10, 0x52, 0, 3, 3 },
{ REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, 0x3F, 0xC0, 6, 0x00, 0x46, 3, 7, 0 },
{ REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, 0x3F, 0xC0, 6, 0x00, 0x47, 3, 7, 0 },
{ REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, 0x3F, 0xC0, 6, 0x00, 0x48, 3, 7, 0 },
{ REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, 0x3F, 0xC0, 6, 0x00, 0x49, 3, 7, 0 },
{ REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4A, 0, 7, 1 },
{ REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4B, 3, 7, 0 },
{ REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4C, 3, 7, 0 },
{ REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4D, 1, 4, 3 },
{ REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4E, 3, 7, 0 }
};
int max77620_regulator_get_status(u32 id)
{
if (id > REGULATOR_MAX)
return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id];
if (reg->type == REGULATOR_SD)
return i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask ? 0 : 1;
return i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8 ? 1 : 0;
}
int max77620_regulator_config_fps(u32 id)
{
if (id > REGULATOR_MAX)
return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id];
i2c_send_byte(I2C_5, 0x3C, reg->fps_addr, (reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period));
return 1;
}
int max77620_regulator_set_voltage(u32 id, u32 mv)
{
if (id > REGULATOR_MAX)
return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id];
if (mv < reg->mv_default || mv > reg->mv_max)
return 0;
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
u8 val = i2c_recv_byte(I2C_5, 0x3C, reg->volt_addr);
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
i2c_send_byte(I2C_5, 0x3C, reg->volt_addr, val);
sleep(1000);
return 1;
}
int max77620_regulator_enable(u32 id, int enable)
{
if (id > REGULATOR_MAX)
return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id];
u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr;
u8 val = i2c_recv_byte(I2C_5, 0x3C, addr);
if (enable)
val = (val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask);
else
val &= ~reg->enable_mask;
i2c_send_byte(I2C_5, 0x3C, addr, val);
sleep(1000);
return 1;
}
void max77620_config_default()
{
for (u32 i = 1; i <= REGULATOR_MAX; i++)
{
i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_CID4);
max77620_regulator_config_fps(i);
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE)
max77620_regulator_enable(i, 1);
}
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_SD_CFG2, 4);
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MAX7762X_H_
#define _MAX7762X_H_
#include "types.h"
/*
* Switch Power domains (max77620):
* Name | Usage | uV step | uV min | uV default | uV max | Init
*-------+---------------+---------+--------+------------+---------+------------------
* sd0 | core | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1)
* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv)
* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 |
* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1)
* ldo1 | XUSB | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
* ldo3 | | 50000 | 800000 | 3100000 | 3100000 |
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 |
* ldo5 | | 50000 | 800000 | 1800000 | 1800000 |
* ldo6 | | 50000 | 800000 | 2900000 | 2900000 |
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 |
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 |
*/
/*
* MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode
* MAX77620_REG_GPIOx: 0x9 sets output and enable
*/
/*! MAX77620 partitions. */
#define REGULATOR_SD0 0
#define REGULATOR_SD1 1
#define REGULATOR_SD2 2
#define REGULATOR_SD3 3
#define REGULATOR_LDO0 4
#define REGULATOR_LDO1 5
#define REGULATOR_LDO2 6
#define REGULATOR_LDO3 7
#define REGULATOR_LDO4 8
#define REGULATOR_LDO5 9
#define REGULATOR_LDO6 10
#define REGULATOR_LDO7 11
#define REGULATOR_LDO8 12
#define REGULATOR_MAX 12
int max77620_regulator_get_status(u32 id);
int max77620_regulator_config_fps(u32 id);
int max77620_regulator_set_voltage(u32 id, u32 mv);
int max77620_regulator_enable(u32 id, int enable);
void max77620_config_default();
#endif

View file

@ -0,0 +1,38 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef FF_INTEGER
#define FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
typedef unsigned __int64 QWORD;
#else /* Embedded platform */
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* This type MUST be 8-bit */
typedef unsigned char BYTE;
/* These types MUST be 16-bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
typedef unsigned long long QWORD;
#endif
#endif

View file

@ -16,9 +16,15 @@
void printk(char *fmt, ...)
{
va_list list;
char buf[512];
va_start(list, fmt);
vsnprintf(buf, sizeof(buf), fmt, list);
video_puts(buf);
vprintk(fmt, list);
va_end(list);
}
void vprintk(char *fmt, va_list args)
{
char buf[512];
vsnprintf(buf, sizeof(buf), fmt, args);
video_puts(buf);
}

View file

@ -1,2 +1,9 @@
#ifndef __PRINTK_H__
#define __PRINTK_H__
#include <stdarg.h>
void printk(char *fmt, ...);
void vprintk(char *fmt, va_list args);
#endif

View file

@ -19,8 +19,10 @@ struct va_format {
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
int sprintf(char *buf, const char *fmt, ...);
int scnprintf(char *buf, size_t size, const char *fmt, ...);
int snprintf(char *buf, size_t size, const char *fmt, ...);
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
int sscanf(const char *buf, const char *fmt, ...);
#endif /* VSPRINTF_H */

View file

@ -3,6 +3,7 @@
#include "loader.h"
#include "stage2.h"
#include "nxboot.h"
#include "sd_utils.h"
#include "lib/printk.h"
#include "display/video_fb.h"
@ -14,13 +15,15 @@ char g_bct0[0x8000];
#pragma GCC diagnostic ignored "-Wmain"
int main(int argc, void **argv) {
stage2_args_t args;
stage2_args_t args = {0};
loader_ctx_t *loader_ctx = get_loader_ctx();
if (argc != STAGE2_ARGC || ((args = *((stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT])).version != 0)) {
generic_panic();
}
resume_sd_state((struct mmc *)args.sd_mmc, (FATFS *)args.sd_fs);
/* Copy the BCT0 from unsafe primary memory into our memory. */
strncpy(g_bct0, args.bct0, sizeof(g_bct0));
@ -35,6 +38,8 @@ int main(int argc, void **argv) {
/* This will load all remaining binaries off of the SD. */
load_payload(g_bct0);
printk("Loaded payloads!\n");
if (loader_ctx->chainload_entrypoint != NULL) {
/* TODO: What do we want to do in terms of argc/argv? */
loader_ctx->chainload_entrypoint(0, NULL);

View file

@ -69,7 +69,7 @@ void nxboot_main(void) {
} else {
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X;
}
cluster_boot_cpu0(loader_ctx->exosphere_loadfile.load_address, 1);
cluster_enable_cpu0(loader_ctx->exosphere_loadfile.load_address, 1);
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) {
/* Wait for Exosphere to wake up. */
}

View file

@ -0,0 +1,67 @@
/**
* 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 PACKED 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

View file

@ -0,0 +1,221 @@
#ifndef __FUSEE_PINMUX_H__
#define __FUSEE_PINMUX_H__
#include <stdbool.h>
#include <stdint.h>
#include "utils.h"
/**
* Pinmux structures.
*/
struct PACKED tegra_pinmux {
uint32_t sdmmc1_clk;
uint32_t sdmmc1_cmd;
uint32_t sdmmc1_dat3;
uint32_t sdmmc1_dat2;
uint32_t sdmmc1_dat1;
uint32_t sdmmc1_dat0;
uint32_t _r18;
uint32_t sdmmc3_clk;
uint32_t sdmmc3_cmd;
uint32_t sdmmc3_dat0;
uint32_t sdmmc3_dat1;
uint32_t sdmmc3_dat2;
uint32_t sdmmc3_dat3;
uint32_t _r34;
uint32_t pex_l0_rst_n;
uint32_t pex_l0_clkreq_n;
uint32_t pex_wake_n;
uint32_t pex_l1_rst_n;
uint32_t pex_l1_clkreq_n;
uint32_t sata_led_active;
uint32_t spi1_mosi;
uint32_t spi1_miso;
uint32_t spi1_sck;
uint32_t spi1_cs0;
uint32_t spi1_cs1;
uint32_t spi2_mosi;
uint32_t spi2_miso;
uint32_t spi2_sck;
uint32_t spi2_cs0;
uint32_t spi2_cs1;
uint32_t spi4_mosi;
uint32_t spi4_miso;
uint32_t spi4_sck;
uint32_t spi4_cs0;
uint32_t qspi_sck;
uint32_t qspi_cs_n;
uint32_t qspi_io0;
uint32_t qspi_io1;
uint32_t qspi_io2;
uint32_t qspi_io3;
uint32_t _ra0;
uint32_t dmic1_clk;
uint32_t dmic1_dat;
uint32_t dmic2_clk;
uint32_t dmic2_dat;
uint32_t dmic3_clk;
uint32_t dmic3_dat;
uint32_t gen1_i2c_scl;
uint32_t gen1_i2c_sda;
uint32_t gen2_i2c_scl;
uint32_t gen2_i2c_sda;
uint32_t gen3_i2c_scl;
uint32_t gen3_i2c_sda;
uint32_t cam_i2c_scl;
uint32_t cam_i2c_sda;
uint32_t pwr_i2c_scl;
uint32_t pwr_i2c_sda;
uint32_t uart1_tx;
uint32_t uart1_rx;
uint32_t uart1_rts;
uint32_t uart1_cts;
uint32_t uart2_tx;
uint32_t uart2_rx;
uint32_t uart2_rts;
uint32_t uart2_cts;
uint32_t uart3_tx;
uint32_t uart3_rx;
uint32_t uart3_rts;
uint32_t uart3_cts;
uint32_t uart4_tx;
uint32_t uart4_rx;
uint32_t uart4_rts;
uint32_t uart4_cts;
uint32_t dap1_fs;
uint32_t dap1_din;
uint32_t dap1_dout;
uint32_t dap1_sclk;
uint32_t dap2_fs;
uint32_t dap2_din;
uint32_t dap2_dout;
uint32_t dap2_sclk;
uint32_t dap4_fs;
uint32_t dap4_din;
uint32_t dap4_dout;
uint32_t dap4_sclk;
uint32_t cam1_mclk;
uint32_t cam2_mclk;
uint32_t jtag_rtck;
uint32_t clk_32k_in;
uint32_t clk_32k_out;
uint32_t batt_bcl;
uint32_t clk_req;
uint32_t cpu_pwr_req;
uint32_t pwr_int_n;
uint32_t shutdown;
uint32_t core_pwr_req;
uint32_t aud_mclk;
uint32_t dvfs_pwm;
uint32_t dvfs_clk;
uint32_t gpio_x1_aud;
uint32_t gpio_x3_aud;
uint32_t pcc7;
uint32_t hdmi_cec;
uint32_t hdmi_int_dp_hpd;
uint32_t spdif_out;
uint32_t spdif_in;
uint32_t usb_vbus_en0;
uint32_t usb_vbus_en1;
uint32_t dp_hpd0;
uint32_t wifi_en;
uint32_t wifi_rst;
uint32_t wifi_wake_ap;
uint32_t ap_wake_bt;
uint32_t bt_rst;
uint32_t bt_wake_ap;
uint32_t ap_wake_nfc;
uint32_t nfc_en;
uint32_t nfc_int;
uint32_t gps_en;
uint32_t gps_rst;
uint32_t cam_rst;
uint32_t cam_af_en;
uint32_t cam_flash_en;
uint32_t cam1_pwdn;
uint32_t cam2_pwdn;
uint32_t cam1_strobe;
uint32_t lcd_te;
uint32_t lcd_bl_pwm;
uint32_t lcd_bl_en;
uint32_t lcd_rst;
uint32_t lcd_gpio1;
uint32_t lcd_gpio2;
uint32_t ap_ready;
uint32_t touch_rst;
uint32_t touch_clk;
uint32_t modem_wake_ap;
uint32_t touch_int;
uint32_t motion_int;
uint32_t als_prox_int;
uint32_t temp_alert;
uint32_t button_power_on;
uint32_t button_vol_up;
uint32_t button_vol_down;
uint32_t button_slide_sw;
uint32_t button_home;
uint32_t pa6;
uint32_t pe6;
uint32_t pe7;
uint32_t ph6;
uint32_t pk0;
uint32_t pk1;
uint32_t pk2;
uint32_t pk3;
uint32_t pk4;
uint32_t pk5;
uint32_t pk6;
uint32_t pk7;
uint32_t pl0;
uint32_t pl1;
uint32_t pz0;
uint32_t pz1;
uint32_t pz2;
uint32_t pz3;
uint32_t pz4;
uint32_t pz5;
};
/**
* 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;
}
#endif

View file

@ -1,10 +1,14 @@
#ifndef FUSEE_PMC_H
#define FUSEE_PMC_H
#ifndef __FUSEE_PMC_H__
#define __FUSEE_PMC_H__
#include "utils.h"
#define PMC_BASE 0x7000E400
/* TODO: get rid of these defines; use the struct instead */
#define APBDEV_PMC_CONTROL MAKE_REG32(PMC_BASE + 0x00)
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24)
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30)
@ -22,6 +26,292 @@
#define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840)
/**
* Definitions of the Tegra PMC.
*/
struct PACKED tegra_pmc {
uint32_t cntrl;
uint32_t sec_disable;
uint32_t pmc_swrst;
uint32_t wake_mask;
uint32_t wake_lvl;
uint32_t wake_status;
uint32_t sw_wake_status;
uint32_t dpd_pads_oride;
uint32_t dpd_sample;
uint32_t dpd_enable;
uint32_t pwrgate_timer_off;
uint32_t clamp_status;
uint32_t pwrgate_toggle;
uint32_t remove_clamping;
uint32_t pwrgate_status;
uint32_t pwrgood_timer;
uint32_t blink_timer;
uint32_t no_iopower;
uint32_t pwr_det;
uint32_t pwr_det_latch;
uint32_t scratch0;
uint32_t scratch1;
uint32_t scratch2;
uint32_t scratch3;
uint32_t scratch4;
uint32_t scratch5;
uint32_t scratch6;
uint32_t scratch7;
uint32_t scratch8;
uint32_t scratch9;
uint32_t scratch10;
uint32_t scratch11;
uint32_t scratch12;
uint32_t scratch13;
uint32_t scratch14;
uint32_t scratch15;
uint32_t scratch16;
uint32_t scratch17;
uint32_t scratch18;
uint32_t scratch19;
uint32_t scratch20;
uint32_t scratch21;
uint32_t scratch22;
uint32_t scratch23;
uint32_t secure_scratch0;
uint32_t secure_scratch1;
uint32_t secure_scratch2;
uint32_t secure_scratch3;
uint32_t secure_scratch4;
uint32_t secure_scratch5;
uint32_t cpupwrgood_timer;
uint32_t cpupwroff_timer;
uint32_t pg_mask;
uint32_t pg_mask_1;
uint32_t auto_wake_lvl;
uint32_t auto_wake_lvl_mask;
uint32_t wake_delay;
uint32_t pwr_det_val;
uint32_t ddr_pwr;
uint32_t usb_debounce_del;
uint32_t usb_ao;
uint32_t crypto_op;
uint32_t pllp_wb0_override;
uint32_t scratch24;
uint32_t scratch25;
uint32_t scratch26;
uint32_t scratch27;
uint32_t scratch28;
uint32_t scratch29;
uint32_t scratch30;
uint32_t scratch31;
uint32_t scratch32;
uint32_t scratch33;
uint32_t scratch34;
uint32_t scratch35;
uint32_t scratch36;
uint32_t scratch37;
uint32_t scratch38;
uint32_t scratch39;
uint32_t scratch40;
uint32_t scratch41;
uint32_t scratch42;
uint32_t bo_mirror0;
uint32_t bo_mirror1;
uint32_t bo_mirror2;
uint32_t sys_33v_en;
uint32_t bo_mirror_access;
uint32_t gate;
uint32_t wake2_mask;
uint32_t wake2_lvl;
uint32_t wake2_stat;
uint32_t sw_wake2_stat;
uint32_t auto_wake2_lvl_mask;
uint32_t pg_mask2;
uint32_t pg_mask_ce1;
uint32_t pg_mask_ce2;
uint32_t pg_mask_ce3;
uint32_t pwrgate_timer_ce0;
uint32_t pwrgate_timer_ce1;
uint32_t pwrgate_timer_ce2;
uint32_t pwrgate_timer_ce3;
uint32_t pwrgate_timer_ce4;
uint32_t pwrgate_timer_ce5;
uint32_t pwrgate_timer_ce6;
uint32_t pcx_edpd_cntrl;
uint32_t osc_edpd_over;
uint32_t clk_out_cntrl;
uint32_t sata_pwrgate;
uint32_t sensor_ctrl;
uint32_t reset_status;
uint32_t io_dpd_req;
uint32_t io_dpd_stat;
uint32_t io_dpd2_req;
uint32_t io_dpd2_stat;
uint32_t sel_dpd_tim;
uint32_t vddp_sel;
uint32_t ddr_cfg;
uint32_t e_no_vttgen;
uint32_t reserved0;
uint32_t pllm_wb0_ovrride_frq;
uint32_t test_pwrgate;
uint32_t pwrgate_timer_mult;
uint32_t dsi_sel_dpd;
uint32_t utmip_uhsic_triggers;
uint32_t utmip_uhsic_saved_st;
uint32_t utmip_pad_cfg;
uint32_t utmip_term_pad_cfg;
uint32_t utmip_uhsic_sleep_cfg;
uint32_t todo_0[9];
uint32_t secure_scratch6;
uint32_t secure_scratch7;
uint32_t scratch43;
uint32_t scratch44;
uint32_t scratch45;
uint32_t scratch46;
uint32_t scratch47;
uint32_t scratch48;
uint32_t scratch49;
uint32_t scratch50;
uint32_t scratch51;
uint32_t scratch52;
uint32_t scratch53;
uint32_t scratch54;
uint32_t scratch55;
uint32_t scratch0_eco;
uint32_t por_dpd_ctrl;
uint32_t scratch2_eco;
uint32_t todo_1[17];
uint32_t pllm_wb0_override2;
uint32_t tsc_mult;
uint32_t cpu_vsense_override;
uint32_t glb_amap_cfg;
uint32_t sticky_bits;
uint32_t sec_disable2;
uint32_t weak_bias;
uint32_t todo_3[13];
uint32_t secure_scratch8;
uint32_t secure_scratch9;
uint32_t secure_scratch10;
uint32_t secure_scratch11;
uint32_t secure_scratch12;
uint32_t secure_scratch13;
uint32_t secure_scratch14;
uint32_t secure_scratch15;
uint32_t secure_scratch16;
uint32_t secure_scratch17;
uint32_t secure_scratch18;
uint32_t secure_scratch19;
uint32_t secure_scratch20;
uint32_t secure_scratch21;
uint32_t secure_scratch22;
uint32_t secure_scratch23;
uint32_t secure_scratch24;
uint32_t secure_scratch25;
uint32_t secure_scratch26;
uint32_t secure_scratch27;
uint32_t secure_scratch28;
uint32_t secure_scratch29;
uint32_t secure_scratch30;
uint32_t secure_scratch31;
uint32_t secure_scratch32;
uint32_t secure_scratch33;
uint32_t secure_scratch34;
uint32_t secure_scratch35;
uint32_t reserved1[52];
uint32_t cntrl2;
uint32_t reserved2[6];
uint32_t io_dpd3_req;
uint32_t io_dpd3_stat;
uint32_t strap_opt_a;
uint32_t reserved3[102];
uint32_t scratch56;
uint32_t scratch57;
uint32_t scratch58;
uint32_t scratch59;
uint32_t scratch60;
uint32_t scratch61;
uint32_t scratch62;
uint32_t scratch63;
uint32_t scratch64;
uint32_t scratch65;
uint32_t scratch66;
uint32_t scratch67;
uint32_t scratch68;
uint32_t scratch69;
uint32_t scratch70;
uint32_t scratch71;
uint32_t scratch72;
uint32_t scratch73;
uint32_t scratch74;
uint32_t scratch75;
uint32_t scratch76;
uint32_t scratch77;
uint32_t scratch78;
uint32_t scratch79;
uint32_t scratch80;
uint32_t scratch81;
uint32_t scratch82;
uint32_t scratch83;
uint32_t scratch84;
uint32_t scratch85;
uint32_t scratch86;
uint32_t scratch87;
uint32_t scratch88;
uint32_t scratch89;
uint32_t scratch90;
uint32_t scratch91;
uint32_t scratch92;
uint32_t scratch93;
uint32_t scratch94;
uint32_t scratch95;
uint32_t scratch96;
uint32_t scratch97;
uint32_t scratch98;
uint32_t scratch99;
uint32_t scratch100;
uint32_t scratch101;
uint32_t scratch102;
uint32_t scratch103;
uint32_t scratch104;
uint32_t scratch105;
uint32_t scratch106;
uint32_t scratch107;
uint32_t scratch108;
uint32_t scratch109;
uint32_t scratch110;
uint32_t scratch111;
uint32_t scratch112;
uint32_t scratch113;
uint32_t scratch114;
uint32_t scratch115;
uint32_t scratch116;
uint32_t scratch117;
uint32_t scratch118;
uint32_t scratch119;
uint32_t scratch1_eco;
};
enum tegra_pmc_masks {
/* 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 pinmux registers.
*/
static inline struct tegra_pmc *pmc_get_regs(void)
{
return (struct tegra_pmc *)0x7000e400;
}
#endif

View file

@ -1,11 +1,65 @@
#include "sd_utils.h"
#include "hwinit.h"
#include "sdmmc.h"
#include "lib/printk.h"
#include "ff.h"
/* This is used by diskio.h. */
struct mmc sd_mmc;
FATFS sd_fs;
static int initialized_sd = 0;
static int mounted_sd = 0;
void save_sd_state(void **mmc, void **ff) {
*mmc = &sd_mmc;
*ff = &ff;
}
void resume_sd_state(void *mmc, void *ff) {
sd_mmc = *(struct mmc *)mmc;
sd_fs = *(FATFS *)ff;
initialized_sd = 1;
mounted_sd = 1;
}
int initialize_sd(void) {
if (initialized_sd) {
return 1;
}
mc_enable_ahb_redirect();
if (sdmmc_init(&sd_mmc, SWITCH_MICROSD) == 0) {
printk("Initialized SD card!\n");
initialized_sd = 1;
}
return initialized_sd;
}
int mount_sd(void) {
if (mounted_sd) {
return 1;
}
if (f_mount(&sd_fs, "", 1) == FR_OK) {
printk("Mounted SD card!\n");
mounted_sd = 1;
}
return mounted_sd;
}
size_t read_sd_file(void *dst, size_t dst_size, const char *filename) {
/* TODO: Implement this function. */
(void)(dst);
(void)(dst_size);
(void)(filename);
if (!initialized_sd && initialize_sd() == 0) {
return 0;
}
if (!mounted_sd && mount_sd() == 0) {
return 0;
}
/* Fail, because this function is unimplemented. */
return 0;
FIL f;
if (f_open(&f, filename, FA_READ) != FR_OK) {
return 0;
}
UINT br;
int res = f_read(&f, dst, dst_size, &br);
f_close(&f);
return res == FR_OK ? (int)br : 0;
}

View file

@ -2,6 +2,11 @@
#define FUSEE_SD_UTILS_H
#include "utils.h"
#include "sdmmc.h"
#include "ff.h"
void save_sd_state(void **mmc, void **ff);
void resume_sd_state(void *mmc, void *ff);
size_t read_sd_file(void *dst, size_t dst_size, const char *filename);

File diff suppressed because it is too large Load diff

View file

@ -1,134 +1,166 @@
#ifndef FUSEE_SDMMC_H
#define FUSEE_SDMMC_H
/**
* 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"
typedef struct {
uint32_t SDHCI_DMA_ADDRESS;
uint16_t SDHCI_BLOCK_SIZE;
uint16_t SDHCI_BLOCK_COUNT;
uint32_t SDHCI_ARGUMENT;
uint16_t SDHCI_TRANSFER_MODE;
uint16_t SDHCI_COMMAND;
uint16_t SDHCI_RESPONSE[0x8];
uint32_t SDHCI_BUFFER;
uint32_t SDHCI_PRESENT_STATE;
uint8_t SDHCI_HOST_CONTROL;
uint8_t SDHCI_POWER_CONTROL;
uint8_t SDHCI_BLOCK_GAP_CONTROL;
uint8_t SDHCI_WAKE_UP_CONTROL;
uint16_t SDHCI_CLOCK_CONTROL;
uint8_t SDHCI_TIMEOUT_CONTROL;
uint8_t SDHCI_SOFTWARE_RESET;
uint32_t SDHCI_INT_STATUS;
uint32_t SDHCI_INT_ENABLE;
uint32_t SDHCI_SIGNAL_ENABLE;
uint16_t SDHCI_ACMD12_ERR;
uint16_t SDHCI_HOST_CONTROL2;
uint32_t SDHCI_CAPABILITIES;
uint32_t SDHCI_CAPABILITIES_1;
uint32_t SDHCI_MAX_CURRENT;
uint32_t _0x4C;
uint16_t SDHCI_SET_ACMD12_ERROR;
uint16_t SDHCI_SET_INT_ERROR;
uint16_t SDHCI_ADMA_ERROR;
uint8_t _0x55[0x3];
uint32_t SDHCI_ADMA_ADDRESS;
uint32_t SDHCI_UPPER_ADMA_ADDRESS;
uint16_t SDHCI_PRESET_FOR_INIT;
uint16_t SDHCI_PRESET_FOR_DEFAULT;
uint16_t SDHCI_PRESET_FOR_HIGH;
uint16_t SDHCI_PRESET_FOR_SDR12;
uint16_t SDHCI_PRESET_FOR_SDR25;
uint16_t SDHCI_PRESET_FOR_SDR50;
uint16_t SDHCI_PRESET_FOR_SDR104;
uint16_t SDHCI_PRESET_FOR_DDR50;
uint8_t _0x70[0x3];
uint32_t _0x74[0x22];
uint16_t SDHCI_SLOT_INT_STATUS;
uint16_t SDHCI_HOST_VERSION;
} sdhci_registers_t;
/* Opaque pointer to the Tegra SDMMC registers */
struct tegra_sdmmc;
typedef struct {
sdhci_registers_t standard_regs;
uint32_t SDMMC_VENDOR_CLOCK_CNTRL;
uint32_t SDMMC_VENDOR_SYS_SW_CNTRL;
uint32_t SDMMC_VENDOR_ERR_INTR_STATUS;
uint32_t SDMMC_VENDOR_CAP_OVERRIDES;
uint32_t SDMMC_VENDOR_BOOT_CNTRL;
uint32_t SDMMC_VENDOR_BOOT_ACK_TIMEOUT;
uint32_t SDMMC_VENDOR_BOOT_DAT_TIMEOUT;
uint32_t SDMMC_VENDOR_DEBOUNCE_COUNT;
uint32_t SDMMC_VENDOR_MISC_CNTRL;
uint32_t SDMMC_MAX_CURRENT_OVERRIDE;
uint32_t SDMMC_MAX_CURRENT_OVERRIDE_HI;
uint32_t _0x12C[0x21];
uint32_t SDMMC_VENDOR_IO_TRIM_CNTRL;
/* Start of SDMMC2/SDMMC4 only */
uint32_t SDMMC_VENDOR_DLLCAL_CFG;
uint32_t SDMMC_VENDOR_DLL_CTRL0;
uint32_t SDMMC_VENDOR_DLL_CTRL1;
uint32_t SDMMC_VENDOR_DLLCAL_CFG_STA;
/* End of SDMMC2/SDMMC4 only */
uint32_t SDMMC_VENDOR_TUNING_CNTRL0;
uint32_t SDMMC_VENDOR_TUNING_CNTRL1;
uint32_t SDMMC_VENDOR_TUNING_STATUS0;
uint32_t SDMMC_VENDOR_TUNING_STATUS1;
uint32_t SDMMC_VENDOR_CLK_GATE_HYSTERESIS_COUNT;
uint32_t SDMMC_VENDOR_PRESET_VAL0;
uint32_t SDMMC_VENDOR_PRESET_VAL1;
uint32_t SDMMC_VENDOR_PRESET_VAL2;
uint32_t SDMMC_SDMEMCOMPPADCTRL;
uint32_t SDMMC_AUTO_CAL_CONFIG;
uint32_t SDMMC_AUTO_CAL_INTERVAL;
uint32_t SDMMC_AUTO_CAL_STATUS;
uint32_t SDMMC_IO_SPARE;
uint32_t SDMMC_SDMMCA_MCCIF_FIFOCTRL;
uint32_t SDMMC_TIMEOUT_WCOAL_SDMMCA;
uint32_t _0x1FC;
} sdmmc_registers_t;
static inline volatile sdmmc_registers_t *get_sdmmc1_regs(void) {
return (volatile sdmmc_registers_t *)(0x700B0000);
}
/**
* 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,
};
static inline volatile sdmmc_registers_t *get_sdmmc1b_regs(void) {
return (volatile sdmmc_registers_t *)(0x700B0000 + 0x1000);
}
static inline volatile sdmmc_registers_t *get_sdmmc2_regs(void) {
return (volatile sdmmc_registers_t *)(0x700B0200);
}
/**
* 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_3V0 = 0b110,
MMC_VOLTAGE_1V8 = 0b101,
};
static inline volatile sdmmc_registers_t *get_sdmmc2b_regs(void) {
return (volatile sdmmc_registers_t *)(0x700B0200 + 0x2000);
}
static inline volatile sdmmc_registers_t *get_sdmmc3_regs(void) {
return (volatile sdmmc_registers_t *)(0x700B0400);
}
/**
* 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,
};
static inline volatile sdmmc_registers_t *get_sdmmc3b_regs(void) {
return (volatile sdmmc_registers_t *)(0x700B0400 + 0x3000);
}
static inline volatile sdmmc_registers_t *get_sdmmc4_regs(void) {
return (volatile sdmmc_registers_t *)(0x700B0600);
}
static inline volatile sdmmc_registers_t *get_sdmmc4b_regs(void) {
return (volatile sdmmc_registers_t *)(0x700B0600 + 0x4000);
}
/**
* Specification versions for SD/MMC cards.
*/
enum sdmmc_spec_version {
#define SDMMC1_REGS (get_sdmmc1_regs())
#define SDMMC2_REGS (get_sdmmc2_regs())
#define SDMMC3_REGS (get_sdmmc3_regs())
#define SDMMC4_REGS (get_sdmmc4_regs())
/* MMC card versions */
MMC_VERSION_4 = 0,
void sdmmc1_init(void);
void sdmmc2_init(void);
void sdmmc3_init(void);
void sdmmc4_init(void);
/* SD card versions */
SD_VERSION_1 = 1,
SD_VERSION_2 = 2,
};
/**
* SDMMC controllers
*/
enum sdmmc_controller {
SWITCH_MICROSD = 0,
SWITCH_EMMC = 3
};
/**
* Primary data structure describing a Fusée MMC driver.
*/
struct mmc {
enum sdmmc_controller controller;
/* Controller properties */
char *name;
unsigned int timeout;
enum sdmmc_card_type card_type;
bool use_dma;
/* Card properties */
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;
uint8_t partition_support;
uint8_t partition_config;
uint8_t partition_attribute;
uint32_t partition_switch_time;
uint8_t read_block_order;
bool uses_block_addressing;
/* 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 {
MMC_PARTITION_USER = 0,
MMC_PARTITION_BOOT1 = 1,
MMC_PARITTION_BOOT2 = 2,
};
/**
* Initiailzes an SDMMC controller for use with an eMMC or SD card device.
*
* @param mmc An (uninitialized) structure for the MMC device.
* @param controller The controller number to be initialized. Either SWITCH_MICROSD or SWITCH_EMMC.
*/
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller);
/**
* 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);
/**
* 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);
#endif

View file

@ -14,6 +14,8 @@ typedef struct {
uint32_t *lfb;
uint32_t console_row;
uint32_t console_col;
void *sd_mmc;
void *sd_fs;
} stage2_args_t;
#endif

View file

@ -0,0 +1,30 @@
/**
* Fusée power supply control code
* ~ktemkin
*/
#include "supplies.h"
#include "lib/printk.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.
*/
void supply_enable(enum switch_power_supply supply)
{
switch(supply) {
case SUPPLY_MICROSD:
max77620_regulator_set_voltage(SUPPLY_MICROSD_REGULATOR, SUPPLY_MICROSD_VOLTAGE);
max77620_regulator_enable(SUPPLY_MICROSD_REGULATOR, true);
return;
default:
printk("ERROR: could not enable unknown supply %d!\n", supply);
return;
}
}

View file

@ -0,0 +1,31 @@
/**
* 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,
};
/**
* Enables a given power supply.
*
* @param supply The power domain on the Switch that is to be enabled.
*/
void supply_enable(enum switch_power_supply supply);
#endif

View file

@ -26,6 +26,22 @@ static inline uint32_t get_time(void) {
return TIMERUS_CNTR_1US_0;
}
/**
* Returns the number of microseconds that have passed since a given get_time().
*/
static inline uint32_t get_time_since(uint32_t base) {
return get_time() - base;
}
/**
* Delays for a given number of microseconds.
*/
static inline void udelay(unsigned usecs)
{
uint32_t start = get_time();
while (get_time() - start < usecs) ;
}
__attribute__ ((noreturn)) void watchdog_reboot(void);
#endif

View file

@ -29,9 +29,8 @@ static inline uintptr_t get_physical_address(const void *addr) {
static inline uint32_t read32le(const volatile void *dword, size_t offset) {
uintptr_t addr = (uintptr_t)dword + offset;
uint32_t dst;
memcpy(&dst, (void *)addr, 4);
return dst;
volatile uint32_t *target = (uint32_t *)addr;
return *target;
}
static inline uint32_t read32be(const volatile void *dword, size_t offset) {
@ -40,9 +39,8 @@ static inline uint32_t read32be(const volatile void *dword, size_t offset) {
static inline uint64_t read64le(const volatile void *qword, size_t offset) {
uintptr_t addr = (uintptr_t)qword + offset;
uint64_t dst;
memcpy(&dst, (void *)addr, 8);
return dst;
volatile uint64_t *target = (uint64_t *)addr;
return *target;
}
static inline uint64_t read64be(const volatile void *qword, size_t offset) {
@ -50,7 +48,9 @@ static inline uint64_t read64be(const volatile void *qword, size_t offset) {
}
static inline void write32le(volatile void *dword, size_t offset, uint32_t value) {
memcpy((void *)((uintptr_t)dword + offset), &value, 4);
uintptr_t addr = (uintptr_t)dword + offset;
volatile uint32_t *target = (uint32_t *)addr;
*target = value;
}
static inline void write32be(volatile void *dword, size_t offset, uint32_t value) {
@ -58,7 +58,9 @@ static inline void write32be(volatile void *dword, size_t offset, uint32_t value
}
static inline void write64le(volatile void *qword, size_t offset, uint64_t value) {
memcpy((void *)((uintptr_t)qword + offset), &value, 8);
uintptr_t addr = (uintptr_t)qword + offset;
volatile uint64_t *target = (uint64_t *)addr;
*target = value;
}
static inline void write64be(volatile void *qword, size_t offset, uint64_t value) {
@ -69,9 +71,9 @@ static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) {
return __builtin_add_overflow_p(a, b, (uint32_t)0);
}
__attribute__ ((noreturn)) void panic(uint32_t code);
__attribute__ ((noreturn)) void generic_panic(void);
__attribute__ ((noreturn)) void panic_predefined(uint32_t which);
void panic(uint32_t code);
void generic_panic(void);
void panic_predefined(uint32_t which);
bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be);
#endif