mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-26 05:42:17 +00:00
fusee: SDMMC driver re-design:
- Based on hekate's, linux's and u-boot's source code; - Full support for SD and MMC; - Fixes multiple issues; - Deployed first in fusee-primary. fusee: Code cleanup and style fixes.
This commit is contained in:
parent
83c9747e5f
commit
ddbbb0b758
30 changed files with 5077 additions and 4709 deletions
|
@ -18,7 +18,7 @@ include $(DEVKITARM)/base_rules
|
|||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := src src/lib src/lib/fatfs src/display src/hwinit
|
||||
SOURCES := src src/sdmmc src/hwinit src/lib src/lib/fatfs src/display
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
#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)
|
||||
#ifndef FUSEE_APB_MISC_H
|
||||
#define FUSEE_APB_MISC_H
|
||||
|
||||
#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20)
|
||||
#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12)
|
||||
|
@ -21,4 +11,44 @@
|
|||
#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT)
|
||||
#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT)
|
||||
|
||||
#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8)
|
||||
#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4)
|
||||
#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8)
|
||||
#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4)
|
||||
#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC1_CD_SOURCE (1 << 0)
|
||||
#define PADCTL_SDMMC1_WP_SOURCE (1 << 1)
|
||||
#define PADCTL_SDMMC3_CD_SOURCE (1 << 2)
|
||||
#define PADCTL_SDMMC3_WP_SOURCE (1 << 3)
|
||||
|
||||
typedef struct {
|
||||
uint32_t asdbgreg; /* 0x810 */
|
||||
uint32_t reserved0[0x31];
|
||||
uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */
|
||||
uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */
|
||||
uint32_t emmc2_pad_cfg_control; /* 0x8DC */
|
||||
uint32_t emmc4_pad_cfg_control; /* 0x8E0 */
|
||||
uint32_t _todo0[0x6E];
|
||||
uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */
|
||||
uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */
|
||||
uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */
|
||||
uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */
|
||||
uint32_t _todo1[0x03];
|
||||
uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */
|
||||
uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */
|
||||
uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */
|
||||
uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */
|
||||
uint32_t _todo2[0x2E];
|
||||
uint32_t vgpio_gpio_mux_sel; /* 0xB74 */
|
||||
uint32_t qspi_sck_lpbk_control; /* 0xB78 */
|
||||
} tegra_padctl_t;
|
||||
|
||||
static inline volatile tegra_padctl_t *padctl_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_padctl_t *)0x70000810;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,95 +1,68 @@
|
|||
#ifndef FUSEE_CAR_H
|
||||
#define FUSEE_CAR_H
|
||||
|
||||
#ifndef __FUSEE_CLOCK_H__
|
||||
#define __FUSEE_CLOCK_H__
|
||||
#define CLK_SOURCE_SDMMC1 20
|
||||
#define CLK_SOURCE_SDMMC2 21
|
||||
#define CLK_SOURCE_SDMMC3 47
|
||||
#define CLK_SOURCE_SDMMC4 25
|
||||
#define CLK_SOURCE_SDMMC_LEGACY 0
|
||||
|
||||
#include "utils.h"
|
||||
#define CLK_L_SDMMC1 (1 << 14)
|
||||
#define CLK_L_SDMMC2 (1 << 9)
|
||||
#define CLK_U_SDMMC3 (1 << 5)
|
||||
#define CLK_L_SDMMC4 (1 << 15)
|
||||
|
||||
/**
|
||||
* Struct definition yanked from u-boot.
|
||||
*/
|
||||
#define TEGRA_CLK_PLLS 6 /* Number of normal PLLs */
|
||||
#define TEGRA_CLK_SIMPLE_PLLS 3 /* Number of simple PLLs */
|
||||
#define TEGRA_CLK_SOURCES 64 /* Number of ppl clock sources L/H/U */
|
||||
#define TEGRA_CLK_SOURCES_VW 32 /* Number of ppl clock sources V/W */
|
||||
#define TEGRA_CLK_SOURCES_X 32 /* Number of ppl clock sources X */
|
||||
#define TEGRA_CLK_SOURCES_Y 18 /* Number of ppl clock sources Y */
|
||||
|
||||
#define CLK_SOURCE_MASK (0b111 << 29)
|
||||
#define CLK_SOURCE_FIRST (0b000 << 29)
|
||||
#define CLK_DIVIDER_MASK (0xff << 0)
|
||||
#define CLK_DIVIDER_UNITY (0x00 << 0)
|
||||
|
||||
#define CAR_CONTROL_SDMMC1 (1 << 14)
|
||||
#define CAR_CONTROL_SDMMC4 (1 << 15)
|
||||
#define CAR_CONTROL_SDMMC_LEGACY (1 << 1)
|
||||
|
||||
/* PLL registers - there are several PLLs in the clock controller */
|
||||
struct clk_pll {
|
||||
typedef struct {
|
||||
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 */
|
||||
};
|
||||
} clk_pll_t;
|
||||
|
||||
/* PLL registers - there are several PLLs in the clock controller */
|
||||
struct clk_pll_simple {
|
||||
typedef struct {
|
||||
uint32_t pll_base; /* the control register */
|
||||
uint32_t pll_misc; /* other misc things */
|
||||
};
|
||||
} clk_pll_simple_t;
|
||||
|
||||
struct clk_pllm {
|
||||
typedef struct {
|
||||
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_SDMMC1_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */
|
||||
CLK_SOURCE_SDMMC4_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */
|
||||
CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ = (0b001 << 29), /* 199.68 MHz */
|
||||
CLK_SOURCE_SDMMC_LEGACY_PLLP_OUT0 = (0b100 << 29), /* Fixed 408 MHz */
|
||||
|
||||
CLK_DIVIDER_MASK = (0xff << 0),
|
||||
CLK_DIVIDER_UNITY = (0x00 << 0),
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reset bits for relevant registers.
|
||||
*/
|
||||
enum {
|
||||
CAR_CONTROL_SDMMC1 = (1 << 14),
|
||||
CAR_CONTROL_SDMMC4 = (1 << 15),
|
||||
CAR_CONTROL_SDMMC_LEGACY = (1 << 1),
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
CLK_SOURCE_SDMMC1 = 20,
|
||||
CLK_SOURCE_SDMMC4 = 25, /* 0x54 into the the main source block */
|
||||
|
||||
CLK_SOURCE_SDMMC_LEGACY = 0, /* first in block Y */
|
||||
};
|
||||
|
||||
} clk_pllm_t;
|
||||
|
||||
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
|
||||
struct tegra_car {
|
||||
typedef struct {
|
||||
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 clk_out_enb_l;
|
||||
uint32_t clk_out_enb_h;
|
||||
uint32_t clk_out_enb_u;
|
||||
|
||||
uint32_t reserved0; /* reserved_0, 0x1C */
|
||||
uint32_t reserved0; /* reserved_0, 0x1C */
|
||||
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
|
||||
uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0,0x24 */
|
||||
uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */
|
||||
|
@ -97,21 +70,21 @@ struct tegra_car {
|
|||
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 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_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 */
|
||||
clk_pll_t pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */
|
||||
|
||||
/* PLLs from 0xe0 to 0xf4 */
|
||||
struct clk_pll_simple pll_simple[TEGRA_CLK_SIMPLE_PLLS];
|
||||
clk_pll_simple_t pll_simple[TEGRA_CLK_SIMPLE_PLLS];
|
||||
|
||||
uint32_t reserved10; /* _reserved_10, 0xF8 */
|
||||
uint32_t reserved11; /* _reserved_11, 0xFC */
|
||||
|
@ -171,11 +144,11 @@ struct tegra_car {
|
|||
|
||||
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 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 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 */
|
||||
|
@ -186,8 +159,8 @@ struct tegra_car {
|
|||
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 */
|
||||
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;
|
||||
|
@ -210,18 +183,18 @@ struct tegra_car {
|
|||
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 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 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 */
|
||||
|
@ -231,68 +204,65 @@ struct tegra_car {
|
|||
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 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 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 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 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 */
|
||||
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 */
|
||||
clk_pll_simple_t 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 */
|
||||
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 */
|
||||
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 */
|
||||
};
|
||||
} tegra_car_t;
|
||||
|
||||
|
||||
/**
|
||||
* Utility function that grabs the Tegra CAR registers.
|
||||
*/
|
||||
static inline struct tegra_car *car_get_regs(void)
|
||||
static inline volatile tegra_car_t *car_get_regs(void)
|
||||
{
|
||||
return (struct tegra_car *)0x60006000UL;
|
||||
return (volatile tegra_car_t *)0x60006000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,36 +1,114 @@
|
|||
#include "fs_utils.h"
|
||||
#include "hwinit.h"
|
||||
#include "sdmmc.h"
|
||||
#include "lib/printk.h"
|
||||
#include "lib/fatfs/ff.h"
|
||||
|
||||
FATFS sd_fs;
|
||||
static int mounted_sd = 0;
|
||||
static bool g_sd_mounted = false;
|
||||
static bool g_sd_initialized = false;
|
||||
static bool g_ahb_redirect_enabled = false;
|
||||
|
||||
int mount_sd(void) {
|
||||
if (mounted_sd) {
|
||||
return 1;
|
||||
bool mount_sd(void)
|
||||
{
|
||||
/* Already mounted. */
|
||||
if (g_sd_mounted)
|
||||
return true;
|
||||
|
||||
/* Enable AHB redirection if necessary. */
|
||||
if (!g_ahb_redirect_enabled) {
|
||||
mc_enable_ahb_redirect();
|
||||
g_ahb_redirect_enabled = true;
|
||||
}
|
||||
if (f_mount(&sd_fs, "", 1) == FR_OK) {
|
||||
printk("Mounted SD card!\n");
|
||||
mounted_sd = 1;
|
||||
|
||||
if (!g_sd_initialized) {
|
||||
/* Initialize SD. */
|
||||
if (sdmmc_device_sd_init(&g_sd_device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SDR104))
|
||||
{
|
||||
g_sd_initialized = true;
|
||||
|
||||
/* Mount SD. */
|
||||
if (f_mount(&sd_fs, "", 1) == FR_OK) {
|
||||
printk("Mounted SD card!\n");
|
||||
g_sd_mounted = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
fatal_error("Failed to initialize the SD card!.\n");
|
||||
}
|
||||
return mounted_sd;
|
||||
|
||||
return g_sd_mounted;
|
||||
}
|
||||
|
||||
size_t read_from_file(void *dst, size_t dst_size, const char *filename) {
|
||||
if (!mounted_sd && mount_sd() == 0) {
|
||||
return 0;
|
||||
void unmount_sd(void)
|
||||
{
|
||||
if (g_sd_mounted)
|
||||
{
|
||||
f_mount(NULL, "", 1);
|
||||
sdmmc_device_finish(&g_sd_device);
|
||||
g_sd_mounted = false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t get_file_size(const char *filename)
|
||||
{
|
||||
/* SD card hasn't been mounted yet. */
|
||||
if (!g_sd_mounted)
|
||||
return 0;
|
||||
|
||||
/* Open the file for reading. */
|
||||
FIL f;
|
||||
if (f_open(&f, filename, FA_READ) != FR_OK) {
|
||||
if (f_open(&f, filename, FA_READ) != FR_OK)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the file size. */
|
||||
uint32_t file_size = f_size(&f);
|
||||
|
||||
/* Close the file. */
|
||||
f_close(&f);
|
||||
|
||||
return file_size;
|
||||
}
|
||||
|
||||
UINT br;
|
||||
int read_from_file(void *dst, uint32_t dst_size, const char *filename)
|
||||
{
|
||||
/* SD card hasn't been mounted yet. */
|
||||
if (!g_sd_mounted)
|
||||
return 0;
|
||||
|
||||
/* Open the file for reading. */
|
||||
FIL f;
|
||||
if (f_open(&f, filename, FA_READ) != FR_OK)
|
||||
return 0;
|
||||
|
||||
/* Sync. */
|
||||
f_sync(&f);
|
||||
|
||||
/* Read from file. */
|
||||
UINT br = 0;
|
||||
int res = f_read(&f, dst, dst_size, &br);
|
||||
f_close(&f);
|
||||
|
||||
return res == FR_OK ? (int)br : 0;
|
||||
return (res == FR_OK) ? (int)br : 0;
|
||||
}
|
||||
|
||||
int write_to_file(void *src, uint32_t src_size, const char *filename)
|
||||
{
|
||||
/* SD card hasn't been mounted yet. */
|
||||
if (!g_sd_mounted)
|
||||
return 0;
|
||||
|
||||
/* Open the file for writing. */
|
||||
FIL f;
|
||||
if (f_open(&f, filename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
|
||||
return 0;
|
||||
|
||||
/* Sync. */
|
||||
f_sync(&f);
|
||||
|
||||
/* Write to file. */
|
||||
UINT bw = 0;
|
||||
int res = f_write(&f, src, src_size, &bw);
|
||||
f_close(&f);
|
||||
|
||||
return (res == FR_OK) ? (int)bw : 0;
|
||||
}
|
|
@ -1,9 +1,19 @@
|
|||
#ifndef FUSEE_FS_UTILS_H
|
||||
#define FUSEE_FS_UTILS_H
|
||||
|
||||
#include "utils.h"
|
||||
#include "sdmmc.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
size_t read_from_file(void *dst, size_t dst_size, const char *filename);
|
||||
#include "sdmmc/sdmmc.h"
|
||||
#include "utils.h"
|
||||
|
||||
sdmmc_t g_sd_sdmmc;
|
||||
sdmmc_device_t g_sd_device;
|
||||
|
||||
bool mount_sd(void);
|
||||
void unmount_sd(void);
|
||||
uint32_t get_file_size(const char *filename);
|
||||
int read_from_file(void *dst, uint32_t dst_size, const char *filename);
|
||||
int write_to_file(void *src, uint32_t src_size, const char *filename);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hwinit.h"
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
#ifndef FUSEE_FUSE_H
|
||||
#define FUSEE_FUSE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_CTRL;
|
||||
uint32_t FUSE_REG_ADDR;
|
||||
|
|
|
@ -3,18 +3,9 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "gpio.h"
|
||||
#include "utils.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.
|
||||
|
@ -22,35 +13,31 @@ enum tegra_gpio_masks {
|
|||
* @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)
|
||||
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin)
|
||||
{
|
||||
volatile struct tegra_gpio *gpio = gpio_get_regs();
|
||||
int bank_number = pin >> GPIO_BANK_SHIFT;
|
||||
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
||||
uint32_t 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)
|
||||
static volatile uint32_t gpio_get_port(uint32_t 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)
|
||||
static volatile uint32_t gpio_get_mask(uint32_t pin)
|
||||
{
|
||||
uint32_t pin_number = pin & GPIO_PIN_MASK;
|
||||
return (1 << pin_number);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Performs a simple GPIO configuration operation.
|
||||
*
|
||||
|
@ -58,7 +45,7 @@ static volatile uint32_t gpio_get_mask(enum tegra_named_gpio pin)
|
|||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
||||
* @param offset The offset into a gpio_bank structure
|
||||
*/
|
||||
static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_set, size_t offset)
|
||||
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset)
|
||||
{
|
||||
// Retrieve the register set that corresponds to the given pin and offset.
|
||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||
|
@ -66,10 +53,9 @@ static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_s
|
|||
|
||||
// Figure out the offset into the cluster,
|
||||
// and the mask to be used.
|
||||
int port = gpio_get_port(pin);
|
||||
uint32_t port = gpio_get_port(pin);
|
||||
uint32_t mask = gpio_get_mask(pin);
|
||||
|
||||
|
||||
// Set or clear the bit, as appropriate.
|
||||
if (should_be_set)
|
||||
cluster[port] |= mask;
|
||||
|
@ -77,7 +63,6 @@ static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_s
|
|||
cluster[port] &= ~mask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs a simple GPIO configuration operation.
|
||||
*
|
||||
|
@ -85,7 +70,7 @@ static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_s
|
|||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
||||
* @param offset The offset into a gpio_bank structure
|
||||
*/
|
||||
static bool gpio_simple_register_get(enum tegra_named_gpio pin, size_t offset)
|
||||
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset)
|
||||
{
|
||||
// Retrieve the register set that corresponds to the given pin and offset.
|
||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||
|
@ -93,57 +78,53 @@ static bool gpio_simple_register_get(enum tegra_named_gpio pin, size_t offset)
|
|||
|
||||
// Figure out the offset into the cluster,
|
||||
// and the mask to be used.
|
||||
int port = gpio_get_port(pin);
|
||||
uint32_t port = gpio_get_port(pin);
|
||||
uint32_t mask = gpio_get_mask(pin);
|
||||
|
||||
// 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)
|
||||
void gpio_configure_mode(uint32_t pin, uint32_t mode)
|
||||
{
|
||||
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(struct tegra_gpio_bank, config));
|
||||
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configures a given pin as either INPUT or OUPUT.
|
||||
*
|
||||
* @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)
|
||||
void gpio_configure_direction(uint32_t pin, uint32_t dir)
|
||||
{
|
||||
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(struct tegra_gpio_bank, direction));
|
||||
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
||||
*
|
||||
* @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)
|
||||
void gpio_write(uint32_t pin, uint32_t value)
|
||||
{
|
||||
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(struct tegra_gpio_bank, out));
|
||||
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
||||
*
|
||||
* @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)
|
||||
uint32_t gpio_read(uint32_t pin)
|
||||
{
|
||||
return gpio_simple_register_get(pin, offsetof(struct tegra_gpio_bank, in));
|
||||
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
||||
}
|
||||
|
|
|
@ -1,19 +1,14 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
|
||||
#ifndef __FUSEE_GPIO_H__
|
||||
#define __FUSEE_GPIO_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "utils.h"
|
||||
|
||||
enum tegra_gpio_port {
|
||||
#define TEGRA_GPIO_PORTS 4
|
||||
#define TEGRA_GPIO_BANKS 8
|
||||
#define GPIO_BANK_SHIFT 5
|
||||
#define GPIO_PORT_SHIFT 3
|
||||
#define GPIO_PORT_MASK 0x03
|
||||
#define GPIO_PIN_MASK 0x07
|
||||
|
||||
typedef enum {
|
||||
TEGRA_GPIO_PORT_A = 0,
|
||||
TEGRA_GPIO_PORT_B = 1,
|
||||
TEGRA_GPIO_PORT_C = 2,
|
||||
|
@ -46,25 +41,9 @@ enum tegra_gpio_port {
|
|||
TEGRA_GPIO_PORT_DD = 29,
|
||||
TEGRA_GPIO_PORT_EE = 30,
|
||||
TEGRA_GPIO_PORT_FF = 31,
|
||||
};
|
||||
} tegra_gpio_port;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
typedef struct {
|
||||
uint32_t config[TEGRA_GPIO_PORTS];
|
||||
uint32_t direction[TEGRA_GPIO_PORTS];
|
||||
uint32_t out[TEGRA_GPIO_PORTS];
|
||||
|
@ -81,94 +60,40 @@ struct tegra_gpio_bank {
|
|||
uint32_t masked_int_enable[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_int_level[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_int_clear[TEGRA_GPIO_PORTS];
|
||||
};
|
||||
} tegra_gpio_bank_t;
|
||||
|
||||
typedef struct {
|
||||
tegra_gpio_bank_t bank[TEGRA_GPIO_BANKS];
|
||||
} tegra_gpio_t;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static inline volatile tegra_gpio_t *gpio_get_regs(void)
|
||||
{
|
||||
return (struct tegra_gpio *)0x6000d000;
|
||||
return (volatile tegra_gpio_t *)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);
|
||||
#define TEGRA_GPIO(port, offset) \
|
||||
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
||||
|
||||
/* Mode select */
|
||||
#define GPIO_MODE_GPIO 0
|
||||
#define GPIO_MODE_SFIO 1
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/* Direction */
|
||||
#define GPIO_DIRECTION_INPUT 0
|
||||
#define GPIO_DIRECTION_OUTPUT 1
|
||||
|
||||
/* Level */
|
||||
#define GPIO_LEVEL_LOW 0
|
||||
#define GPIO_LEVEL_HIGH 1
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/* Named GPIOs */
|
||||
#define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1)
|
||||
#define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4)
|
||||
#define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4)
|
||||
|
||||
/**
|
||||
* 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);
|
||||
void gpio_configure_mode(uint32_t pin, uint32_t mode);
|
||||
void gpio_configure_direction(uint32_t pin, uint32_t dir);
|
||||
void gpio_write(uint32_t pin, uint32_t value);
|
||||
uint32_t gpio_read(uint32_t pin);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,70 +9,18 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "diskio.h" /* FatFs lower layer API */
|
||||
#include "../../sdmmc.h"
|
||||
#include "../../hwinit.h"
|
||||
|
||||
static bool g_ahb_redirect_enabled = false;
|
||||
|
||||
/* Global sd struct. */
|
||||
struct mmc g_sd_mmc = {0};
|
||||
static bool g_sd_initialized = false;
|
||||
|
||||
int initialize_sd_mmc(void) {
|
||||
if (!g_ahb_redirect_enabled) {
|
||||
mc_enable_ahb_redirect();
|
||||
g_ahb_redirect_enabled = true;
|
||||
}
|
||||
|
||||
if (!g_sd_initialized) {
|
||||
int rc = sdmmc_init(&g_sd_mmc, SWITCH_MICROSD, false);
|
||||
if (rc == 0) {
|
||||
g_sd_initialized = true;
|
||||
return 0;
|
||||
} else {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Uncomment if needed:
|
||||
static struct mmc nand_mmc = {0};
|
||||
static bool g_nand_initialized = false;
|
||||
|
||||
int initialize_nand_mmc(void) {
|
||||
if (!g_ahb_redirect_enabled) {
|
||||
mc_enable_ahb_redirect();
|
||||
g_ahb_redirect_enabled = true;
|
||||
}
|
||||
|
||||
if (!g_nand_initialized) {
|
||||
int rc = sdmmc_init(&g_sd_mmc, SWITCH_EMMC);
|
||||
if (rc == 0) {
|
||||
g_nand_initialized = true;
|
||||
return 0;
|
||||
} else {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
#include "diskio.h" /* FatFs lower layer API */
|
||||
#include "../../fs_utils.h"
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get Drive Status */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,15 +30,10 @@ DSTATUS disk_status (
|
|||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
switch (pdrv) {
|
||||
case 0:
|
||||
return initialize_sd_mmc() == 0 ? 0 : STA_NOINIT;
|
||||
default:
|
||||
return STA_NODISK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,18 +43,18 @@ DSTATUS disk_initialize (
|
|||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
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 */
|
||||
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 */
|
||||
)
|
||||
{
|
||||
switch (pdrv) {
|
||||
case 0:
|
||||
return sdmmc_read(&g_sd_mmc, buff, sector, count) == 0 ? RES_OK : RES_ERROR;
|
||||
default:
|
||||
return RES_PARERR;
|
||||
}
|
||||
switch (pdrv) {
|
||||
case 0:
|
||||
return sdmmc_device_read(&g_sd_device, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
default:
|
||||
return RES_PARERR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,18 +64,18 @@ DRESULT disk_read (
|
|||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
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 */
|
||||
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 */
|
||||
)
|
||||
{
|
||||
switch (pdrv) {
|
||||
case 0:
|
||||
return sdmmc_write(&g_sd_mmc, buff, sector, count) == 0 ? RES_OK : RES_ERROR;
|
||||
default:
|
||||
return RES_PARERR;
|
||||
}
|
||||
switch (pdrv) {
|
||||
case 0:
|
||||
return sdmmc_device_write(&g_sd_device, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
default:
|
||||
return RES_PARERR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -142,11 +85,11 @@ DRESULT disk_write (
|
|||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_ioctl (
|
||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||
BYTE cmd, /* Control code */
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||
BYTE cmd, /* Control code */
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "fs_utils.h"
|
||||
#include "stage2.h"
|
||||
#include "chainloader.h"
|
||||
#include "sdmmc.h"
|
||||
#include "sdmmc/sdmmc.h"
|
||||
#include "lib/fatfs/ff.h"
|
||||
#include "lib/printk.h"
|
||||
#include "display/video_fb.h"
|
||||
|
@ -89,10 +89,14 @@ static void setup_env(void) {
|
|||
|
||||
/* Set up the exception handlers. */
|
||||
setup_exception_handlers();
|
||||
|
||||
/* Mount the SD card. */
|
||||
mount_sd();
|
||||
}
|
||||
|
||||
static void cleanup_env(void) {
|
||||
f_unmount("");
|
||||
/* Unmount the SD card. */
|
||||
unmount_sd();
|
||||
|
||||
display_enable_backlight(false);
|
||||
display_end();
|
||||
|
@ -108,12 +112,13 @@ int main(void) {
|
|||
const char *stage2_path;
|
||||
stage2_args_t *stage2_args;
|
||||
uint32_t stage2_version = 0;
|
||||
extern struct mmc g_sd_mmc;
|
||||
|
||||
sdmmc_set_loglevel(2);
|
||||
/* Set the SDMMC's driver logging level. */
|
||||
sdmmc_set_log_level(SDMMC_LOG_INFO);
|
||||
|
||||
/* Initialize the display, console, etc. */
|
||||
setup_env();
|
||||
|
||||
|
||||
/* Say hello. */
|
||||
printk("Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
|
||||
printk("Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
||||
|
@ -137,7 +142,7 @@ int main(void) {
|
|||
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
|
||||
memcpy(&stage2_args->version, &stage2_version, 4);
|
||||
stage2_args->display_initialized = false;
|
||||
memcpy(&stage2_args->sd_mmc, &g_sd_mmc, sizeof(g_sd_mmc));
|
||||
memcpy(&stage2_args->sd_sdmmc, &g_sd_sdmmc, sizeof(g_sd_sdmmc));
|
||||
strcpy(stage2_args->bct0, bct0);
|
||||
g_chainloader_argc = 2;
|
||||
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
/**
|
||||
* Fusée pad control code
|
||||
* ~ktemkin
|
||||
*/
|
||||
|
||||
#ifndef __FUSEE_PADCTL_H__
|
||||
#define __FUSEE_PADCTL_H__
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* Registers in the Misc Pad control region
|
||||
*/
|
||||
struct tegra_padctl {
|
||||
/* TODO: support registers before? */
|
||||
uint32_t sdmmc1_control;
|
||||
uint32_t sdmmc3_control;
|
||||
uint32_t sdmmc2_control;
|
||||
uint32_t sdmmc4_control;
|
||||
|
||||
/* TODO: support registers after? */
|
||||
uint8_t _todo[656];
|
||||
|
||||
uint32_t vgpio_gpio_mux_sel;
|
||||
};
|
||||
|
||||
/**
|
||||
* Masks for Pad Control registers
|
||||
*/
|
||||
enum tegra_padctl_masks {
|
||||
|
||||
/* SDMMC1 */
|
||||
PADCTL_SDMMC1_DEEP_LOOPBACK = (1 << 0),
|
||||
|
||||
/* SDMMC3 */
|
||||
PADCTL_SDMMC3_DEEP_LOOPBACK = (1 << 0),
|
||||
|
||||
/* SDMMC2 */
|
||||
PADCTL_SDMMC2_ENABLE_DATA_IN = (0xFF << 8),
|
||||
PADCTL_SDMMC2_ENABLE_CLK_IN = (0x3 << 4),
|
||||
PADCTL_SDMMC2_DEEP_LOOPBACK = (1 << 0),
|
||||
|
||||
/* SDMMC4 */
|
||||
PADCTL_SDMMC4_ENABLE_DATA_IN = (0xFF << 8),
|
||||
PADCTL_SDMMC4_ENABLE_CLK_IN = (0x3 << 4),
|
||||
PADCTL_SDMMC4_DEEP_LOOPBACK = (1 << 0),
|
||||
|
||||
/* VGPIO/GPIO */
|
||||
PADCTL_SDMMC1_CD_SOURCE = (1 << 0),
|
||||
PADCTL_SDMMC1_WP_SOURCE = (1 << 1),
|
||||
PADCTL_SDMMC3_CD_SOURCE = (1 << 2),
|
||||
PADCTL_SDMMC3_WP_SOURCE = (1 << 3),
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Utility function that grabs the Tegra PADCTL registers.
|
||||
*/
|
||||
static inline struct tegra_padctl *padctl_get_regs(void)
|
||||
{
|
||||
return (struct tegra_padctl *)0x700008d4;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef EXOSPHERE_PANIC_COLOR_H
|
||||
#define EXOSPHERE_PANIC_COLOR_H
|
||||
#ifndef FUSEE_PANIC_COLOR_H
|
||||
#define FUSEE_PANIC_COLOR_H
|
||||
|
||||
#define COLOR_0 0x00F00003
|
||||
#define COLOR_1 0x0F000003
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
#ifndef __FUSEE_PINMUX_H__
|
||||
#define __FUSEE_PINMUX_H__
|
||||
#ifndef FUSEE_PINMUX_H
|
||||
#define FUSEE_PINMUX_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "utils.h"
|
||||
#define PINMUX_TRISTATE (1 << 4)
|
||||
#define PINMUX_PARKED (1 << 5)
|
||||
#define PINMUX_INPUT (1 << 6)
|
||||
#define PINMUX_PULL_NONE (0 << 2)
|
||||
#define PINMUX_PULL_DOWN (1 << 2)
|
||||
#define PINMUX_PULL_UP (2 << 2)
|
||||
#define PINMUX_SELECT_FUNCTION0 0
|
||||
#define PINMUX_SELECT_FUNCTION1 1
|
||||
#define PINMUX_SELECT_FUNCTION2 2
|
||||
#define PINMUX_SELECT_FUNCTION3 3
|
||||
#define PINMUX_DRIVE_1X (0 << 13)
|
||||
#define PINMUX_DRIVE_2X (1 << 13)
|
||||
#define PINMUX_DRIVE_3X (2 << 13)
|
||||
#define PINMUX_DRIVE_4X (3 << 13)
|
||||
|
||||
/**
|
||||
* Pinmux structures.
|
||||
*/
|
||||
struct tegra_pinmux {
|
||||
typedef struct {
|
||||
uint32_t sdmmc1_clk;
|
||||
uint32_t sdmmc1_cmd;
|
||||
uint32_t sdmmc1_dat3;
|
||||
|
@ -174,48 +182,11 @@ struct tegra_pinmux {
|
|||
uint32_t pz3;
|
||||
uint32_t pz4;
|
||||
uint32_t pz5;
|
||||
};
|
||||
} tegra_pinmux_t;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static inline volatile tegra_pinmux_t *pinmux_get_regs(void)
|
||||
{
|
||||
return (struct tegra_pinmux *)0x70003000;
|
||||
return (volatile tegra_pinmux_t *)0x70003000;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,37 +1,27 @@
|
|||
#ifndef __FUSEE_PMC_H__
|
||||
#define __FUSEE_PMC_H__
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define PMC_BASE 0x7000E400
|
||||
|
||||
#ifndef FUSEE_PMC_H
|
||||
#define FUSEE_PMC_H
|
||||
|
||||
/* TODO: get rid of these defines; use the struct instead */
|
||||
#define PMC_BASE 0x7000E400
|
||||
|
||||
#define PMC_CONTROL_SDMMC1 (1 << 12)
|
||||
#define PMC_CONTROL_SDMMC3 (1 << 13)
|
||||
#define PMC_CONTROL_SDMMC4 (1 << 14)
|
||||
|
||||
#define APBDEV_PMC_CONTROL MAKE_REG32(PMC_BASE + 0x00)
|
||||
|
||||
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24)
|
||||
|
||||
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30)
|
||||
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_REG32(PMC_BASE + 0x38)
|
||||
|
||||
#define APBDEV_PMC_SCRATCH0_0 MAKE_REG32(PMC_BASE + 0x50)
|
||||
|
||||
#define APBDEV_PMC_CRYPTO_OP_0 MAKE_REG32(PMC_BASE + 0xF4)
|
||||
|
||||
#define APBDEV_PM_0 MAKE_REG32(PMC_BASE + 0x14)
|
||||
#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_REG32(PMC_BASE + 0x168)
|
||||
#define APBDEV_PMC_RST_STATUS_0 MAKE_REG32(PMC_BASE + 0x1B4)
|
||||
#define APBDEV_PMC_CNTRL2_0 MAKE_REG32(PMC_BASE + 0x440)
|
||||
|
||||
#define APBDEV_PMC_SCRATCH43_0 MAKE_REG32(PMC_BASE + 0x22C)
|
||||
|
||||
#define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840)
|
||||
|
||||
/**
|
||||
* Definitions of the Tegra PMC.
|
||||
* NOTE: Incomplete, do not use
|
||||
*/
|
||||
struct tegra_pmc {
|
||||
typedef struct {
|
||||
uint32_t cntrl;
|
||||
uint32_t sec_disable;
|
||||
uint32_t pmc_swrst;
|
||||
|
@ -297,23 +287,11 @@ struct tegra_pmc {
|
|||
uint32_t scratch118;
|
||||
uint32_t scratch119;
|
||||
uint32_t scratch1_eco;
|
||||
};
|
||||
} tegra_pmc_t;
|
||||
|
||||
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 PMC registers.
|
||||
*/
|
||||
static inline volatile struct tegra_pmc *pmc_get_regs(void)
|
||||
static inline volatile tegra_pmc_t *pmc_get_regs(void)
|
||||
{
|
||||
return (volatile struct tegra_pmc *)0x7000E400;
|
||||
return (volatile tegra_pmc_t *)0x7000E400;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,313 +0,0 @@
|
|||
/**
|
||||
* Fusée SD/MMC driver for the Switch
|
||||
* ~ktemkin
|
||||
*/
|
||||
|
||||
#ifndef __FUSEE_SDMMC_H__
|
||||
#define __FUSEE_SDMMC_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "utils.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/* Opaque pointer to the Tegra SDMMC registers */
|
||||
struct tegra_sdmmc;
|
||||
|
||||
|
||||
/**
|
||||
* Bus widths supported by the SD/MMC cards.
|
||||
*/
|
||||
enum sdmmc_bus_width {
|
||||
MMC_BUS_WIDTH_1BIT = 0,
|
||||
MMC_BUS_WIDTH_4BIT = 1,
|
||||
MMC_BUS_WIDTH_8BIT = 2,
|
||||
|
||||
SD_BUS_WIDTH_1BIT = 0,
|
||||
SD_BUS_WIDTH_4BIT = 2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Describes the voltages that the host will use to drive the SD card.
|
||||
* CAUTION: getting these wrong can damage (especially embedded) cards!
|
||||
*/
|
||||
enum sdmmc_bus_voltage {
|
||||
MMC_VOLTAGE_3V3 = 0b111,
|
||||
MMC_VOLTAGE_1V8 = 0b101,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Represents the different types of devices an MMC object
|
||||
* can represent.
|
||||
*/
|
||||
enum sdmmc_card_type {
|
||||
MMC_CARD_EMMC,
|
||||
MMC_CARD_MMC,
|
||||
MMC_CARD_SD,
|
||||
MMC_CARD_CART,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specification versions for SD/MMC cards.
|
||||
*/
|
||||
enum sdmmc_spec_version {
|
||||
|
||||
/* MMC card versions */
|
||||
MMC_VERSION_4 = 0,
|
||||
|
||||
/* SD card versions */
|
||||
SD_VERSION_1_0 = 0,
|
||||
SD_VERSION_1_1 = 1,
|
||||
SD_VERSION_2_0 = 2,
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* SDMMC controllers
|
||||
*/
|
||||
enum sdmmc_controller {
|
||||
SWITCH_MICROSD = 0,
|
||||
SWITCH_EMMC = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* Write permission modes for SD cards.
|
||||
*/
|
||||
enum sdmmc_write_permission {
|
||||
SDMMC_WRITE_DISABLED,
|
||||
SDMMC_WRITE_ENABLED,
|
||||
|
||||
/* use this with the utmost caution so you don't wind up with a brick */
|
||||
SDMMC_WRITE_ENABLED_INCLUDING_EMMC,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Methods by which we can touch registers accessed via.
|
||||
* CMD_SWITCH_MODE.
|
||||
*/
|
||||
enum sdmmc_switch_access_mode {
|
||||
|
||||
/* Normal commands */
|
||||
MMC_SWITCH_MODE_CMD_SET = 0,
|
||||
MMC_SWITCH_MODE_SET_BITS = 1,
|
||||
MMC_SWITCH_MODE_CLEAR_BITS = 2,
|
||||
MMC_SWITCH_MODE_WRITE_BYTE = 3,
|
||||
|
||||
/* EXTCSD access */
|
||||
MMC_SWITCH_EXTCSD_NORMAL = 1,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Offsets into the SWITCH_MODE argument.
|
||||
*/
|
||||
enum sdmmc_switch_argument_offsets {
|
||||
MMC_SWITCH_VALUE_SHIFT = 8,
|
||||
MMC_SWITCH_FIELD_SHIFT = 16,
|
||||
MMC_SWITCH_ACCESS_MODE_SHIFT = 24,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Bus speeds possible for an SDMMC controller.
|
||||
*/
|
||||
enum sdmmc_bus_speed {
|
||||
/* SD card speeds */
|
||||
SDMMC_SPEED_SDR12 = 0,
|
||||
SDMMC_SPEED_SDR25 = 1,
|
||||
SDMMC_SPEED_SDR50 = 2,
|
||||
SDMMC_SPEED_SDR104 = 3,
|
||||
SDMMC_SPEED_DDR50 = 4,
|
||||
|
||||
/* Other speed: non-spec-compliant value used for e.g. HS400 */
|
||||
SDMMC_SPEED_OTHER = 5,
|
||||
|
||||
/* eMMC card speeds */
|
||||
/* note: to avoid an enum clash, we add ten to these */
|
||||
SDMMC_SPEED_HS26 = 10 ,
|
||||
SDMMC_SPEED_HS52 = 11 ,
|
||||
SDMMC_SPEED_HS200 = 12 ,
|
||||
SDMMC_SPEED_HS400 = 13 ,
|
||||
|
||||
/* special speeds */
|
||||
SDMMC_SPEED_INIT = -1,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Primary data structure describing a Fusée MMC driver.
|
||||
*/
|
||||
struct mmc {
|
||||
enum sdmmc_controller controller;
|
||||
|
||||
/* Controller properties */
|
||||
const char *name;
|
||||
bool use_dma;
|
||||
bool allow_voltage_switching;
|
||||
unsigned int timeout;
|
||||
enum tegra_named_gpio card_detect_gpio;
|
||||
enum sdmmc_write_permission write_enable;
|
||||
|
||||
/* Per-controller operations. */
|
||||
int (*set_up_clock_and_io)(struct mmc *mmc);
|
||||
void (*configure_clock)(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor);
|
||||
int (*enable_supplies)(struct mmc *mmc);
|
||||
int (*switch_to_low_voltage)(struct mmc *mmc);
|
||||
bool (*card_present)(struct mmc *mmc);
|
||||
|
||||
/* Per-card-type operations */
|
||||
int (*card_init)(struct mmc *mmc);
|
||||
int (*establish_relative_address)(struct mmc *mmc);
|
||||
int (*switch_mode)(struct mmc *mmc, int a, int b, int c, uint32_t timeout, void *response);
|
||||
int (*switch_bus_width)(struct mmc *mmc, enum sdmmc_bus_width width);
|
||||
int (*optimize_speed)(struct mmc *mmc);
|
||||
int (*card_switch_bus_speed)(struct mmc *mmc, enum sdmmc_bus_speed speed);
|
||||
|
||||
/* Card properties */
|
||||
enum sdmmc_card_type card_type;
|
||||
uint32_t mmc_card_type;
|
||||
|
||||
uint8_t cid[15];
|
||||
uint32_t relative_address;
|
||||
uint8_t partitioned;
|
||||
enum sdmmc_spec_version spec_version;
|
||||
enum sdmmc_bus_width max_bus_width;
|
||||
enum sdmmc_bus_voltage operating_voltage;
|
||||
enum sdmmc_bus_speed operating_speed;
|
||||
|
||||
uint8_t partition_support;
|
||||
uint8_t partition_config;
|
||||
uint8_t partition_attribute;
|
||||
uint32_t partition_switch_time;
|
||||
|
||||
uint8_t read_block_order;
|
||||
uint8_t write_block_order;
|
||||
uint8_t tuning_block_order;
|
||||
bool uses_block_addressing;
|
||||
|
||||
/* Current operation status flags */
|
||||
uint32_t active_data_buffer;
|
||||
|
||||
/* Pointers to hardware structures */
|
||||
volatile struct tegra_sdmmc *regs;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Primary data structure describing a Fusée MMC driver.
|
||||
*/
|
||||
struct mmc;
|
||||
|
||||
|
||||
/**
|
||||
* Parititions supported by the Switch eMMC.
|
||||
*/
|
||||
enum sdmmc_partition {
|
||||
SDMMC_PARTITION_USER = 0,
|
||||
SDMMC_PARTITION_BOOT0 = 1,
|
||||
SDMMC_PARTITION_BOOT1 = 2,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the current SDMMC debugging loglevel.
|
||||
*
|
||||
* @param loglevel Current log level. A higher value prints more logs.
|
||||
* @return The loglevel prior to when this was applied, for easy restoration.
|
||||
*/
|
||||
int sdmmc_set_loglevel(int loglevel);
|
||||
|
||||
|
||||
/**
|
||||
* Set up a new SDMMC driver.
|
||||
*
|
||||
* @param mmc The SDMMC structure to be initiailized with the device state.
|
||||
* @param controler The controller description to be used; usually SWITCH_EMMC
|
||||
* or SWITCH_MICROSD.
|
||||
* @param allow_voltage_switching True if we should allow voltage switching,
|
||||
* which may not make sense if we're about to chainload to another component without
|
||||
* preseving the overall structure.
|
||||
*/
|
||||
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching);
|
||||
|
||||
|
||||
/**
|
||||
* Imports a SDMMC driver struct from another program. This mainly intended for stage2,
|
||||
* so that it can reuse stage1's SDMMC struct instance(s).
|
||||
*
|
||||
* @param mmc The SDMMC structure to be imported.
|
||||
*/
|
||||
int sdmmc_import_struct(struct mmc *mmc);
|
||||
|
||||
|
||||
/**
|
||||
* Selects the active MMC partition. Can be used to select
|
||||
* boot partitions for access. Affects all operations going forward.
|
||||
*
|
||||
* @param mmc The MMC controller whose card is to be used.
|
||||
* @param partition The partition number to be selected.
|
||||
*
|
||||
* @return 0 on success, or an error code on failure.
|
||||
*/
|
||||
int sdmmc_select_partition(struct mmc *mmc, enum sdmmc_partition partition);
|
||||
|
||||
|
||||
/**
|
||||
* Reads a sector or sectors from a given SD card.
|
||||
*
|
||||
* @param mmc The MMC device to work with.
|
||||
* @param buffer The output buffer to target.
|
||||
* @param sector The sector number to read.
|
||||
* @param count The number of sectors to read.
|
||||
*/
|
||||
int sdmmc_read(struct mmc *mmc, void *buffer, uint32_t sector, unsigned int count);
|
||||
|
||||
|
||||
/**
|
||||
* Releases the SDMMC write lockout, enabling access to the card.
|
||||
* Note that by default, setting this to WRITE_ENABLED will not allow access to eMMC.
|
||||
* Check the source for a third constant that can be used to enable eMMC writes.
|
||||
*
|
||||
* @param perms The permissions to apply-- typically WRITE_DISABLED or WRITE_ENABLED.
|
||||
*/
|
||||
void sdmmc_set_write_enable(struct mmc *mmc, enum sdmmc_write_permission perms);
|
||||
|
||||
|
||||
/**
|
||||
* Writes a sector or sectors to a given SD/MMC card.
|
||||
*
|
||||
* @param mmc The MMC device to work with.
|
||||
* @param buffer The input buffer to write.
|
||||
* @param block The sector number to write from.
|
||||
* @param count The number of sectors to write.
|
||||
*
|
||||
* @return 0 on success, or an error code on failure.
|
||||
*/
|
||||
int sdmmc_write(struct mmc *mmc, const void *buffer, uint32_t block, unsigned int count);
|
||||
|
||||
|
||||
/**
|
||||
* Checks to see whether an SD card is present.
|
||||
*
|
||||
* @mmc mmc The controller with which to check for card presence.
|
||||
* @return true iff a card is present
|
||||
*/
|
||||
bool sdmmc_card_present(struct mmc *mmc);
|
||||
|
||||
/**
|
||||
* Prints out all of the tegra_mmc struct fields
|
||||
*
|
||||
* @mmc mmc The controller with which to dump registers.
|
||||
*/
|
||||
void sdmmc_dump_regs(struct mmc *mmc);
|
||||
|
||||
#endif
|
448
fusee/fusee-primary/src/sdmmc/mmc.h
Normal file
448
fusee/fusee-primary/src/sdmmc/mmc.h
Normal file
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* Header for MultiMediaCard (MMC)
|
||||
*
|
||||
* Copyright 2002 Hewlett-Packard Company
|
||||
*
|
||||
* Use consistent with the GNU GPL is permitted,
|
||||
* provided that this copyright notice is
|
||||
* preserved in its entirety in all copies and derived works.
|
||||
*
|
||||
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
|
||||
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
|
||||
* FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*
|
||||
* Many thanks to Alessandro Rubini and Jonathan Corbet!
|
||||
*
|
||||
* Based strongly on code by:
|
||||
*
|
||||
* Author: Yong-iL Joh <tolkien@mizi.com>
|
||||
*
|
||||
* Author: Andrew Christian
|
||||
* 15 May 2002
|
||||
*/
|
||||
|
||||
#ifndef LINUX_MMC_MMC_H
|
||||
#define LINUX_MMC_MMC_H
|
||||
|
||||
/* Standard MMC commands (4.1) type argument response */
|
||||
/* class 1 */
|
||||
#define MMC_GO_IDLE_STATE 0 /* bc */
|
||||
#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
|
||||
#define MMC_ALL_SEND_CID 2 /* bcr R2 */
|
||||
#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
|
||||
#define MMC_SET_DSR 4 /* bc [31:16] RCA */
|
||||
#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */
|
||||
#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
|
||||
#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
|
||||
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
|
||||
#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
|
||||
#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
|
||||
#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
|
||||
#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
|
||||
#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
|
||||
#define MMC_BUS_TEST_R 14 /* adtc R1 */
|
||||
#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
|
||||
#define MMC_BUS_TEST_W 19 /* adtc R1 */
|
||||
#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */
|
||||
#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */
|
||||
|
||||
/* class 2 */
|
||||
#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
|
||||
#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */
|
||||
#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */
|
||||
|
||||
/* class 3 */
|
||||
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
|
||||
|
||||
/* class 4 */
|
||||
#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
|
||||
#define MMC_PROGRAM_CID 26 /* adtc R1 */
|
||||
#define MMC_PROGRAM_CSD 27 /* adtc R1 */
|
||||
|
||||
/* class 6 */
|
||||
#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
|
||||
#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
|
||||
#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
|
||||
|
||||
/* class 5 */
|
||||
#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
|
||||
#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
|
||||
#define MMC_ERASE 38 /* ac R1b */
|
||||
|
||||
/* class 9 */
|
||||
#define MMC_FAST_IO 39 /* ac <Complex> R4 */
|
||||
#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
|
||||
|
||||
/* class 7 */
|
||||
#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
|
||||
|
||||
/* class 8 */
|
||||
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
||||
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
||||
|
||||
/* class 11 */
|
||||
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
|
||||
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
|
||||
#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */
|
||||
#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */
|
||||
#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */
|
||||
|
||||
/*
|
||||
* MMC_SWITCH argument format:
|
||||
*
|
||||
* [31:26] Always 0
|
||||
* [25:24] Access Mode
|
||||
* [23:16] Location of target Byte in EXT_CSD
|
||||
* [15:08] Value Byte
|
||||
* [07:03] Always 0
|
||||
* [02:00] Command Set
|
||||
*/
|
||||
|
||||
/*
|
||||
MMC status in R1, for native mode (SPI bits are different)
|
||||
Type
|
||||
e : error bit
|
||||
s : status bit
|
||||
r : detected and set for the actual command response
|
||||
x : detected and set during command execution. the host must poll
|
||||
the card by sending status command in order to read these bits.
|
||||
Clear condition
|
||||
a : according to the card state
|
||||
b : always related to the previous command. Reception of
|
||||
a valid command will clear it (with a delay of one command)
|
||||
c : clear by read
|
||||
*/
|
||||
|
||||
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
|
||||
#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
|
||||
#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
|
||||
#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
|
||||
#define R1_ERASE_PARAM (1 << 27) /* ex, c */
|
||||
#define R1_WP_VIOLATION (1 << 26) /* erx, c */
|
||||
#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
|
||||
#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
|
||||
#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
|
||||
#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
|
||||
#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
|
||||
#define R1_CC_ERROR (1 << 20) /* erx, c */
|
||||
#define R1_ERROR (1 << 19) /* erx, c */
|
||||
#define R1_UNDERRUN (1 << 18) /* ex, c */
|
||||
#define R1_OVERRUN (1 << 17) /* ex, c */
|
||||
#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
|
||||
#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
|
||||
#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
|
||||
#define R1_ERASE_RESET (1 << 13) /* sr, c */
|
||||
#define R1_STATUS(x) (x & 0xFFFFE000)
|
||||
#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
|
||||
#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
|
||||
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */
|
||||
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */
|
||||
#define R1_APP_CMD (1 << 5) /* sr, c */
|
||||
|
||||
#define R1_STATE_IDLE 0
|
||||
#define R1_STATE_READY 1
|
||||
#define R1_STATE_IDENT 2
|
||||
#define R1_STATE_STBY 3
|
||||
#define R1_STATE_TRAN 4
|
||||
#define R1_STATE_DATA 5
|
||||
#define R1_STATE_RCV 6
|
||||
#define R1_STATE_PRG 7
|
||||
#define R1_STATE_DIS 8
|
||||
|
||||
/*
|
||||
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
|
||||
* R1 is the low order byte; R2 is the next highest byte, when present.
|
||||
*/
|
||||
#define R1_SPI_IDLE (1 << 0)
|
||||
#define R1_SPI_ERASE_RESET (1 << 1)
|
||||
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
|
||||
#define R1_SPI_COM_CRC (1 << 3)
|
||||
#define R1_SPI_ERASE_SEQ (1 << 4)
|
||||
#define R1_SPI_ADDRESS (1 << 5)
|
||||
#define R1_SPI_PARAMETER (1 << 6)
|
||||
/* R1 bit 7 is always zero */
|
||||
#define R2_SPI_CARD_LOCKED (1 << 8)
|
||||
#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */
|
||||
#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP
|
||||
#define R2_SPI_ERROR (1 << 10)
|
||||
#define R2_SPI_CC_ERROR (1 << 11)
|
||||
#define R2_SPI_CARD_ECC_ERROR (1 << 12)
|
||||
#define R2_SPI_WP_VIOLATION (1 << 13)
|
||||
#define R2_SPI_ERASE_PARAM (1 << 14)
|
||||
#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */
|
||||
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
|
||||
|
||||
/*
|
||||
* OCR bits are mostly in host.h
|
||||
*/
|
||||
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
|
||||
#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
|
||||
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
|
||||
#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
|
||||
#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
|
||||
#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
|
||||
#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
|
||||
#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
|
||||
#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
|
||||
#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
|
||||
#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
|
||||
#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
|
||||
#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
|
||||
#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
|
||||
#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
|
||||
#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
|
||||
#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
|
||||
#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
|
||||
|
||||
/*
|
||||
* Card Command Classes (CCC)
|
||||
*/
|
||||
#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
|
||||
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
|
||||
/* (and for SPI, CMD58,59) */
|
||||
#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
|
||||
/* (CMD11) */
|
||||
#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
|
||||
/* (CMD16,17,18) */
|
||||
#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
|
||||
/* (CMD20) */
|
||||
#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
|
||||
/* (CMD16,24,25,26,27) */
|
||||
#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
|
||||
/* (CMD32,33,34,35,36,37,38,39) */
|
||||
#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
|
||||
/* (CMD28,29,30) */
|
||||
#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
|
||||
/* (CMD16,CMD42) */
|
||||
#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
|
||||
/* (CMD55,56,57,ACMD*) */
|
||||
#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
|
||||
/* (CMD5,39,40,52,53) */
|
||||
#define CCC_SWITCH (1<<10) /* (10) High speed switch */
|
||||
/* (CMD6,34,35,36,37,50) */
|
||||
/* (11) Reserved */
|
||||
/* (CMD?) */
|
||||
|
||||
/*
|
||||
* CSD field definitions
|
||||
*/
|
||||
|
||||
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
|
||||
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
|
||||
#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
|
||||
#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
|
||||
|
||||
#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
|
||||
#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
|
||||
#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
|
||||
#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
|
||||
#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
|
||||
|
||||
/*
|
||||
* EXT_CSD fields
|
||||
*/
|
||||
|
||||
#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */
|
||||
#define EXT_CSD_FLUSH_CACHE 32 /* W */
|
||||
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
|
||||
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
|
||||
#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */
|
||||
#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */
|
||||
#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */
|
||||
#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */
|
||||
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
|
||||
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
||||
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
|
||||
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
|
||||
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
|
||||
#define EXT_CSD_HPI_MGMT 161 /* R/W */
|
||||
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
||||
#define EXT_CSD_BKOPS_EN 163 /* R/W */
|
||||
#define EXT_CSD_BKOPS_START 164 /* W */
|
||||
#define EXT_CSD_SANITIZE_START 165 /* W */
|
||||
#define EXT_CSD_WR_REL_PARAM 166 /* RO */
|
||||
#define EXT_CSD_RPMB_MULT 168 /* RO */
|
||||
#define EXT_CSD_FW_CONFIG 169 /* R/W */
|
||||
#define EXT_CSD_BOOT_WP 173 /* R/W */
|
||||
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
|
||||
#define EXT_CSD_PART_CONFIG 179 /* R/W */
|
||||
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
|
||||
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
|
||||
#define EXT_CSD_STROBE_SUPPORT 184 /* RO */
|
||||
#define EXT_CSD_HS_TIMING 185 /* R/W */
|
||||
#define EXT_CSD_POWER_CLASS 187 /* R/W */
|
||||
#define EXT_CSD_REV 192 /* RO */
|
||||
#define EXT_CSD_STRUCTURE 194 /* RO */
|
||||
#define EXT_CSD_CARD_TYPE 196 /* RO */
|
||||
#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */
|
||||
#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */
|
||||
#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */
|
||||
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
|
||||
#define EXT_CSD_PWR_CL_26_195 201 /* RO */
|
||||
#define EXT_CSD_PWR_CL_52_360 202 /* RO */
|
||||
#define EXT_CSD_PWR_CL_26_360 203 /* RO */
|
||||
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
|
||||
#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
|
||||
#define EXT_CSD_REL_WR_SEC_C 222 /* RO */
|
||||
#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */
|
||||
#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
|
||||
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
|
||||
#define EXT_CSD_BOOT_MULT 226 /* RO */
|
||||
#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
|
||||
#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
|
||||
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
|
||||
#define EXT_CSD_TRIM_MULT 232 /* RO */
|
||||
#define EXT_CSD_PWR_CL_200_195 236 /* RO */
|
||||
#define EXT_CSD_PWR_CL_200_360 237 /* RO */
|
||||
#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */
|
||||
#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */
|
||||
#define EXT_CSD_BKOPS_STATUS 246 /* RO */
|
||||
#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
|
||||
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
|
||||
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
|
||||
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
|
||||
#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */
|
||||
#define EXT_CSD_PRE_EOL_INFO 267 /* RO */
|
||||
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */
|
||||
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */
|
||||
#define EXT_CSD_CMDQ_DEPTH 307 /* RO */
|
||||
#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */
|
||||
#define EXT_CSD_SUPPORTED_MODE 493 /* RO */
|
||||
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
|
||||
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
|
||||
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
|
||||
#define EXT_CSD_MAX_PACKED_READS 501 /* RO */
|
||||
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
|
||||
#define EXT_CSD_HPI_FEATURES 503 /* RO */
|
||||
|
||||
/*
|
||||
* EXT_CSD field definitions
|
||||
*/
|
||||
|
||||
#define EXT_CSD_WR_REL_PARAM_EN (1<<2)
|
||||
|
||||
#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40)
|
||||
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10)
|
||||
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04)
|
||||
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01)
|
||||
|
||||
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
|
||||
|
||||
#define EXT_CSD_PART_SETTING_COMPLETED (0x1)
|
||||
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
|
||||
|
||||
#define EXT_CSD_CMD_SET_NORMAL (1<<0)
|
||||
#define EXT_CSD_CMD_SET_SECURE (1<<1)
|
||||
#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
|
||||
|
||||
#define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */
|
||||
#define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */
|
||||
#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \
|
||||
EXT_CSD_CARD_TYPE_HS_52)
|
||||
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
|
||||
/* DDR mode @1.8V or 3V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
|
||||
/* DDR mode @1.2V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
|
||||
| EXT_CSD_CARD_TYPE_DDR_1_2V)
|
||||
#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */
|
||||
#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */
|
||||
/* SDR mode @1.2V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \
|
||||
EXT_CSD_CARD_TYPE_HS200_1_2V)
|
||||
#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */
|
||||
#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */
|
||||
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \
|
||||
EXT_CSD_CARD_TYPE_HS400_1_2V)
|
||||
#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */
|
||||
|
||||
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
|
||||
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
|
||||
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
|
||||
#define EXT_CSD_BUS_WIDTH_STROBE BIT(7) /* Enhanced strobe mode */
|
||||
|
||||
#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */
|
||||
#define EXT_CSD_TIMING_HS 1 /* High speed */
|
||||
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
|
||||
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
|
||||
#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */
|
||||
|
||||
#define EXT_CSD_SEC_ER_EN BIT(0)
|
||||
#define EXT_CSD_SEC_BD_BLK_EN BIT(2)
|
||||
#define EXT_CSD_SEC_GB_CL_EN BIT(4)
|
||||
#define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */
|
||||
|
||||
#define EXT_CSD_RST_N_EN_MASK 0x3
|
||||
#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */
|
||||
|
||||
#define EXT_CSD_NO_POWER_NOTIFICATION 0
|
||||
#define EXT_CSD_POWER_ON 1
|
||||
#define EXT_CSD_POWER_OFF_SHORT 2
|
||||
#define EXT_CSD_POWER_OFF_LONG 3
|
||||
|
||||
#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */
|
||||
#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */
|
||||
#define EXT_CSD_PWR_CL_8BIT_SHIFT 4
|
||||
#define EXT_CSD_PWR_CL_4BIT_SHIFT 0
|
||||
|
||||
#define EXT_CSD_PACKED_EVENT_EN BIT(3)
|
||||
|
||||
/*
|
||||
* EXCEPTION_EVENT_STATUS field
|
||||
*/
|
||||
#define EXT_CSD_URGENT_BKOPS BIT(0)
|
||||
#define EXT_CSD_DYNCAP_NEEDED BIT(1)
|
||||
#define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2)
|
||||
#define EXT_CSD_PACKED_FAILURE BIT(3)
|
||||
|
||||
#define EXT_CSD_PACKED_GENERIC_ERROR BIT(0)
|
||||
#define EXT_CSD_PACKED_INDEXED_ERROR BIT(1)
|
||||
|
||||
/*
|
||||
* BKOPS status level
|
||||
*/
|
||||
#define EXT_CSD_BKOPS_LEVEL_2 0x2
|
||||
|
||||
/*
|
||||
* BKOPS modes
|
||||
*/
|
||||
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01
|
||||
#define EXT_CSD_AUTO_BKOPS_MASK 0x02
|
||||
|
||||
/*
|
||||
* Command Queue
|
||||
*/
|
||||
#define EXT_CSD_CMDQ_MODE_ENABLED BIT(0)
|
||||
#define EXT_CSD_CMDQ_DEPTH_MASK GENMASK(4, 0)
|
||||
#define EXT_CSD_CMDQ_SUPPORTED BIT(0)
|
||||
|
||||
/*
|
||||
* MMC_SWITCH access modes
|
||||
*/
|
||||
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
|
||||
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
|
||||
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
|
||||
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
|
||||
|
||||
/*
|
||||
* Erase/trim/discard
|
||||
*/
|
||||
#define MMC_ERASE_ARG 0x00000000
|
||||
#define MMC_SECURE_ERASE_ARG 0x80000000
|
||||
#define MMC_TRIM_ARG 0x00000001
|
||||
#define MMC_DISCARD_ARG 0x00000003
|
||||
#define MMC_SECURE_TRIM1_ARG 0x80000001
|
||||
#define MMC_SECURE_TRIM2_ARG 0x80008000
|
||||
#define MMC_SECURE_ARGS 0x80000000
|
||||
#define MMC_TRIM_ARGS 0x00008001
|
||||
|
||||
#endif /* LINUX_MMC_MMC_H */
|
153
fusee/fusee-primary/src/sdmmc/sd.h
Normal file
153
fusee/fusee-primary/src/sdmmc/sd.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* include/linux/mmc/sd.h
|
||||
*
|
||||
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef LINUX_MMC_SD_H
|
||||
#define LINUX_MMC_SD_H
|
||||
|
||||
/* SD commands type argument response */
|
||||
/* class 0 */
|
||||
/* This is basically the same command as for MMC with some quirks. */
|
||||
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
||||
|
||||
/* class 10 */
|
||||
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
||||
|
||||
/* class 5 */
|
||||
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
||||
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
||||
|
||||
/* Application commands */
|
||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||
#define SD_APP_SD_STATUS 13 /* adtc R1 */
|
||||
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||
#define SD_APP_SET_CLR_CARD_DETECT 42 /* ac [0] set cd R1 */
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
|
||||
/* OCR bit definitions */
|
||||
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||
#define SD_OCR_VDD_LOW (1 << 7) /* SD: Reserved for Low Voltage Range */
|
||||
#define SD_OCR_VDD_20_21 (1 << 8)
|
||||
#define SD_OCR_VDD_21_22 (1 << 9)
|
||||
#define SD_OCR_VDD_22_23 (1 << 10)
|
||||
#define SD_OCR_VDD_23_24 (1 << 11)
|
||||
#define SD_OCR_VDD_24_25 (1 << 12)
|
||||
#define SD_OCR_VDD_25_26 (1 << 13)
|
||||
#define SD_OCR_VDD_26_27 (1 << 14)
|
||||
#define SD_OCR_VDD_27_28 (1 << 15)
|
||||
#define SD_OCR_VDD_28_29 (1 << 16)
|
||||
#define SD_OCR_VDD_29_30 (1 << 17)
|
||||
#define SD_OCR_VDD_30_31 (1 << 18)
|
||||
#define SD_OCR_VDD_31_32 (1 << 19)
|
||||
#define SD_OCR_VDD_32_33 (1 << 20)
|
||||
#define SD_OCR_VDD_33_34 (1 << 21)
|
||||
#define SD_OCR_VDD_34_35 (1 << 22)
|
||||
#define SD_OCR_VDD_35_36 (1 << 23)
|
||||
|
||||
/*
|
||||
* SD_SWITCH argument format:
|
||||
*
|
||||
* [31] Check (0) or switch (1)
|
||||
* [30:24] Reserved (0)
|
||||
* [23:20] Function group 6
|
||||
* [19:16] Function group 5
|
||||
* [15:12] Function group 4
|
||||
* [11:8] Function group 3
|
||||
* [7:4] Function group 2
|
||||
* [3:0] Function group 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* SD_SEND_IF_COND argument format:
|
||||
*
|
||||
* [31:12] Reserved (0)
|
||||
* [11:8] Host Voltage Supply Flags
|
||||
* [7:0] Check Pattern (0xAA)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCR field definitions
|
||||
*/
|
||||
|
||||
#define SD_SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
|
||||
#define SD_SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
|
||||
#define SD_SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
|
||||
#define SD_SCR_BUS_WIDTH_1 1
|
||||
#define SD_SCR_BUS_WIDTH_4 4
|
||||
#define SD_SCR_CMD20_SUPPORT 1
|
||||
#define SD_SCR_CMD23_SUPPORT 2
|
||||
|
||||
/*
|
||||
* SD bus widths
|
||||
*/
|
||||
#define SD_BUS_WIDTH_1 0
|
||||
#define SD_BUS_WIDTH_4 2
|
||||
|
||||
/*
|
||||
* SD bus speed modes
|
||||
*/
|
||||
#define UHS_SDR12_BUS_SPEED 0
|
||||
#define HIGH_SPEED_BUS_SPEED 1
|
||||
#define UHS_SDR25_BUS_SPEED 1
|
||||
#define UHS_SDR50_BUS_SPEED 2
|
||||
#define UHS_SDR104_BUS_SPEED 3
|
||||
#define UHS_DDR50_BUS_SPEED 4
|
||||
#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED)
|
||||
#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED)
|
||||
#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED)
|
||||
#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED)
|
||||
#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED)
|
||||
#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED)
|
||||
|
||||
/*
|
||||
* SD bus driver types
|
||||
*/
|
||||
#define SD_DRIVER_TYPE_B 0x01
|
||||
#define SD_DRIVER_TYPE_A 0x02
|
||||
#define SD_DRIVER_TYPE_C 0x04
|
||||
#define SD_DRIVER_TYPE_D 0x08
|
||||
|
||||
/*
|
||||
* SD bus current limits
|
||||
*/
|
||||
#define SD_SET_CURRENT_LIMIT_200 0
|
||||
#define SD_SET_CURRENT_LIMIT_400 1
|
||||
#define SD_SET_CURRENT_LIMIT_600 2
|
||||
#define SD_SET_CURRENT_LIMIT_800 3
|
||||
#define SD_SET_CURRENT_NO_CHANGE (-1)
|
||||
#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200)
|
||||
#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400)
|
||||
#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600)
|
||||
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
|
||||
|
||||
/*
|
||||
* SD_SWITCH mode
|
||||
*/
|
||||
#define SD_SWITCH_CHECK 0
|
||||
#define SD_SWITCH_SET 1
|
||||
|
||||
/*
|
||||
* SD_SWITCH function groups
|
||||
*/
|
||||
#define SD_SWITCH_GRP_ACCESS 0
|
||||
|
||||
/*
|
||||
* SD_SWITCH access modes
|
||||
*/
|
||||
#define SD_SWITCH_ACCESS_DEF 0
|
||||
#define SD_SWITCH_ACCESS_HS 1
|
||||
|
||||
#endif /* LINUX_MMC_SD_H */
|
1510
fusee/fusee-primary/src/sdmmc/sdmmc.c
Normal file
1510
fusee/fusee-primary/src/sdmmc/sdmmc.c
Normal file
File diff suppressed because it is too large
Load diff
160
fusee/fusee-primary/src/sdmmc/sdmmc.h
Normal file
160
fusee/fusee-primary/src/sdmmc/sdmmc.h
Normal file
|
@ -0,0 +1,160 @@
|
|||
#ifndef FUSEE_SDMMC_H
|
||||
#define FUSEE_SDMMC_H
|
||||
|
||||
#include "sdmmc_core.h"
|
||||
|
||||
/* Structure for storing the MMC CID (adapted from Linux headers) */
|
||||
typedef struct {
|
||||
uint32_t manfid;
|
||||
uint8_t prod_name[8];
|
||||
uint8_t prv;
|
||||
uint32_t serial;
|
||||
uint16_t oemid;
|
||||
uint16_t year;
|
||||
uint8_t hwrev;
|
||||
uint8_t fwrev;
|
||||
uint8_t month;
|
||||
} mmc_cid_t;
|
||||
|
||||
/* Structure for storing the MMC CSD (adapted from Linux headers) */
|
||||
typedef struct {
|
||||
uint8_t structure;
|
||||
uint8_t mmca_vsn;
|
||||
uint16_t cmdclass;
|
||||
uint16_t taac_clks;
|
||||
uint32_t taac_ns;
|
||||
uint32_t c_size;
|
||||
uint32_t r2w_factor;
|
||||
uint32_t max_dtr;
|
||||
uint32_t erase_size; /* In sectors */
|
||||
uint32_t read_blkbits;
|
||||
uint32_t write_blkbits;
|
||||
uint32_t capacity;
|
||||
uint32_t read_partial:1,
|
||||
read_misalign:1,
|
||||
write_partial:1,
|
||||
write_misalign:1,
|
||||
dsr_imp:1;
|
||||
} mmc_csd_t;
|
||||
|
||||
/* Structure for storing the MMC extended CSD (adapted from Linux headers) */
|
||||
typedef struct {
|
||||
uint8_t rev;
|
||||
uint8_t erase_group_def;
|
||||
uint8_t sec_feature_support;
|
||||
uint8_t rel_sectors;
|
||||
uint8_t rel_param;
|
||||
uint8_t part_config;
|
||||
uint8_t cache_ctrl;
|
||||
uint8_t rst_n_function;
|
||||
uint8_t max_packed_writes;
|
||||
uint8_t max_packed_reads;
|
||||
uint8_t packed_event_en;
|
||||
uint32_t part_time; /* Units: ms */
|
||||
uint32_t sa_timeout; /* Units: 100ns */
|
||||
uint32_t generic_cmd6_time; /* Units: 10ms */
|
||||
uint32_t power_off_longtime; /* Units: ms */
|
||||
uint8_t power_off_notification; /* state */
|
||||
uint32_t hs_max_dtr;
|
||||
uint32_t hs200_max_dtr;
|
||||
uint32_t sectors;
|
||||
uint32_t hc_erase_size; /* In sectors */
|
||||
uint32_t hc_erase_timeout; /* In milliseconds */
|
||||
uint32_t sec_trim_mult; /* Secure trim multiplier */
|
||||
uint32_t sec_erase_mult; /* Secure erase multiplier */
|
||||
uint32_t trim_timeout; /* In milliseconds */
|
||||
uint32_t partition_setting_completed; /* enable bit */
|
||||
uint64_t enhanced_area_offset; /* Units: Byte */
|
||||
uint32_t enhanced_area_size; /* Units: KB */
|
||||
uint32_t cache_size; /* Units: KB */
|
||||
uint32_t hpi_en; /* HPI enablebit */
|
||||
uint32_t hpi; /* HPI support bit */
|
||||
uint32_t hpi_cmd; /* cmd used as HPI */
|
||||
uint32_t bkops; /* background support bit */
|
||||
uint32_t man_bkops_en; /* manual bkops enable bit */
|
||||
uint32_t auto_bkops_en; /* auto bkops enable bit */
|
||||
uint32_t data_sector_size; /* 512 bytes or 4KB */
|
||||
uint32_t data_tag_unit_size; /* DATA TAG UNIT size */
|
||||
uint32_t boot_ro_lock; /* ro lock support */
|
||||
uint32_t boot_ro_lockable;
|
||||
uint32_t ffu_capable; /* Firmware upgrade support */
|
||||
uint32_t cmdq_en; /* Command Queue enabled */
|
||||
uint32_t cmdq_support; /* Command Queue supported */
|
||||
uint32_t cmdq_depth; /* Command Queue depth */
|
||||
uint8_t fwrev[8]; /* FW version */
|
||||
uint8_t raw_exception_status; /* 54 */
|
||||
uint8_t raw_partition_support; /* 160 */
|
||||
uint8_t raw_rpmb_size_mult; /* 168 */
|
||||
uint8_t raw_erased_mem_count; /* 181 */
|
||||
uint8_t strobe_support; /* 184 */
|
||||
uint8_t raw_ext_csd_structure; /* 194 */
|
||||
uint8_t raw_card_type; /* 196 */
|
||||
uint8_t raw_driver_strength; /* 197 */
|
||||
uint8_t out_of_int_time; /* 198 */
|
||||
uint8_t raw_pwr_cl_52_195; /* 200 */
|
||||
uint8_t raw_pwr_cl_26_195; /* 201 */
|
||||
uint8_t raw_pwr_cl_52_360; /* 202 */
|
||||
uint8_t raw_pwr_cl_26_360; /* 203 */
|
||||
uint8_t raw_s_a_timeout; /* 217 */
|
||||
uint8_t raw_hc_erase_gap_size; /* 221 */
|
||||
uint8_t raw_erase_timeout_mult; /* 223 */
|
||||
uint8_t raw_hc_erase_grp_size; /* 224 */
|
||||
uint8_t raw_sec_trim_mult; /* 229 */
|
||||
uint8_t raw_sec_erase_mult; /* 230 */
|
||||
uint8_t raw_sec_feature_support; /* 231 */
|
||||
uint8_t raw_trim_mult; /* 232 */
|
||||
uint8_t raw_pwr_cl_200_195; /* 236 */
|
||||
uint8_t raw_pwr_cl_200_360; /* 237 */
|
||||
uint8_t raw_pwr_cl_ddr_52_195; /* 238 */
|
||||
uint8_t raw_pwr_cl_ddr_52_360; /* 239 */
|
||||
uint8_t raw_pwr_cl_ddr_200_360; /* 253 */
|
||||
uint8_t raw_bkops_status; /* 246 */
|
||||
uint8_t raw_sectors[4]; /* 212 - 4 bytes */
|
||||
uint8_t pre_eol_info; /* 267 */
|
||||
uint8_t device_life_time_est_typ_a; /* 268 */
|
||||
uint8_t device_life_time_est_typ_b; /* 269 */
|
||||
uint32_t feature_support;
|
||||
} mmc_ext_csd_t;
|
||||
|
||||
/* Structure for storing the SD SCR (adapted from Linux headers) */
|
||||
typedef struct {
|
||||
uint8_t sda_vsn;
|
||||
uint8_t sda_spec3;
|
||||
uint8_t bus_widths;
|
||||
uint8_t cmds;
|
||||
} sd_scr_t;
|
||||
|
||||
/* Structure for storing the SD SSR (adapted from Linux headers) */
|
||||
typedef struct {
|
||||
uint8_t dat_bus_width;
|
||||
uint8_t secured_mode;
|
||||
uint16_t sd_card_type;
|
||||
uint8_t speed_class;
|
||||
uint8_t uhs_speed_grade;
|
||||
uint8_t uhs_au_size;
|
||||
uint8_t video_speed_class;
|
||||
uint8_t app_perf_class;
|
||||
} sd_ssr_t;
|
||||
|
||||
/* Structure describing a SDMMC device's context. */
|
||||
typedef struct {
|
||||
/* Underlying driver context. */
|
||||
sdmmc_t *sdmmc;
|
||||
|
||||
bool is_180v;
|
||||
bool is_block_sdhc;
|
||||
uint32_t rca;
|
||||
mmc_cid_t cid;
|
||||
mmc_csd_t csd;
|
||||
mmc_ext_csd_t ext_csd;
|
||||
sd_scr_t scr;
|
||||
sd_ssr_t ssr;
|
||||
} sdmmc_device_t;
|
||||
|
||||
int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed);
|
||||
int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed);
|
||||
int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data);
|
||||
int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data);
|
||||
int sdmmc_device_finish(sdmmc_device_t *device);
|
||||
|
||||
#endif
|
1971
fusee/fusee-primary/src/sdmmc/sdmmc_core.c
Normal file
1971
fusee/fusee-primary/src/sdmmc/sdmmc_core.c
Normal file
File diff suppressed because it is too large
Load diff
287
fusee/fusee-primary/src/sdmmc/sdmmc_core.h
Normal file
287
fusee/fusee-primary/src/sdmmc/sdmmc_core.h
Normal file
|
@ -0,0 +1,287 @@
|
|||
#ifndef FUSEE_SDMMC_CORE_H
|
||||
#define FUSEE_SDMMC_CORE_H
|
||||
|
||||
#include "sdmmc_tegra.h"
|
||||
|
||||
/* Present state */
|
||||
#define SDHCI_CMD_INHIBIT 0x00000001
|
||||
#define SDHCI_DATA_INHIBIT 0x00000002
|
||||
#define SDHCI_DOING_WRITE 0x00000100
|
||||
#define SDHCI_DOING_READ 0x00000200
|
||||
#define SDHCI_SPACE_AVAILABLE 0x00000400
|
||||
#define SDHCI_DATA_AVAILABLE 0x00000800
|
||||
#define SDHCI_CARD_PRESENT 0x00010000
|
||||
#define SDHCI_WRITE_PROTECT 0x00080000
|
||||
#define SDHCI_DATA_LVL_MASK 0x00F00000
|
||||
#define SDHCI_DATA_LVL_SHIFT 20
|
||||
#define SDHCI_DATA_0_LVL_MASK 0x00100000
|
||||
#define SDHCI_CMD_LVL 0x01000000
|
||||
|
||||
/* SDHCI clock control */
|
||||
#define SDHCI_DIVIDER_SHIFT 8
|
||||
#define SDHCI_DIVIDER_HI_SHIFT 6
|
||||
#define SDHCI_DIV_MASK 0xFF
|
||||
#define SDHCI_DIV_MASK_LEN 8
|
||||
#define SDHCI_DIV_HI_MASK 0x300
|
||||
#define SDHCI_PROG_CLOCK_MODE 0x0020
|
||||
#define SDHCI_CLOCK_CARD_EN 0x0004
|
||||
#define SDHCI_CLOCK_INT_STABLE 0x0002
|
||||
#define SDHCI_CLOCK_INT_EN 0x0001
|
||||
|
||||
/* SDHCI host control */
|
||||
#define SDHCI_CTRL_LED 0x01
|
||||
#define SDHCI_CTRL_4BITBUS 0x02
|
||||
#define SDHCI_CTRL_HISPD 0x04
|
||||
#define SDHCI_CTRL_DMA_MASK 0x18
|
||||
#define SDHCI_CTRL_SDMA 0x00
|
||||
#define SDHCI_CTRL_ADMA1 0x08
|
||||
#define SDHCI_CTRL_ADMA32 0x10
|
||||
#define SDHCI_CTRL_ADMA64 0x18
|
||||
#define SDHCI_CTRL_8BITBUS 0x20
|
||||
#define SDHCI_CTRL_CDTEST_INS 0x40
|
||||
#define SDHCI_CTRL_CDTEST_EN 0x80
|
||||
|
||||
/* SDHCI host control 2 */
|
||||
#define SDHCI_CTRL_UHS_MASK 0x0007
|
||||
#define SDHCI_CTRL_UHS_SDR12 0x0000
|
||||
#define SDHCI_CTRL_UHS_SDR25 0x0001
|
||||
#define SDHCI_CTRL_UHS_SDR50 0x0002
|
||||
#define SDHCI_CTRL_UHS_SDR104 0x0003
|
||||
#define SDHCI_CTRL_UHS_DDR50 0x0004
|
||||
#define SDHCI_CTRL_HS400 0x0005
|
||||
#define SDHCI_CTRL_VDD_180 0x0008
|
||||
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
|
||||
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
|
||||
#define SDHCI_CTRL_DRV_TYPE_A 0x0010
|
||||
#define SDHCI_CTRL_DRV_TYPE_C 0x0020
|
||||
#define SDHCI_CTRL_DRV_TYPE_D 0x0030
|
||||
#define SDHCI_CTRL_EXEC_TUNING 0x0040
|
||||
#define SDHCI_CTRL_TUNED_CLK 0x0080
|
||||
#define SDHCI_UHS2_IF_EN 0x0100
|
||||
#define SDHCI_HOST_VERSION_4_EN 0x1000
|
||||
#define SDHCI_ADDRESSING_64BIT_EN 0x2000
|
||||
#define SDHCI_ASYNC_INTR_EN 0x4000
|
||||
#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
|
||||
|
||||
/* SDHCI capabilities */
|
||||
#define SDHCI_CAN_DO_8BIT 0x00040000
|
||||
#define SDHCI_CAN_DO_ADMA2 0x00080000
|
||||
#define SDHCI_CAN_DO_ADMA1 0x00100000
|
||||
#define SDHCI_CAN_DO_HISPD 0x00200000
|
||||
#define SDHCI_CAN_DO_SDMA 0x00400000
|
||||
#define SDHCI_CAN_VDD_330 0x01000000
|
||||
#define SDHCI_CAN_VDD_300 0x02000000
|
||||
#define SDHCI_CAN_VDD_180 0x04000000
|
||||
#define SDHCI_CAN_64BIT 0x10000000
|
||||
#define SDHCI_ASYNC_INTR 0x20000000
|
||||
|
||||
/* Vendor clock control */
|
||||
#define SDMMC_CLOCK_TAP_MASK (0xFF << 16)
|
||||
#define SDMMC_CLOCK_TAP_SDMMC1 (0x04 << 16)
|
||||
#define SDMMC_CLOCK_TAP_SDMMC2 (0x00 << 16)
|
||||
#define SDMMC_CLOCK_TAP_SDMMC3 (0x03 << 16)
|
||||
#define SDMMC_CLOCK_TAP_SDMMC4 (0x00 << 16)
|
||||
#define SDMMC_CLOCK_TRIM_MASK (0xFF << 24)
|
||||
#define SDMMC_CLOCK_TRIM_SDMMC1 (0x02 << 24)
|
||||
#define SDMMC_CLOCK_TRIM_SDMMC2 (0x08 << 24)
|
||||
#define SDMMC_CLOCK_TRIM_SDMMC3 (0x03 << 24)
|
||||
#define SDMMC_CLOCK_TRIM_SDMMC4 (0x08 << 24)
|
||||
#define SDMMC_CLOCK_PADPIPE_CLKEN_OVERRIDE (1 << 3)
|
||||
|
||||
/* Autocal configuration */
|
||||
#define SDMMC_AUTOCAL_PDPU_CONFIG_MASK 0x7F7F
|
||||
#define SDMMC_AUTOCAL_PDPU_SDMMC1_1V8 0x7B7B
|
||||
#define SDMMC_AUTOCAL_PDPU_SDMMC1_3V3 0x7D00
|
||||
#define SDMMC_AUTOCAL_PDPU_SDMMC4_1V8 0x0505
|
||||
#define SDMMC_AUTOCAL_START (1 << 31)
|
||||
#define SDMMC_AUTOCAL_ENABLE (1 << 29)
|
||||
|
||||
/* Autocal status */
|
||||
#define SDMMC_AUTOCAL_ACTIVE (1 << 31)
|
||||
|
||||
/* Vendor tuning control 0*/
|
||||
#define SDMMC_VENDOR_TUNING_TRIES_MASK (0x7 << 13)
|
||||
#define SDMMC_VENDOR_TUNING_TRIES_SHIFT 13
|
||||
#define SDMMC_VENDOR_TUNING_MULTIPLIER_MASK (0x7F << 6)
|
||||
#define SDMMC_VENDOR_TUNING_MULTIPLIER_UNITY (1 << 6)
|
||||
#define SDMMC_VENDOR_TUNING_DIVIDER_MASK (0x7 << 3)
|
||||
#define SDMMC_VENDOR_TUNING_SET_BY_HW (1 << 17)
|
||||
|
||||
/* Vendor tuning control 1*/
|
||||
#define SDMMC_VENDOR_TUNING_STEP_SIZE_SDR50_DEFAULT (0 << 0)
|
||||
#define SDMMC_VENDOR_TUNING_STEP_SIZE_SDR104_DEFAULT (0 << 4)
|
||||
|
||||
/* Vendor capability overrides */
|
||||
#define SDMMC_VENDOR_CAPABILITY_DQS_TRIM_MASK (0x3F << 8)
|
||||
#define SDMMC_VENDOR_CAPABILITY_DQS_TRIM_HS400 (0x11 << 8)
|
||||
|
||||
/* Timeouts */
|
||||
#define SDMMC_AUTOCAL_TIMEOUT (10 * 1000)
|
||||
#define SDMMC_TUNING_TIMEOUT (150 * 1000)
|
||||
|
||||
/* Command response flags */
|
||||
#define SDMMC_RSP_PRESENT (1 << 0)
|
||||
#define SDMMC_RSP_136 (1 << 1)
|
||||
#define SDMMC_RSP_CRC (1 << 2)
|
||||
#define SDMMC_RSP_BUSY (1 << 3)
|
||||
#define SDMMC_RSP_OPCODE (1 << 4)
|
||||
|
||||
/* Command types */
|
||||
#define SDMMC_CMD_MASK (3 << 5)
|
||||
#define SDMMC_CMD_AC (0 << 5)
|
||||
#define SDMMC_CMD_ADTC (1 << 5)
|
||||
#define SDMMC_CMD_BC (2 << 5)
|
||||
#define SDMMC_CMD_BCR (3 << 5)
|
||||
|
||||
/* SPI command response flags */
|
||||
#define SDMMC_RSP_SPI_S1 (1 << 7)
|
||||
#define SDMMC_RSP_SPI_S2 (1 << 8)
|
||||
#define SDMMC_RSP_SPI_B4 (1 << 9)
|
||||
#define SDMMC_RSP_SPI_BUSY (1 << 10)
|
||||
|
||||
/* Native response types for commands */
|
||||
#define SDMMC_RSP_NONE (0)
|
||||
#define SDMMC_RSP_R1 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE)
|
||||
#define SDMMC_RSP_R1B (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE|SDMMC_RSP_BUSY)
|
||||
#define SDMMC_RSP_R2 (SDMMC_RSP_PRESENT|SDMMC_RSP_136|SDMMC_RSP_CRC)
|
||||
#define SDMMC_RSP_R3 (SDMMC_RSP_PRESENT)
|
||||
#define SDMMC_RSP_R4 (SDMMC_RSP_PRESENT)
|
||||
#define SDMMC_RSP_R5 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE)
|
||||
#define SDMMC_RSP_R6 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE)
|
||||
#define SDMMC_RSP_R7 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE)
|
||||
#define SDMMC_RSP_R1_NO_CRC (SDMMC_RSP_PRESENT|SDMMC_RSP_OPCODE)
|
||||
|
||||
/* SPI response types for commands */
|
||||
#define SDMMC_RSP_SPI_R1 (SDMMC_RSP_SPI_S1)
|
||||
#define SDMMC_RSP_SPI_R1B (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_BUSY)
|
||||
#define SDMMC_RSP_SPI_R2 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2)
|
||||
#define SDMMC_RSP_SPI_R3 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4)
|
||||
#define SDMMC_RSP_SPI_R4 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4)
|
||||
#define SDMMC_RSP_SPI_R5 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2)
|
||||
#define SDMMC_RSP_SPI_R7 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4)
|
||||
|
||||
/* Internal logging */
|
||||
typedef enum {
|
||||
SDMMC_LOG_NONE = 0,
|
||||
SDMMC_LOG_ERROR = 1,
|
||||
SDMMC_LOG_WARN = 2,
|
||||
SDMMC_LOG_INFO = 3,
|
||||
SDMMC_LOG_DEBUG = 4
|
||||
} SdmmcLogLevel;
|
||||
|
||||
/* SDMMC controllers */
|
||||
typedef enum {
|
||||
SDMMC_1 = 0,
|
||||
SDMMC_2 = 1,
|
||||
SDMMC_3 = 2,
|
||||
SDMMC_4 = 3
|
||||
} SdmmcControllerNum;
|
||||
|
||||
typedef enum {
|
||||
SDMMC_VOLTAGE_NONE = 0,
|
||||
SDMMC_VOLTAGE_1V8 = 1,
|
||||
SDMMC_VOLTAGE_3V3 = 2
|
||||
} SdmmcBusVoltage;
|
||||
|
||||
typedef enum {
|
||||
SDMMC_BUS_WIDTH_1BIT = 0,
|
||||
SDMMC_BUS_WIDTH_4BIT = 1,
|
||||
SDMMC_BUS_WIDTH_8BIT = 2
|
||||
} SdmmcBusWidth;
|
||||
|
||||
typedef enum {
|
||||
SDMMC_SPEED_INIT_HS = 0,
|
||||
SDMMC_SPEED_HS26 = 1,
|
||||
SDMMC_SPEED_HS52 = 2,
|
||||
SDMMC_SPEED_HS200 = 3,
|
||||
SDMMC_SPEED_HS400 = 4,
|
||||
SDMMC_SPEED_INIT_SDR = 5,
|
||||
SDMMC_SPEED_UNK6 = 6,
|
||||
SDMMC_SPEED_SDR25 = 7,
|
||||
SDMMC_SPEED_SDR12 = 8,
|
||||
SDMMC_SPEED_UNK9 = 9,
|
||||
SDMMC_SPEED_SDR50 = 10,
|
||||
SDMMC_SPEED_SDR104 = 11,
|
||||
SDMMC_SPEED_UNK12 = 12,
|
||||
SDMMC_SPEED_DDR50 = 13,
|
||||
SDMMC_SPEED_UNK14 = 14,
|
||||
} SdmmcBusSpeed;
|
||||
|
||||
typedef enum {
|
||||
SDMMC_CAR_DIVIDER_SDR12 = 31, // (16.5 * 2) - 2
|
||||
SDMMC_CAR_DIVIDER_SDR25 = 15, // (8.5 * 2) - 2
|
||||
SDMMC_CAR_DIVIDER_SDR50 = 7, // (4.5 * 2) - 2
|
||||
SDMMC_CAR_DIVIDER_SDR104 = 2, // (2 * 2) - 2
|
||||
SDMMC_CAR_DIVIDER_DDR50 = 18, // (5 * 2 * 2) - 2
|
||||
SDMMC_CAR_DIVIDER_HS26 = 30, // (16 * 2) - 2
|
||||
SDMMC_CAR_DIVIDER_HS52 = 14, // (8 * 2) - 2
|
||||
SDMMC_CAR_DIVIDER_HS200 = 3, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ
|
||||
SDMMC_CAR_DIVIDER_HS400 = 3, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ
|
||||
} SdmmcCarDivider;
|
||||
|
||||
/* Structure for describing a SDMMC device. */
|
||||
typedef struct {
|
||||
/* Controller number */
|
||||
SdmmcControllerNum controller;
|
||||
|
||||
/* Backing register space */
|
||||
volatile tegra_sdmmc_t *regs;
|
||||
|
||||
/* Controller properties */
|
||||
const char *name;
|
||||
bool has_sd;
|
||||
bool is_clk_running;
|
||||
bool is_sd_clk_enabled;
|
||||
bool is_tuning_tap_val_set;
|
||||
bool use_adma;
|
||||
uint32_t tap_val;
|
||||
uint32_t internal_divider;
|
||||
uint32_t resp[4];
|
||||
uint32_t resp_auto_cmd12;
|
||||
uint32_t next_dma_addr;
|
||||
uint8_t* dma_bounce_buf;
|
||||
SdmmcBusVoltage bus_voltage;
|
||||
SdmmcBusWidth bus_width;
|
||||
|
||||
/* Per-controller operations. */
|
||||
int (*sdmmc_config)();
|
||||
} sdmmc_t;
|
||||
|
||||
/* Structure for describing a SDMMC command. */
|
||||
typedef struct {
|
||||
uint32_t opcode;
|
||||
uint32_t arg;
|
||||
uint32_t resp[4];
|
||||
uint32_t flags; /* expected response type */
|
||||
} sdmmc_command_t;
|
||||
|
||||
/* Structure for describing a SDMMC request. */
|
||||
typedef struct {
|
||||
void* data;
|
||||
uint32_t blksz;
|
||||
uint32_t num_blocks;
|
||||
bool is_multi_block;
|
||||
bool is_read;
|
||||
bool is_auto_cmd12;
|
||||
} sdmmc_request_t;
|
||||
|
||||
int sdmmc_init(sdmmc_t *sdmmc, SdmmcControllerNum controller, SdmmcBusVoltage bus_voltage, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed);
|
||||
void sdmmc_finish(sdmmc_t *sdmmc);
|
||||
int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed);
|
||||
void sdmmc_select_bus_width(sdmmc_t *sdmmc, SdmmcBusWidth width);
|
||||
void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage);
|
||||
void sdmmc_adjust_sd_clock(sdmmc_t *sdmmc);
|
||||
int sdmmc_switch_voltage(sdmmc_t *sdmmc);
|
||||
void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc);
|
||||
int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcode);
|
||||
int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t *num_blocks_out);
|
||||
int sdmmc_load_response(sdmmc_t *sdmmc, uint32_t flags, uint32_t *resp);
|
||||
int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode);
|
||||
void sdmmc_set_log_level(SdmmcLogLevel log_level);
|
||||
void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...);
|
||||
void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...);
|
||||
void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...);
|
||||
void sdmmc_debug(sdmmc_t *sdmmc, char *fmt, ...);
|
||||
void sdmmc_dump_regs(sdmmc_t *sdmmc);
|
||||
|
||||
#endif
|
154
fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h
Normal file
154
fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
#ifndef FUSEE_SDMMC_TEGRA_H
|
||||
#define FUSEE_SDMMC_TEGRA_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_POWER (1 << 0)
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 (5 << 1)
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 (6 << 1)
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 (7 << 1)
|
||||
|
||||
#define TEGRA_MMC_HOSTCTL_DMASEL_MASK (3 << 3)
|
||||
#define TEGRA_MMC_HOSTCTL_DMASEL_SDMA (0 << 3)
|
||||
#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_32BIT (2 << 3)
|
||||
#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_64BIT (3 << 3)
|
||||
|
||||
#define TEGRA_MMC_TRNMOD_DMA_ENABLE (1 << 0)
|
||||
#define TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE (1 << 1)
|
||||
#define TEGRA_MMC_TRNMOD_AUTO_CMD12 (1 << 2)
|
||||
#define TEGRA_MMC_TRNMOD_AUTO_CMD23 (1 << 3)
|
||||
#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_WRITE (0 << 4)
|
||||
#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ (1 << 4)
|
||||
#define TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT (1 << 5)
|
||||
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_MASK (3 << 0)
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE (0 << 0)
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136 (1 << 0)
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48 (2 << 0)
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY (3 << 0)
|
||||
|
||||
#define TEGRA_MMC_TRNMOD_CMD_CRC_CHECK (1 << 3)
|
||||
#define TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK (1 << 4)
|
||||
#define TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER (1 << 5)
|
||||
|
||||
#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD (1 << 0)
|
||||
#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT (1 << 1)
|
||||
|
||||
#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE (1 << 0)
|
||||
#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE (1 << 1)
|
||||
#define TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE (1 << 2)
|
||||
#define TEGRA_MMC_CLKCON_PROG_CLOCK_MODE (1 << 5)
|
||||
|
||||
#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_SHIFT 8
|
||||
#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_MASK (0xff << 8)
|
||||
|
||||
#define TEGRA_MMC_SWRST_SW_RESET_FOR_ALL (1 << 0)
|
||||
#define TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE (1 << 1)
|
||||
#define TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE (1 << 2)
|
||||
|
||||
#define TEGRA_MMC_NORINTSTS_CMD_COMPLETE (1 << 0)
|
||||
#define TEGRA_MMC_NORINTSTS_XFER_COMPLETE (1 << 1)
|
||||
#define TEGRA_MMC_NORINTSTS_DMA_INTERRUPT (1 << 3)
|
||||
#define TEGRA_MMC_NORINTSTS_ERR_INTERRUPT (1 << 15)
|
||||
#define TEGRA_MMC_NORINTSTS_CMD_TIMEOUT (1 << 16)
|
||||
|
||||
#define TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE (1 << 0)
|
||||
#define TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE (1 << 1)
|
||||
#define TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT (1 << 3)
|
||||
#define TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY (1 << 4)
|
||||
#define TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY (1 << 5)
|
||||
|
||||
#define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE (1 << 1)
|
||||
|
||||
typedef struct {
|
||||
/* SDHCI standard registers */
|
||||
uint32_t dma_address;
|
||||
uint16_t block_size;
|
||||
uint16_t block_count;
|
||||
uint32_t argument;
|
||||
uint16_t transfer_mode;
|
||||
uint16_t command;
|
||||
uint32_t response[0x4];
|
||||
uint32_t buffer;
|
||||
uint32_t present_state;
|
||||
uint8_t host_control;
|
||||
uint8_t power_control;
|
||||
uint8_t block_gap_control;
|
||||
uint8_t wake_up_control;
|
||||
uint16_t clock_control;
|
||||
uint8_t timeout_control;
|
||||
uint8_t software_reset;
|
||||
uint32_t int_status;
|
||||
uint32_t int_enable;
|
||||
uint32_t signal_enable;
|
||||
uint16_t acmd12_err;
|
||||
uint16_t host_control2;
|
||||
uint32_t capabilities;
|
||||
uint32_t capabilities_1;
|
||||
uint32_t max_current;
|
||||
uint32_t _0x4c;
|
||||
uint16_t set_acmd12_error;
|
||||
uint16_t set_int_error;
|
||||
uint8_t adma_error;
|
||||
uint8_t _0x56[0x3];
|
||||
uint32_t adma_address;
|
||||
uint32_t upper_adma_address;
|
||||
uint16_t preset_for_init;
|
||||
uint16_t preset_for_default;
|
||||
uint16_t preset_for_high;
|
||||
uint16_t preset_for_sdr12;
|
||||
uint16_t preset_for_sdr25;
|
||||
uint16_t preset_for_sdr50;
|
||||
uint16_t preset_for_sdr104;
|
||||
uint16_t preset_for_ddr50;
|
||||
uint32_t _0x70[0x23];
|
||||
uint16_t slot_int_status;
|
||||
uint16_t host_version;
|
||||
|
||||
/* vendor specific registers */
|
||||
uint32_t vendor_clock_cntrl;
|
||||
uint32_t vendor_sys_sw_cntrl;
|
||||
uint32_t vendor_err_intr_status;
|
||||
uint32_t vendor_cap_overrides;
|
||||
uint32_t vendor_boot_cntrl;
|
||||
uint32_t vendor_boot_ack_timeout;
|
||||
uint32_t vendor_boot_dat_timeout;
|
||||
uint32_t vendor_debounce_count;
|
||||
uint32_t vendor_misc_cntrl;
|
||||
uint32_t max_current_override;
|
||||
uint32_t max_current_override_hi;
|
||||
uint32_t _0x12c[0x20];
|
||||
uint32_t vendor_io_trim_cntrl;
|
||||
|
||||
/* start of sdmmc2/sdmmc4 only */
|
||||
uint32_t vendor_dllcal_cfg;
|
||||
uint32_t vendor_dll_ctrl0;
|
||||
uint32_t vendor_dll_ctrl1;
|
||||
uint32_t vendor_dllcal_cfg_sta;
|
||||
/* end of sdmmc2/sdmmc4 only */
|
||||
|
||||
uint32_t vendor_tuning_cntrl0;
|
||||
uint32_t vendor_tuning_cntrl1;
|
||||
uint32_t vendor_tuning_status0;
|
||||
uint32_t vendor_tuning_status1;
|
||||
uint32_t vendor_clk_gate_hysteresis_count;
|
||||
uint32_t vendor_preset_val0;
|
||||
uint32_t vendor_preset_val1;
|
||||
uint32_t vendor_preset_val2;
|
||||
uint32_t sdmemcomppadctrl;
|
||||
uint32_t auto_cal_config;
|
||||
uint32_t auto_cal_interval;
|
||||
uint32_t auto_cal_status;
|
||||
uint32_t io_spare;
|
||||
uint32_t sdmmca_mccif_fifoctrl;
|
||||
uint32_t timeout_wcoal_sdmmca;
|
||||
uint32_t _0x1fc;
|
||||
} tegra_sdmmc_t;
|
||||
|
||||
static inline volatile tegra_sdmmc_t *sdmmc_get_regs(uint32_t idx)
|
||||
{
|
||||
return (volatile tegra_sdmmc_t *)(0x700B0000 + (idx * 0x200));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef FUSEE_SE_H
|
||||
#define FUSEE_SE_H
|
||||
|
||||
#include "utils.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
|
||||
|
@ -206,4 +205,4 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v
|
|||
void se_initialize_rng(unsigned int keyslot);
|
||||
void se_generate_random(unsigned int keyslot, void *dst, size_t size);
|
||||
|
||||
#endif /* EXOSPHERE_SE_H */
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "utils.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "display/video_fb.h"
|
||||
#include "fs_utils.h"
|
||||
#include "stage2.h"
|
||||
|
@ -97,7 +98,7 @@ void load_stage2(const char *bct0) {
|
|||
} else {
|
||||
tmp_addr = config.load_address;
|
||||
}
|
||||
|
||||
|
||||
if (read_from_file((void *)tmp_addr, size, config.path) != size) {
|
||||
fatal_error("Failed to read stage2 (%s)!\n", config.path);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#ifndef FUSEE_STAGE2_H
|
||||
#define FUSEE_STAGE2_H
|
||||
|
||||
#include "utils.h"
|
||||
#include "sdmmc.h"
|
||||
#include "sdmmc/sdmmc_core.h"
|
||||
|
||||
/* TODO: Is there a more concise way to do this? */
|
||||
#define STAGE2_ARGV_PROGRAM_PATH 0
|
||||
|
@ -22,7 +21,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
struct mmc sd_mmc;
|
||||
sdmmc_t sd_sdmmc;
|
||||
bool display_initialized;
|
||||
char bct0[BCTO_MAX_SIZE];
|
||||
} stage2_args_t;
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/**
|
||||
* Fusée power supply control code
|
||||
* ~ktemkin
|
||||
*/
|
||||
|
||||
#include "lib/driver_utils.h"
|
||||
#include "supplies.h"
|
||||
|
||||
// FIXME: replace hwinit with our own code
|
||||
#include "hwinit/max7762x.h"
|
||||
|
||||
/**
|
||||
* Enables a given power supply.
|
||||
*
|
||||
* @param supply The power domain on the Switch that is to be enabled.
|
||||
* @param use_low_voltage If the supply supports multiple voltages, use the lower one.
|
||||
* Some devices start in a high power mode, but an can be switched to a lower one.
|
||||
* Set this to false unless you know what you're doing.
|
||||
*/
|
||||
void supply_enable(enum switch_power_supply supply, bool use_low_voltage)
|
||||
{
|
||||
uint32_t voltage = 0;
|
||||
|
||||
switch(supply) {
|
||||
case SUPPLY_MICROSD:
|
||||
voltage = use_low_voltage ? SUPPLY_MICROSD_LOW_VOLTAGE : SUPPLY_MICROSD_VOLTAGE;
|
||||
|
||||
max77620_regulator_set_voltage(SUPPLY_MICROSD_REGULATOR, voltage);
|
||||
max77620_regulator_enable(SUPPLY_MICROSD_REGULATOR, true);
|
||||
return;
|
||||
|
||||
default:
|
||||
printk("ERROR: could not enable unknown supply %d!\n", supply);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* Fusée power supply control code
|
||||
* ~ktemkin
|
||||
*/
|
||||
|
||||
#ifndef __FUSEE_SUPPLIES_H__
|
||||
#define __FUSEE_SUPPLIES_H__
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
enum switch_power_supply {
|
||||
SUPPLY_MICROSD,
|
||||
};
|
||||
|
||||
|
||||
enum switch_power_constants {
|
||||
|
||||
/* MicroSD card */
|
||||
SUPPLY_MICROSD_REGULATOR = 6,
|
||||
SUPPLY_MICROSD_VOLTAGE = 3300000,
|
||||
SUPPLY_MICROSD_LOW_VOLTAGE = 1800000,
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enables a given power supply.
|
||||
*
|
||||
* @param supply The power domain on the Switch that is to be enabled.
|
||||
* @param use_low_voltage If the supply supports multiple voltages, use the lower one.
|
||||
* Some devices start in a high power mode, but an can be switched to a lower one.
|
||||
* Set this to false unless you know what you're doing.
|
||||
*/
|
||||
void supply_enable(enum switch_power_supply supply, bool use_low_voltage);
|
||||
|
||||
#endif
|
|
@ -4,9 +4,7 @@
|
|||
#include "utils.h"
|
||||
|
||||
#define TIMERS_BASE 0x60005000
|
||||
|
||||
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
|
||||
|
||||
#define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10)
|
||||
|
||||
typedef struct {
|
||||
|
@ -36,10 +34,9 @@ static inline uint32_t get_time_since(uint32_t base) {
|
|||
/**
|
||||
* Delays for a given number of microseconds.
|
||||
*/
|
||||
static inline void udelay(unsigned usecs)
|
||||
{
|
||||
uint32_t start = get_time();
|
||||
while (get_time() - start < usecs) ;
|
||||
static inline void udelay(unsigned usecs) {
|
||||
uint32_t start = get_time();
|
||||
while (get_time() - start < usecs);
|
||||
}
|
||||
|
||||
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
||||
|
|
Loading…
Reference in a new issue