thermosphere: attempt to output to uart-c

This commit is contained in:
TuxSH 2019-07-19 01:45:56 +02:00
parent 4e6108839d
commit 076c988796
10 changed files with 958 additions and 55 deletions

View file

@ -14,41 +14,86 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "utils.h"
#include "car.h" #include "car.h"
#include "timers.h" #include "timers.h"
#include "utils.h"
static inline u32 get_special_clk_reg(CarDevice dev) { static inline uint32_t get_clk_source_reg(CarDevice dev) {
switch (dev) { switch (dev) {
case CARDEVICE_UARTA: return 0x178; case CARDEVICE_UARTA: return 0x178;
case CARDEVICE_UARTB: return 0x17C; case CARDEVICE_UARTB: return 0x17C;
case CARDEVICE_UARTC: return 0x1A0;
case CARDEVICE_I2C1: return 0x124; case CARDEVICE_I2C1: return 0x124;
case CARDEVICE_I2C5: return 0x128; case CARDEVICE_I2C5: return 0x128;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0x42C;
case CARDEVICE_HOST1X: return 0x180;
case CARDEVICE_TSEC: return 0x1F4;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 0x410;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 0x1D4;
case CARDEVICE_ACTMON: return 0x3E8; case CARDEVICE_ACTMON: return 0x3E8;
case CARDEVICE_BPMP: return 0; case CARDEVICE_BPMP: return 0;
default: return -1;// generic_panic(); default: return 0;//generic_panic();
} }
} }
static inline u32 get_special_clk_val(CarDevice dev) { static inline uint32_t get_clk_source_val(CarDevice dev) {
switch (dev) { switch (dev) {
case CARDEVICE_UARTA: return 0; case CARDEVICE_UARTA: return 0;
case CARDEVICE_UARTB: return 0; case CARDEVICE_UARTB: return 0;
case CARDEVICE_I2C1: return (6 << 29); case CARDEVICE_UARTC: return 0;
case CARDEVICE_I2C5: return (6 << 29); case CARDEVICE_I2C1: return 6;
case CARDEVICE_ACTMON: return (6 << 29); case CARDEVICE_I2C5: return 6;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0;
case CARDEVICE_HOST1X: return 4;
case CARDEVICE_TSEC: return 0;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 0;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 0;
case CARDEVICE_ACTMON: return 6;
case CARDEVICE_BPMP: return 0; case CARDEVICE_BPMP: return 0;
default: return -1; //generic_panic(); default: return 0;//generic_panic();
} }
} }
static u32 g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; static inline uint32_t get_clk_source_div(CarDevice dev) {
static u32 g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; switch (dev) {
case CARDEVICE_UARTA: return 0;
case CARDEVICE_UARTB: return 0;
case CARDEVICE_UARTC: return 0;
case CARDEVICE_I2C1: return 0;
case CARDEVICE_I2C5: return 0;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0;
case CARDEVICE_HOST1X: return 3;
case CARDEVICE_TSEC: return 2;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 2;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 4;
case CARDEVICE_ACTMON: return 0;
case CARDEVICE_BPMP: return 0;
default: return 0;//generic_panic();
}
}
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298};
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
void clk_enable(CarDevice dev) { void clk_enable(CarDevice dev) {
u32 special_reg; uint32_t clk_source_reg;
if ((special_reg = get_special_clk_reg(dev))) { if ((clk_source_reg = get_clk_source_reg(dev))) {
MAKE_CAR_REG(special_reg) = get_special_clk_val(dev); MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev);
} }
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
} }
@ -65,7 +110,6 @@ void rst_disable(CarDevice dev) {
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
} }
void clkrst_enable(CarDevice dev) { void clkrst_enable(CarDevice dev) {
clk_enable(dev); clk_enable(dev);
rst_disable(dev); rst_disable(dev);
@ -78,5 +122,18 @@ void clkrst_disable(CarDevice dev) {
void clkrst_reboot(CarDevice dev) { void clkrst_reboot(CarDevice dev) {
clkrst_disable(dev); clkrst_disable(dev);
clkrst_enable(dev); if (dev == CARDEVICE_KFUSE) {
/* Workaround for KFUSE clock. */
clk_enable(dev);
udelay(100);
rst_disable(dev);
udelay(200);
} else {
clkrst_enable(dev);
}
}
void clkrst_enable_fuse_regs(bool enable) {
volatile tegra_car_t *car = car_get_regs();
car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28));
} }

View file

@ -17,27 +17,477 @@
#pragma once #pragma once
#include "utils.h" #include "utils.h"
#define CAR_BASE 0x60006000ull #define CAR_BASE 0x60006000
#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) #define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n)
#define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 MAKE_CAR_REG(0x048) #define CLK_L_SDMMC1 (1 << 14)
#define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) #define CLK_L_SDMMC2 (1 << 9)
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) #define CLK_U_SDMMC3 (1 << 5)
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) #define CLK_L_SDMMC4 (1 << 15)
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454)
#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 NUM_CAR_BANKS 7 #define NUM_CAR_BANKS 7
/* Clock and reset devices. */
typedef enum { typedef enum {
CARDEVICE_UARTA = 6, CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = 7, CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_I2C1 = 12, CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_I2C5 = 47, CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_ACTMON = 119, CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_BPMP = 1 CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_BPMP = ((0 << 5) | 0x1)
} CarDevice; } CarDevice;
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
typedef struct {
uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */
/* _RST_DEVICES_L/H/U_0 0x4-0xc */
uint32_t rst_dev_l;
uint32_t rst_dev_h;
uint32_t rst_dev_u;
/* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */
uint32_t clk_out_enb_l;
uint32_t clk_out_enb_h;
uint32_t clk_out_enb_u;
uint32_t _0x1C;
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */
uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */
uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */
uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */
uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */
uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */
uint32_t _0x3C;
uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */
uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */
uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */
uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */
uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */
uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */
uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */
uint32_t _0x60[2];
uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */
uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */
uint32_t _0x70[4];
/* PLLC 0x80-0x8c */
uint32_t pllc_base;
uint32_t pllc_out;
uint32_t pllc_misc0;
uint32_t pllc_misc1;
/* PLLM 0x90-0x9c */
uint32_t pllm_base;
uint32_t pllm_out;
uint32_t pllm_misc1;
uint32_t pllm_misc2;
/* PLLP 0xa0-0xac */
uint32_t pllp_base;
uint32_t pllp_outa;
uint32_t pllp_outb;
uint32_t pllp_misc;
/* PLLA 0xb0-0xbc */
uint32_t plla_base;
uint32_t plla_out;
uint32_t plla_misc0;
uint32_t plla_misc1;
/* PLLU 0xc0-0xcc */
uint32_t pllu_base;
uint32_t pllu_out;
uint32_t pllu_misc1;
uint32_t pllu_misc2;
/* PLLD 0xd0-0xdc */
uint32_t plld_base;
uint32_t plld_out;
uint32_t plld_misc1;
uint32_t plld_misc2;
/* PLLX 0xe0-0xe4 */
uint32_t pllx_base;
uint32_t pllx_misc;
/* PLLE 0xe8-0xf4 */
uint32_t plle_base;
uint32_t plle_misc;
uint32_t plle_ss_cntl1;
uint32_t plle_ss_cntl2;
uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */
uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */
uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */
uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */
uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */
uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */
uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */
uint32_t _0x114;
uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */
uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */
uint32_t _0x120;
uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */
uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */
uint32_t _0x12c[2];
uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */
uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */
uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */
uint32_t _0x140;
uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */
uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */
uint32_t _0x14c;
uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */
uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */
uint32_t _0x158[3];
uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */
uint32_t _0x168[4];
uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */
uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */
uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */
uint32_t _0x184[5];
uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */
uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */
uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */
uint32_t _0x1a4;
uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */
uint32_t _0x1ac[2];
uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */
uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */
uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */
uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */
uint32_t _0x1c4[2];
uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */
uint32_t _0x1d0;
uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */
uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */
uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */
uint32_t _0x1e0[5];
uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */
uint32_t _0x1f8;
uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */
uint32_t _0x200[32];
uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */
uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */
uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */
uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */
uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */
uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */
uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */
uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */
uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */
uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */
uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */
uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */
uint32_t _0x2b0[17];
uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */
uint32_t _0x2f8[2];
/* _RST_DEV_L/H/U_SET_0 0x300-0x314 */
uint32_t rst_dev_l_set;
uint32_t rst_dev_l_clr;
uint32_t rst_dev_h_set;
uint32_t rst_dev_h_clr;
uint32_t rst_dev_u_set;
uint32_t rst_dev_u_clr;
uint32_t _0x318[2];
/* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */
uint32_t clk_enb_l_set;
uint32_t clk_enb_l_clr;
uint32_t clk_enb_h_set;
uint32_t clk_enb_h_clr;
uint32_t clk_enb_u_set;
uint32_t clk_enb_u_clr;
uint32_t _0x338;
uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */
uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */
uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */
/* Additional (T30) registers */
uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
uint32_t _0x350[2];
uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */
uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
uint32_t _0x38c[5];
uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */
uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */
uint32_t _0x3a8[2];
uint32_t _0x3b0;
uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */
uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */
uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */
uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */
uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */
uint32_t _0x3c8[2];
uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */
uint32_t _0x3d4[4];
uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */
uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */
uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */
uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */
uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */
uint32_t _0x3f8;
uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */
uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */
uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */
uint32_t _0x408[2];
uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */
uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */
uint32_t _0x418[2];
uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */
uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */
uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */
uint32_t _0x42c;
/* _RST_DEV_V/W_SET_0 0x430-0x43c */
uint32_t rst_dev_v_set;
uint32_t rst_dev_v_clr;
uint32_t rst_dev_w_set;
uint32_t rst_dev_w_clr;
/* _CLK_ENB_V/W_CLR_0 0x440-0x44c */
uint32_t clk_enb_v_set;
uint32_t clk_enb_v_clr;
uint32_t clk_enb_w_set;
uint32_t clk_enb_w_clr;
/* Additional (T114+) registers */
uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */
uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */
uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */
uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */
uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */
uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */
uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */
uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */
uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */
uint32_t _0x474;
uint32_t intstatus; /* _INTSTATUS_0, 0x478 */
uint32_t intmask; /* _INTMASK_0, 0x47c */
uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */
uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */
uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */
uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */
uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */
uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */
uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */
uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */
uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */
uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */
uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */
uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */
uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */
uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */
uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */
uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */
uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */
uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */
uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */
uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */
uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */
uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */
uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */
uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */
uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */
uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */
uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */
uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */
uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */
uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */
uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */
uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */
uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */
uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */
uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */
uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */
uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */
uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */
uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */
uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */
uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */
uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */
uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */
uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */
uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */
uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */
uint32_t _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 lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */
uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */
uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */
uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */
uint32_t _0x568[2];
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */
uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */
uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */
uint32_t _0x57c[5];
uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/
uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */
uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */
uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */
uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */
uint32_t _0x5ac[6];
uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */
uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */
uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */
uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */
uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */
uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */
uint32_t _0x5dc[2];
uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */
uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */
uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */
uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */
uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */
uint32_t _0x5f8[2];
uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */
uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */
uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */
uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */
uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */
uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */
uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */
uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */
uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */
uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */
uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */
uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */
uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */
uint32_t _0x634[3];
uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */
uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */
uint32_t _0x648;
uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */
uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */
uint32_t _0x654;
uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */
uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */
uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */
uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */
uint32_t _0x668;
uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */
uint32_t _0x670[2];
uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */
uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */
uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */
uint32_t _0x684[2];
uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */
uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */
uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */
uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */
uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */
uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */
uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */
uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */
uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */
uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */
uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */
uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */
uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */
uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */
uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */
uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */
uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */
uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */
uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */
uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */
uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */
uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */
uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */
uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */
uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */
uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */
uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */
uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */
uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */
uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */
uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */
uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */
uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */
uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */
uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */
uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */
uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */
uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
} tegra_car_t;
static inline volatile tegra_car_t *car_get_regs(void) {
return (volatile tegra_car_t *)CAR_BASE;
}
void clk_enable(CarDevice dev); void clk_enable(CarDevice dev);
void clk_disable(CarDevice dev); void clk_disable(CarDevice dev);
void rst_enable(CarDevice dev); void rst_enable(CarDevice dev);
@ -45,5 +495,6 @@ void rst_disable(CarDevice dev);
void clkrst_enable(CarDevice dev); void clkrst_enable(CarDevice dev);
void clkrst_disable(CarDevice dev); void clkrst_disable(CarDevice dev);
void clkrst_reboot(CarDevice dev); void clkrst_reboot(CarDevice dev);
void clkrst_enable_fuse_regs(bool enable);

