From ecb616e4115244539f412e420a5413f3b87e3354 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Thu, 30 Apr 2020 03:27:39 +0300 Subject: [PATCH] sdram: Add MR read request --- bootloader/mem/emc.h | 25 +++++++++++++++++++ bootloader/mem/sdram.c | 52 ++++++++++++++++++++++++++++++++++++++- bootloader/mem/sdram.h | 2 ++ nyx/nyx_gui/mem/emc.h | 26 ++++++++++++++++++++ nyx/nyx_gui/mem/sdram.c | 54 +++++++++++++++++++++++++++++++++++++++-- nyx/nyx_gui/mem/sdram.h | 2 ++ 6 files changed, 158 insertions(+), 3 deletions(-) diff --git a/bootloader/mem/emc.h b/bootloader/mem/emc.h index bfce612..dbd7caf 100644 --- a/bootloader/mem/emc.h +++ b/bootloader/mem/emc.h @@ -2,6 +2,7 @@ * arch/arm/mach-tegra/tegra21_emc.h * * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2020, CTCaer. * * 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 @@ -664,4 +665,28 @@ #define EMC_PMC_SCRATCH2 0x444 #define EMC_PMC_SCRATCH3 0x448 +#define EMC_STATUS_UPDATE_TIMEOUT 1000 + +typedef enum _emc_mr_t +{ + MR5_MAN_ID = 5, + MR6_REV_ID1 = 6, + MR7_REV_ID2 = 7, + MR8_DENSITY = 8, +} emc_mr_t; + +enum +{ + EMC_CHAN0 = 0, + EMC_CHAN1 = 1 +}; + +typedef struct _emc_mr_data_t +{ + u8 dev0_ch0; + u8 dev0_ch1; + u8 dev1_ch0; + u8 dev1_ch1; +} emc_mr_data_t; + #endif diff --git a/bootloader/mem/sdram.c b/bootloader/mem/sdram.c index 3bc283d..ca3bcbf 100644 --- a/bootloader/mem/sdram.c +++ b/bootloader/mem/sdram.c @@ -49,6 +49,56 @@ static u32 _get_sdram_id() return sdram_id; } +static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel) +{ + bool err = true; + + for (s32 i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; i++) + { + if (emc_channel) + { + if (emc_channel != 1) + goto done; + + if (((EMC_CH1(reg_offset) & bit_mask) != 0) == updated_state) + { + err = false; + break; + } + } + else if (((EMC(reg_offset) & bit_mask) != 0) == updated_state) + { + err = false; + break; + } + usleep(1); + } + +done: + return err; +} + +static void _sdram_req_mrr_data(u32 data, bool dual_channel) +{ + EMC(EMC_MRR) = data; + _sdram_wait_emc_status(EMC_EMC_STATUS, EMC_STATUS_MRR_DIVLD, true, EMC_CHAN0); + if (dual_channel) + _sdram_wait_emc_status(EMC_EMC_STATUS, EMC_STATUS_MRR_DIVLD, true, EMC_CHAN1); +} + +emc_mr_data_t sdram_read_mrx(emc_mr_t mrx) +{ + emc_mr_data_t data; + _sdram_req_mrr_data((1 << 31) | (mrx << 16), EMC_CHAN0); + data.dev0_ch0 = EMC(EMC_MRR) & 0xFF; + data.dev0_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); + _sdram_req_mrr_data((1 << 30) | (mrx << 16), EMC_CHAN1); + data.dev1_ch0 = EMC(EMC_MRR) & 0xFF; + data.dev1_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); + + return data; +} + static void _sdram_config(const sdram_params_t *params) { // Program DPD3/DPD4 regs (coldboot path). @@ -91,7 +141,7 @@ break_nosleep: if (params->emc_clock_source_dll) CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll; if (params->clear_clock2_mc1) - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000; // Clear Reset to MC1. CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x2000001; // Enable EMC and MEM clocks. CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x4000; // Enable EMC_DLL clock. diff --git a/bootloader/mem/sdram.h b/bootloader/mem/sdram.h index badc703..059bc9c 100644 --- a/bootloader/mem/sdram.h +++ b/bootloader/mem/sdram.h @@ -17,11 +17,13 @@ #ifndef _SDRAM_H_ #define _SDRAM_H_ +#include "emc.h" #include "sdram_param_t210.h" void sdram_init(); sdram_params_t *sdram_get_params(); sdram_params_t *sdram_get_params_patched(); void sdram_lp0_save_params(const void *params); +emc_mr_data_t sdram_read_mrx(emc_mr_t mrx); #endif diff --git a/nyx/nyx_gui/mem/emc.h b/nyx/nyx_gui/mem/emc.h index bfce612..9be6fe8 100644 --- a/nyx/nyx_gui/mem/emc.h +++ b/nyx/nyx_gui/mem/emc.h @@ -2,6 +2,7 @@ * arch/arm/mach-tegra/tegra21_emc.h * * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2020, CTCaer. * * 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 @@ -231,6 +232,7 @@ #define EMC_COMP_PAD_SW_CTRL 0x57c #define EMC_REQ_CTRL 0x2b0 #define EMC_EMC_STATUS 0x2b4 +#define EMC_STATUS_MRR_DIVLD (1 << 20) #define EMC_CFG_2 0x2b8 #define EMC_CFG_DIG_DLL 0x2bc #define EMC_CFG_DIG_DLL_PERIOD 0x2c0 @@ -664,4 +666,28 @@ #define EMC_PMC_SCRATCH2 0x444 #define EMC_PMC_SCRATCH3 0x448 +#define EMC_STATUS_UPDATE_TIMEOUT 1000 + +typedef enum _emc_mr_t +{ + MR5_MAN_ID = 5, + MR6_REV_ID1 = 6, + MR7_REV_ID2 = 7, + MR8_DENSITY = 8, +} emc_mr_t; + +enum +{ + EMC_CHAN0 = 0, + EMC_CHAN1 = 1 +}; + +typedef struct _emc_mr_data_t +{ + u8 dev0_ch0; + u8 dev0_ch1; + u8 dev1_ch0; + u8 dev1_ch1; +} emc_mr_data_t; + #endif diff --git a/nyx/nyx_gui/mem/sdram.c b/nyx/nyx_gui/mem/sdram.c index 9c06ec4..933141a 100644 --- a/nyx/nyx_gui/mem/sdram.c +++ b/nyx/nyx_gui/mem/sdram.c @@ -40,7 +40,57 @@ static u32 _get_sdram_id() { - return (fuse_read_odm(4) & 0x38) >> 3; + return ((fuse_read_odm(4) & 0x38) >> 3); +} + +static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel) +{ + bool err = true; + + for (s32 i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; i++) + { + if (emc_channel) + { + if (emc_channel != 1) + goto done; + + if (((EMC_CH1(reg_offset) & bit_mask) != 0) == updated_state) + { + err = false; + break; + } + } + else if (((EMC(reg_offset) & bit_mask) != 0) == updated_state) + { + err = false; + break; + } + usleep(1); + } + +done: + return err; +} + +static void _sdram_req_mrr_data(u32 data, bool dual_channel) +{ + EMC(EMC_MRR) = data; + _sdram_wait_emc_status(EMC_EMC_STATUS, EMC_STATUS_MRR_DIVLD, true, EMC_CHAN0); + if (dual_channel) + _sdram_wait_emc_status(EMC_EMC_STATUS, EMC_STATUS_MRR_DIVLD, true, EMC_CHAN1); +} + +emc_mr_data_t sdram_read_mrx(emc_mr_t mrx) +{ + emc_mr_data_t data; + _sdram_req_mrr_data((1 << 31) | (mrx << 16), EMC_CHAN0); + data.dev0_ch0 = EMC(EMC_MRR) & 0xFF; + data.dev0_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); + _sdram_req_mrr_data((1 << 30) | (mrx << 16), EMC_CHAN1); + data.dev1_ch0 = EMC(EMC_MRR) & 0xFF; + data.dev1_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); + + return data; } static void _sdram_config(const sdram_params_t *params) @@ -85,7 +135,7 @@ break_nosleep: if (params->emc_clock_source_dll) CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll; if (params->clear_clock2_mc1) - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000; // Clear Reset to MC1. CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x2000001; // Enable EMC and MEM clocks. CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x4000; // Enable EMC_DLL clock. diff --git a/nyx/nyx_gui/mem/sdram.h b/nyx/nyx_gui/mem/sdram.h index badc703..059bc9c 100644 --- a/nyx/nyx_gui/mem/sdram.h +++ b/nyx/nyx_gui/mem/sdram.h @@ -17,11 +17,13 @@ #ifndef _SDRAM_H_ #define _SDRAM_H_ +#include "emc.h" #include "sdram_param_t210.h" void sdram_init(); sdram_params_t *sdram_get_params(); sdram_params_t *sdram_get_params_patched(); void sdram_lp0_save_params(const void *params); +emc_mr_data_t sdram_read_mrx(emc_mr_t mrx); #endif