307
thermosphere/src/fmt.c Normal file
View file

@ -0,0 +1,307 @@
/*
* Copyright (c) 2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Adapted from Luma3DS with permission. */
/* File : barebones/ee_printf.c
This file contains an implementation of ee_printf that only requires a method to output a char to a UART without pulling in library code.
This code is based on a file that contains the following:
Copyright (C) 2002 Michael Ringgaard. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
//TuxSH's changes: add support for 64-bit numbers, remove floating-point code
#include <string.h>
#include <stdarg.h>
#include "types.h"
#define ZEROPAD (1<<0) //Pad with zero
#define SIGN (1<<1) //Unsigned/signed long
#define PLUS (1<<2) //Show plus
#define SPACE (1<<3) //Spacer
#define LEFT (1<<4) //Left justified
#define HEX_PREP (1<<5) //0x
#define UPPERCASE (1<<6) //'ABCDEF'
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
static s32 skipAtoi(const char **s)
{
s32 i = 0;
while(IS_DIGIT(**s)) i = i * 10 + *((*s)++) - '0';
return i;
}
static char *processNumber(char *str, s64 num, bool isHex, s32 size, s32 precision, u32 type)
{
char sign = 0;
if(type & SIGN)
{
if(num < 0)
{
sign = '-';
num = -num;
size--;
}
else if(type & PLUS)
{
sign = '+';
size--;
}
else if(type & SPACE)
{
sign = ' ';
size--;
}
}
static const char *lowerDigits = "0123456789abcdef",
*upperDigits = "0123456789ABCDEF";
s32 i = 0;
char tmp[20];
const char *dig = (type & UPPERCASE) ? upperDigits : lowerDigits;
if(num == 0)
{
if(precision != 0) tmp[i++] = '0';
type &= ~HEX_PREP;
}
else
{
while(num != 0)
{
u64 base = isHex ? 16ULL : 10ULL;
tmp[i++] = dig[(u64)num % base];
num = (s64)((u64)num / base);
}
}
if(type & LEFT || precision != -1) type &= ~ZEROPAD;
if(type & HEX_PREP && isHex) size -= 2;
if(i > precision) precision = i;
size -= precision;
if(!(type & (ZEROPAD | LEFT))) while(size-- > 0) *str++ = ' ';
if(sign) *str++ = sign;
if(type & HEX_PREP && isHex)
{
*str++ = '0';
*str++ = 'x';
}
if(type & ZEROPAD) while(size-- > 0) *str++ = '0';
while(i < precision--) *str++ = '0';
while(i-- > 0) *str++ = tmp[i];
while(size-- > 0) *str++ = ' ';
return str;
}
int vsprintf(char *buf, const char *fmt, va_list args)
{
char *str;
for(str = buf; *fmt; fmt++)
{
if(*fmt != '%')
{
*str++ = *fmt;
continue;
}
//Process flags
u32 flags = 0; //Flags to number()
bool loop = true;
while(loop)
{
switch(*++fmt)
{
case '-': flags |= LEFT; break;
case '+': flags |= PLUS; break;
case ' ': flags |= SPACE; break;
case '#': flags |= HEX_PREP; break;
case '0': flags |= ZEROPAD; break;
default: loop = false; break;
}
}
//Get field width
s32 fieldWidth = -1; //Width of output field
if(IS_DIGIT(*fmt)) fieldWidth = skipAtoi(&fmt);
else if(*fmt == '*')
{
fmt++;
fieldWidth = va_arg(args, s32);
if(fieldWidth < 0)
{
fieldWidth = -fieldWidth;
flags |= LEFT;
}
}
//Get the precision
s32 precision = -1; //Min. # of digits for integers; max number of chars for from string
if(*fmt == '.')
{
fmt++;
if(IS_DIGIT(*fmt)) precision = skipAtoi(&fmt);
else if(*fmt == '*')
{
fmt++;
precision = va_arg(args, s32);
}
if(precision < 0) precision = 0;
}
//Get the conversion qualifier
u32 integerType = 0;
if(*fmt == 'l')
{
if(*++fmt == 'l')
{
fmt++;
integerType = 1;
}
}
else if(*fmt == 'h')
{
if(*++fmt == 'h')
{
fmt++;
integerType = 3;
}
else integerType = 2;
}
bool isHex;
switch(*fmt)
{
case 'c':
if(!(flags & LEFT)) while(--fieldWidth > 0) *str++ = ' ';
*str++ = (u8)va_arg(args, s32);
while(--fieldWidth > 0) *str++ = ' ';
continue;
case 's':
{
char *s = va_arg(args, char *);
if(!s) s = "<NULL>";
u32 len = (precision != -1) ? strnlen(s, precision) : strlen(s);
if(!(flags & LEFT)) while((s32)len < fieldWidth--) *str++ = ' ';
for(u32 i = 0; i < len; i++) *str++ = *s++;
while((s32)len < fieldWidth--) *str++ = ' ';
continue;
}
case 'p':
if(fieldWidth == -1)
{
fieldWidth = 8;
flags |= ZEROPAD;
}
str = processNumber(str, va_arg(args, u32), true, fieldWidth, precision, flags);
continue;
//Integer number formats - set up the flags and "break"
case 'X':
flags |= UPPERCASE;
//Falls through
case 'x':
isHex = true;
break;
case 'd':
case 'i':
flags |= SIGN;
//Falls through
case 'u':
isHex = false;
break;
default:
if(*fmt != '%') *str++ = '%';
if(*fmt) *str++ = *fmt;
else fmt--;
continue;
}
s64 num;
if(flags & SIGN)
{
if(integerType == 1) num = va_arg(args, s64);
else num = va_arg(args, s32);
if(integerType == 2) num = (s16)num;
else if(integerType == 3) num = (s8)num;
}
else
{
if(integerType == 1) num = va_arg(args, u64);
else num = va_arg(args, u32);
if(integerType == 2) num = (u16)num;
else if(integerType == 3) num = (u8)num;
}
str = processNumber(str, num, isHex, fieldWidth, precision, flags);
}
*str = 0;
return str - buf;
}
int sprintf(char *buf, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int res = vsprintf(buf, fmt, args);
va_end(args);
return res;
}

33
thermosphere/src/log.c Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "log.h"
#include "uart.h"
#include "utils.h"
// NOTE: UNSAFE!
int serialLog(const char *fmt, ...)
{
char buf[128];
va_list args;
va_start(args, fmt);
int res = vsprintf(buf, fmt, args);
va_end(args);
uart_send(UART_C, buf, res);
return res;
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2019 Atmosphère-NX * Copyright (c) 2019 Atmosphère-NX
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -14,12 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "utils.h" #pragma once
#include "timers.h" #include <stdarg.h>
void wait(u32 microseconds) { int serialLog(const char *fmt, ...);
u32 old_time = TIMERUS_CNTR_1US_0;
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
/* Spin-lock. */
}
}

View file

@ -1,7 +1,15 @@
#include "utils.h" #include "utils.h"
#include "uart.h"
#include "car.h"
#include "log.h"
int main(void) int main(void)
{ {
// Setup stuff // Init uart (hardcoded atm)
uart_select(UART_C);
clkrst_reboot(CARDEVICE_UARTC);
uart_init(UART_C, 115200, true);
serialLog("Hello from Thermosphere!\n");
return 0; return 0;
} }

View file

@ -15,29 +15,81 @@
*/ */
#pragma once #pragma once
#include "utils.h" #include "utils.h"
#define TIMERS_BASE 0x60005000ull #define TIMERS_BASE 0x60005000
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) #define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) #define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10)
#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14)
#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0) #define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0)
#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4) #define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4)
#define RTC_BASE 0x7000E000
#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n)
#define RTC_SECONDS MAKE_RTC_REG(0x08)
#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C)
#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10)
typedef struct { typedef struct {
u32 CONFIG; uint32_t CONFIG;
u32 STATUS; uint32_t STATUS;
u32 COMMAND; uint32_t COMMAND;
u32 PATTERN; uint32_t PATTERN;
} watchdog_timers_t; } watchdog_timers_t;
#define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) #define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n))
#define WDT_REBOOT_PATTERN 0xC45A #define WDT_REBOOT_PATTERN 0xC45A
#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n) #define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n)
void wait(u32 microseconds); void wait(uint32_t microseconds);
static inline u32 get_time(void) { static inline uint32_t get_time_s(void) {
return RTC_SECONDS;
}
static inline uint32_t get_time_ms(void) {
return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10));
}
static inline uint32_t get_time_us(void) {
return TIMERUS_CNTR_1US_0; return TIMERUS_CNTR_1US_0;
} }
/**
* Returns the time in microseconds.
*/
static inline uint32_t get_time(void) {
return get_time_us();
}
/**
* Returns the number of microseconds that have passed since a given get_time().
*/
static inline uint32_t get_time_since(uint32_t base) {
return get_time_us() - base;
}
/**
* Delays for a given number of microseconds.
*/
static inline void udelay(uint32_t usecs) {
uint32_t start = get_time_us();
while (get_time_us() - start < usecs);
}
/**
* Delays until a number of usecs have passed since an absolute start time.
*/
static inline void udelay_absolute(uint32_t start, uint32_t usecs) {
while (get_time_us() - start < usecs);
}
/**
* Delays for a given number of milliseconds.
*/
static inline void mdelay(uint32_t msecs) {
uint32_t start = get_time_ms();
while (get_time_ms() - start < msecs);
}

View file

@ -27,7 +27,7 @@ void uart_select(UartDevice dev) {
PINMUX_AUX_UARTn_CTS_0(id) = 0x44; /* UART, enable, pull down */ PINMUX_AUX_UARTn_CTS_0(id) = 0x44; /* UART, enable, pull down */
} }
void uart_init(UartDevice dev, u32 baud) { void uart_init(UartDevice dev, u32 baud, bool txInverted) {
volatile uart_t *uart = get_uart_device(dev); volatile uart_t *uart = get_uart_device(dev);
/* Set baud rate. */ /* Set baud rate. */
@ -41,11 +41,11 @@ void uart_init(UartDevice dev, u32 baud) {
uart->UART_IER_DLAB = 0; uart->UART_IER_DLAB = 0;
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */ uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */
uart->UART_LSR; uart->UART_LSR;
wait(3 * ((baud + 999999) / baud)); udelay(3 * ((baud + 999999) / baud));
uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */ uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */
uart->UART_MCR = 0; uart->UART_MCR = 0;
uart->UART_MSR = 0; uart->UART_MSR = 0;
uart->UART_IRDA_CSR = 0; uart->UART_IRDA_CSR = txInverted ? 2 : 0;
uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */ uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */
uart->UART_MIE = 0; uart->UART_MIE = 0;
uart->UART_ASR = 0; uart->UART_ASR = 0;

View file

@ -156,7 +156,7 @@ typedef struct {
} uart_t; } uart_t;
void uart_select(UartDevice dev); void uart_select(UartDevice dev);
void uart_init(UartDevice dev, u32 baud); void uart_init(UartDevice dev, u32 baud, bool txInverted);
void uart_wait_idle(UartDevice dev, UartVendorStatus status); void uart_wait_idle(UartDevice dev, UartVendorStatus status);
void uart_send(UartDevice dev, const void *buf, size_t len); void uart_send(UartDevice dev, const void *buf, size_t len);
void uart_recv(UartDevice dev, void *buf, size_t len); void uart_recv(UartDevice dev, void *buf, size_t len);

View file

@ -26,7 +26,7 @@
#define MASK2(a,b) (MASK(a) & ~MASK(b)) #define MASK2(a,b) (MASK(a) & ~MASK(b))
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) #define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
#define MAKE_REG32(a) (*(volatile u32 *)(a)) #define MAKE_REG32(a) (*(volatile u32 *)(uintptr_t)(a))
#define ALIGN(m) __attribute__((aligned(m))) #define ALIGN(m) __attribute__((aligned(m)))
#define PACKED __attribute__((packed)) #define PACKED __attribute__((packed))