mirror of
https://github.com/Decscots/Lockpick_RCM.git
synced 2024-11-01 04:25:08 +01:00
Add BPMP overclock, add hekate fixes, fix sprintf
This commit is contained in:
parent
34890f0025
commit
82bea6be8f
112
source/gfx/di.c
112
source/gfx/di.c
@ -18,15 +18,16 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "di.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../power/max77620.h"
|
||||
#include "../power/max7762x.h"
|
||||
#include "../soc/gpio.h"
|
||||
#include "../soc/pinmux.h"
|
||||
#include "../soc/clock.h"
|
||||
#include "../soc/gpio.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../soc/pinmux.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#include "di.inl"
|
||||
|
||||
@ -46,54 +47,61 @@ void display_init()
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL);
|
||||
|
||||
// Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x20000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIP_CAL) = 0xA;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 0xA;
|
||||
// Enable Display Interface specific clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000; // Clear reset DSI, MIPI_CAL.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000; // Set enable clock DSI, MIPI_CAL.
|
||||
|
||||
// DPD idle.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000; // Set enable clock DISP1, HOST1X.
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x20000; // Set enable clock UART_FST_MIPI_CAL.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = 10; // Set PLLP_OUT3 and div 6 (17MHz).
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000; // Set enable clock DSIA_LP.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
|
||||
|
||||
// Disable deap power down.
|
||||
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
|
||||
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
|
||||
|
||||
// Config pins.
|
||||
// Config LCD and Backlight pins.
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE;
|
||||
|
||||
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); // Backlight +-5V.
|
||||
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); // Backlight +-5V.
|
||||
// Set Backlight +-5V pins mode and direction
|
||||
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE);
|
||||
|
||||
// Enable Backlight power.
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // Backlight +5V enable.
|
||||
|
||||
usleep(10000);
|
||||
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // Backlight -5V enable.
|
||||
|
||||
usleep(10000);
|
||||
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO); // Backlight PWM, Enable, Reset.
|
||||
// Configure Backlight pins (PWM, EN, RST).
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Backlight Enable enable.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Enable Backlight EN.
|
||||
|
||||
// Config display interface and display.
|
||||
// Power up supply regulator for display interface.
|
||||
MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0;
|
||||
|
||||
// Set DISP1 clock source and parrent clock.
|
||||
exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4);
|
||||
|
||||
// Setup display communication interfaces.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_3, 61);
|
||||
|
||||
usleep(10000);
|
||||
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); // Backlight Reset enable.
|
||||
|
||||
// Enable Backlight Reset.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH);
|
||||
usleep(60000);
|
||||
|
||||
// Setups DSI packet configuration and request display id.
|
||||
DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204;
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x337; // MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
@ -122,19 +130,22 @@ void display_init()
|
||||
|
||||
usleep(20000);
|
||||
|
||||
// Configure PLLD for DISP1.
|
||||
exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3);
|
||||
|
||||
// Finalize DSI configuration.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_5, 21);
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4;
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_7, 10);
|
||||
|
||||
usleep(10000);
|
||||
|
||||
// Calibrate display communication pads.
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_9, 4);
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16);
|
||||
|
||||
usleep(10000);
|
||||
|
||||
// Enable video display controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113);
|
||||
}
|
||||
|
||||
@ -142,11 +153,10 @@ void display_backlight_pwm_init()
|
||||
{
|
||||
clock_enable_pwm();
|
||||
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31); // Enable PWM
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM.
|
||||
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; // PWM clock source.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFFC) | 1; // PWM clock source.
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
|
||||
|
||||
}
|
||||
|
||||
void display_backlight(bool enable)
|
||||
@ -167,7 +177,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
{
|
||||
for (u32 i = old_value; i < brightness + 1; i++)
|
||||
{
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31) | (i << 16); // Enable PWM
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
|
||||
usleep(step_delay);
|
||||
}
|
||||
}
|
||||
@ -175,7 +185,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
{
|
||||
for (u32 i = old_value; i > brightness; i--)
|
||||
{
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31) | (i << 16); // Enable PWM
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
|
||||
usleep(step_delay);
|
||||
}
|
||||
}
|
||||
@ -191,13 +201,14 @@ void display_end()
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF
|
||||
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // Disable host cmd packet.
|
||||
|
||||
// De-initialize video controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_13, 16);
|
||||
|
||||
usleep(10000);
|
||||
|
||||
// De-initialize display panel.
|
||||
if (_display_ver == 0x10)
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_14, 22);
|
||||
|
||||
@ -206,31 +217,31 @@ void display_end()
|
||||
|
||||
usleep(50000);
|
||||
|
||||
// Disable display and backlight pins.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
|
||||
|
||||
usleep(10000);
|
||||
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable.
|
||||
|
||||
usleep(10000);
|
||||
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable.
|
||||
|
||||
usleep(10000);
|
||||
|
||||
// Disable clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000;
|
||||
// Disable Display Interface specific clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000; // Set reset clock DSI, MIPI_CAL.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000; // Clear enable clock DSI, MIPI_CAL.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1X.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000; // Clear enable DISP1, HOST1X.
|
||||
|
||||
// Power down pads.
|
||||
DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);
|
||||
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
|
||||
|
||||
// Switch to automatic function mode.
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
|
||||
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFFC)| 1;
|
||||
}
|
||||
|
||||
void display_color_screen(u32 color)
|
||||
@ -243,7 +254,6 @@ void display_color_screen(u32 color)
|
||||
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ;
|
||||
|
||||
usleep(35000);
|
||||
|
||||
display_backlight(true);
|
||||
@ -252,11 +262,11 @@ void display_color_screen(u32 color)
|
||||
u32 *display_init_framebuffer()
|
||||
{
|
||||
// Sanitize framebuffer area.
|
||||
memset((u32 *)0xC0000000, 0, 0x3C0000);
|
||||
// This configures the framebuffer @ 0xC0000000 with a resolution of 1280x720 (line stride 768).
|
||||
memset((u32 *)FB_ADDRESS, 0, 0x3C0000);
|
||||
// This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32);
|
||||
|
||||
usleep(35000);
|
||||
|
||||
return (u32 *)0xC0000000;
|
||||
return (u32 *)FB_ADDRESS;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
#define FB_ADDRESS 0xC0000000
|
||||
|
||||
/*! Display registers. */
|
||||
#define _DIREG(reg) ((reg) * 4)
|
||||
|
||||
@ -233,7 +235,7 @@
|
||||
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
|
||||
#define DC_WIN_DV_CONTROL 0x70E
|
||||
|
||||
// The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER).
|
||||
/*! The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
|
||||
#define DC_WINBUF_START_ADDR 0x800
|
||||
#define DC_WINBUF_ADDR_H_OFFSET 0x806
|
||||
#define DC_WINBUF_ADDR_V_OFFSET 0x808
|
||||
@ -333,7 +335,7 @@
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
|
||||
|
||||
#define DSI_PAD_CONTROL_CD 0x4c
|
||||
#define DSI_PAD_CONTROL_CD 0x4C
|
||||
#define DSI_VIDEO_MODE_CONTROL 0x4E
|
||||
|
||||
#define DSI_PAD_CONTROL_1 0x4F
|
||||
|
@ -122,7 +122,7 @@ static const cfg_op_t _display_config_2[94] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}
|
||||
};
|
||||
@ -405,7 +405,7 @@ static const cfg_op_t _display_config_11[113] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
@ -455,7 +455,7 @@ static const cfg_op_t _display_config_12[17] = {
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_CMD_INT_ENABLE, 0},
|
||||
{DC_CMD_CONT_SYNCPT_VSYNC, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
@ -548,7 +548,7 @@ static const cfg_op_t cfg_display_framebuffer[32] = {
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, 0},
|
||||
{DC_WINBUF_SURFACE_KIND, 0}, //Regular surface.
|
||||
{DC_WINBUF_START_ADDR, 0xC0000000}, //Framebuffer address.
|
||||
{DC_WINBUF_START_ADDR, FB_ADDRESS}, //Framebuffer address.
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0},
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 0},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
|
@ -128,12 +128,12 @@ void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride)
|
||||
|
||||
void gfx_clear_grey(u8 color)
|
||||
{
|
||||
memset(gfx_ctxt.fb, color, 0x3C0000);
|
||||
memset(gfx_ctxt.fb, color, gfx_ctxt.width * gfx_ctxt.height * 4);
|
||||
}
|
||||
|
||||
void gfx_clear_color(u32 color)
|
||||
{
|
||||
for (u32 i = 0; i < gfx_ctxt.height * gfx_ctxt.stride; i++)
|
||||
for (u32 i = 0; i < gfx_ctxt.width * gfx_ctxt.height; i++)
|
||||
gfx_ctxt.fb[i] = color;
|
||||
}
|
||||
|
||||
|
@ -537,7 +537,7 @@ pkg2_done:
|
||||
FIL fp;
|
||||
// sysmodule NCAs only ever have one section (exefs) so 0x600 is sufficient
|
||||
u8 *dec_header = (u8*)malloc(0x600);
|
||||
char path[100] = "sd:/test/nca1111111111111";//"emmc:/Contents/registered";
|
||||
char path[100] = "emmc:/Contents/registered";
|
||||
u32 titles_found = 0, title_limit = 2, read_bytes = 0;
|
||||
if (!memcmp(pkg1_id->id, "2016", 4))
|
||||
title_limit = 1;
|
||||
|
@ -1,10 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------/
|
||||
/ FatFs - Generic FAT Filesystem Module R0.13c (p3) /
|
||||
/ FatFs - Generic FAT Filesystem Module R0.13c (p4) /
|
||||
/-----------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||
/ Copyright (c) 2018 naehrwert
|
||||
/ Copyright (C) 2018-2019 CTCaer
|
||||
/
|
||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||
/ source and binary forms, with or without modification, are permitted provided
|
||||
@ -3472,7 +3487,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
#if FF_USE_LFN == 1
|
||||
fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
|
||||
#if FF_FS_EXFAT
|
||||
fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */
|
||||
fs->dirbuf = DirBuf; /* Static directory block scratchpad buffer */
|
||||
#endif
|
||||
#endif
|
||||
#if FF_FS_RPATH != 0
|
||||
@ -4243,9 +4258,9 @@ FRESULT f_getcwd (
|
||||
TCHAR *tp = buff;
|
||||
#if FF_VOLUMES >= 2
|
||||
UINT vl;
|
||||
#endif
|
||||
#if FF_STR_VOLUME_ID
|
||||
const char *vp;
|
||||
#endif
|
||||
#endif
|
||||
FILINFO fno;
|
||||
DEF_NAMBUF
|
||||
@ -4726,7 +4741,7 @@ FRESULT f_getfree (
|
||||
/* Get logical drive */
|
||||
res = find_volume(&path, &fs, 0);
|
||||
if (res == FR_OK) {
|
||||
*fatfs = fs; /* Return ptr to the fs object */
|
||||
if (fatfs) *fatfs = fs; /* Return ptr to the fs object */
|
||||
/* If free_clst is valid, return it without full FAT scan */
|
||||
if (fs->free_clst <= fs->n_fatent - 2) {
|
||||
*nclst = fs->free_clst;
|
||||
@ -6632,4 +6647,3 @@ FRESULT f_setcp (
|
||||
return FR_OK;
|
||||
}
|
||||
#endif /* FF_CODE_PAGE == 0 */
|
||||
|
||||
|
@ -95,6 +95,7 @@ typedef DWORD FSIZE_t;
|
||||
/* Filesystem object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||
BYTE pdrv; /* Associated physical drive */
|
||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||
@ -137,8 +138,6 @@ typedef struct {
|
||||
DWORD bitbase; /* Allocation bitmap base sector */
|
||||
#endif
|
||||
DWORD winsect; /* Current sector appearing in the win[] */
|
||||
DWORD padding; /* Ensure window is 16-aligned */
|
||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
} FATFS;
|
||||
|
||||
|
||||
@ -169,6 +168,9 @@ typedef struct {
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
#if !FF_FS_TINY
|
||||
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
|
||||
#endif
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
@ -179,9 +181,6 @@ typedef struct {
|
||||
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
|
||||
#endif
|
||||
#if !FF_FS_TINY
|
||||
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
|
||||
#endif
|
||||
#if FF_USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
|
||||
#endif
|
||||
@ -280,7 +279,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe
|
||||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
||||
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
|
||||
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */
|
||||
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
||||
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
|
||||
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
|
||||
|
@ -34,7 +34,6 @@
|
||||
#define MERGE2(a, b) a ## b
|
||||
#define CVTBL(tbl, cp) MERGE2(tbl, cp)
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Code Conversion Tables */
|
||||
/*------------------------------------------------------------------------*/
|
||||
@ -623,5 +622,4 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */
|
||||
return uni;
|
||||
}
|
||||
|
||||
|
||||
#endif /* #if FF_USE_LFN */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "mem/heap.h"
|
||||
#include "power/max77620.h"
|
||||
#include "rtc/max77620-rtc.h"
|
||||
#include "soc/bpmp.h"
|
||||
#include "soc/hw_init.h"
|
||||
#include "storage/sdmmc.h"
|
||||
#include "utils/util.h"
|
||||
@ -107,7 +108,7 @@ int sd_save_to_file(void *buf, u32 size, const char *filename)
|
||||
if (res)
|
||||
{
|
||||
EPRINTFARGS("Error (%d) creating file\n%s.\n", res, filename);
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
f_write(&fp, buf, size, NULL);
|
||||
@ -159,6 +160,8 @@ void ipl_main()
|
||||
gfx_con_init();
|
||||
display_backlight_pwm_init();
|
||||
|
||||
bpmp_clk_rate_set(BPMP_CLK_SUPER_BOOST);
|
||||
|
||||
sd_mount();
|
||||
dump_keys();
|
||||
}
|
||||
|
@ -107,17 +107,12 @@ void heap_init(u32 base)
|
||||
|
||||
void *malloc(u32 size)
|
||||
{
|
||||
return (void *)_heap_alloc(&_heap, size, 0x10);
|
||||
}
|
||||
|
||||
void *memalign(u32 align, u32 size)
|
||||
{
|
||||
return (void *)_heap_alloc(&_heap, size, align);
|
||||
return (void *)_heap_alloc(&_heap, size, sizeof(hnode_t));
|
||||
}
|
||||
|
||||
void *calloc(u32 num, u32 size)
|
||||
{
|
||||
void *res = (void *)_heap_alloc(&_heap, num * size, 0x10);
|
||||
void *res = (void *)_heap_alloc(&_heap, num * size, sizeof(hnode_t));
|
||||
memset(res, 0, num * size);
|
||||
return res;
|
||||
}
|
||||
|
@ -23,6 +23,5 @@ void heap_init(u32 base);
|
||||
void *malloc(u32 size);
|
||||
void *calloc(u32 num, u32 size);
|
||||
void free(void *buf);
|
||||
void *memalign(u32 align, u32 size);
|
||||
|
||||
#endif
|
||||
|
@ -127,7 +127,7 @@ void mc_disable_ahb_redirect()
|
||||
void mc_enable()
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
|
||||
// Enable MIPI CAL clock.
|
||||
// Enable EMC clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF) | 0x2000000;
|
||||
// Enable MC clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE) | 1;
|
||||
|
@ -39,7 +39,13 @@
|
||||
|
||||
static u32 _get_sdram_id()
|
||||
{
|
||||
return (fuse_read_odm(4) & 0x38) >> 3;
|
||||
u32 sdram_id = (fuse_read_odm(4) & 0x38) >> 3;
|
||||
|
||||
// Check if id is proper.
|
||||
if (sdram_id > 7)
|
||||
sdram_id = 0;
|
||||
|
||||
return sdram_id;
|
||||
}
|
||||
|
||||
static void _sdram_config(const sdram_params_t *params)
|
||||
@ -539,7 +545,7 @@ void sdram_init()
|
||||
const sdram_params_t *params = (const sdram_params_t *)sdram_get_params();
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05);
|
||||
max77620_regulator_set_voltage(REGULATOR_SD1, 1100000);
|
||||
max77620_regulator_set_voltage(REGULATOR_SD1, 1100000); // Set DRAM voltage.
|
||||
|
||||
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
|
||||
usleep(params->pmc_vddp_sel_wait);
|
||||
|
@ -130,7 +130,7 @@
|
||||
#define MAX77620_POWER_MODE_DISABLE 0
|
||||
#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2)
|
||||
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_DISABLE 0
|
||||
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_FAST (1 << 0)
|
||||
@ -153,6 +153,24 @@
|
||||
#define MAX77620_REG_PUE_GPIO 0x3E
|
||||
#define MAX77620_REG_PDE_GPIO 0x3F
|
||||
#define MAX77620_REG_AME_GPIO 0x40
|
||||
#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN (0 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1)
|
||||
#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1)
|
||||
#define MAX77620_CNFG_GPIO_DIR_OUTPUT (0 << 1)
|
||||
#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW (0 << 3)
|
||||
#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4)
|
||||
#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4)
|
||||
#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
|
||||
|
||||
#define MAX77620_REG_ONOFFCNFG1 0x41
|
||||
#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7)
|
||||
@ -259,25 +277,6 @@
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0)
|
||||
|
||||
#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0
|
||||
#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1)
|
||||
#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1)
|
||||
#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0
|
||||
#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0
|
||||
#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4)
|
||||
#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4)
|
||||
#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
|
||||
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2)
|
||||
|
@ -24,16 +24,16 @@
|
||||
* Switch Power domains (max77620):
|
||||
* Name | Usage | uV step | uV min | uV default | uV max | Init
|
||||
*-------+---------------+---------+--------+------------+---------+------------------
|
||||
* sd0 | core | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
|
||||
* sd0 | SoC | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
|
||||
* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1)
|
||||
* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv)
|
||||
* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 |
|
||||
* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1)
|
||||
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
|
||||
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
|
||||
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
|
||||
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 |
|
||||
* ldo5 | GC ASIC | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
|
||||
* ldo5 | GC ASIC | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
|
||||
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V
|
||||
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 |
|
||||
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 |
|
||||
@ -71,6 +71,8 @@
|
||||
/* MAX77621_VOUT */
|
||||
#define MAX77621_VOUT_ENABLE (1 << 7)
|
||||
#define MAX77621_VOUT_MASK 0x7F
|
||||
#define MAX77621_VOUT_0_95V 0x37
|
||||
#define MAX77621_VOUT_1_09V 0x4F
|
||||
|
||||
/* MAX77621_VOUT_DVC_DVS */
|
||||
#define MAX77621_DVS_VOUT_MASK 0x7F
|
||||
|
@ -52,7 +52,7 @@ void max77620_rtc_get_time(rtc_time_t *time)
|
||||
}
|
||||
|
||||
// Get date.
|
||||
time->date = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f;
|
||||
time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f;
|
||||
time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1;
|
||||
time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ typedef struct _rtc_time_t {
|
||||
u8 sec;
|
||||
u8 min;
|
||||
u8 hour;
|
||||
u8 date;
|
||||
u8 day;
|
||||
u8 month;
|
||||
u16 year;
|
||||
} rtc_time_t;
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "../sec/se.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../soc/bpmp.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../sec/se_t210.h"
|
||||
#include "../utils/util.h"
|
||||
@ -108,10 +109,14 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
|
||||
|
||||
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0);
|
||||
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
|
||||
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
|
||||
|
||||
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
|
||||
int res = _se_wait();
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
|
||||
|
||||
if (src)
|
||||
free(ll_src);
|
||||
if (dst)
|
||||
@ -227,18 +232,7 @@ int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src,
|
||||
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
}
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
return _se_execute(OP_START, dst, 0x10, src, 0x10);
|
||||
return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "../sec/tsec.h"
|
||||
#include "../sec/tsec_t210.h"
|
||||
#include "../sec/se_t210.h"
|
||||
#include "../soc/bpmp.h"
|
||||
#include "../soc/clock.h"
|
||||
#include "../soc/smmu.h"
|
||||
#include "../soc/t210.h"
|
||||
@ -64,8 +65,12 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
u32 *pdir, *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
|
||||
u32 *pkg11_magic_off;
|
||||
|
||||
//Enable clocks.
|
||||
bpmp_mmu_disable();
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
// Enable clocks.
|
||||
clock_enable_host1x();
|
||||
usleep(2);
|
||||
clock_enable_tsec();
|
||||
clock_enable_sor_safe();
|
||||
clock_enable_sor0();
|
||||
@ -170,7 +175,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
}
|
||||
|
||||
//Execute firmware.
|
||||
HOST1X(0x3300) = 0x34C2E1DA;
|
||||
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
|
||||
TSEC(TSEC_STATUS) = 0;
|
||||
TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1.
|
||||
TSEC(TSEC_BOOTVEC) = 0;
|
||||
@ -247,7 +252,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
}
|
||||
|
||||
//Fetch result.
|
||||
HOST1X(0x3300) = 0;
|
||||
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
|
||||
u32 buf[4];
|
||||
buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB);
|
||||
buf[1] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB);
|
||||
@ -272,7 +277,8 @@ out:;
|
||||
clock_disable_sor0();
|
||||
clock_disable_sor_safe();
|
||||
clock_disable_tsec();
|
||||
clock_disable_host1x();
|
||||
bpmp_mmu_enable();
|
||||
bpmp_clk_rate_set(BPMP_CLK_SUPER_BOOST);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
249
source/soc/bpmp.c
Normal file
249
source/soc/bpmp.c
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
*
|
||||
* 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 "bpmp.h"
|
||||
#include "clock.h"
|
||||
#include "t210.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#define BPMP_CACHE_CONFIG 0x0
|
||||
#define CFG_ENABLE (1 << 0)
|
||||
#define CFG_FORCE_WRITE_THROUGH (1 << 3)
|
||||
#define CFG_DISABLE_WRITE_BUFFER (1 << 10)
|
||||
#define CFG_DISABLE_READ_BUFFER (1 << 11)
|
||||
#define CFG_FULL_LINE_DIRTY (1 << 13)
|
||||
#define CFG_TAG_CHK_ABRT_ON_ERR (1 << 14)
|
||||
#define BPMP_CACHE_LOCK 0x4
|
||||
#define BPMP_CACHE_SIZE 0xC
|
||||
#define BPMP_CACHE_LFSR 0x10
|
||||
#define BPMP_CACHE_TAG_STATUS 0x14
|
||||
#define BPMP_CACHE_CLKEN_OVERRIDE 0x18
|
||||
#define BPMP_CACHE_MAINT_ADDR 0x20
|
||||
#define BPMP_CACHE_MAINT_DATA 0x24
|
||||
#define BPMP_CACHE_MAINT_REQ 0x28
|
||||
#define MAINT_REQ_WAY_BITMAP(x) ((x) << 8)
|
||||
|
||||
#define BPMP_CACHE_INT_MASK 0x40
|
||||
#define BPMP_CACHE_INT_CLEAR 0x44
|
||||
#define INT_CLR_MAINT_DONE (1 << 0)
|
||||
|
||||
#define BPMP_CACHE_INT_RAW_EVENT 0x48
|
||||
#define INT_RAW_EVENT_MAINT_DONE (1 << 0)
|
||||
#define BPMP_CACHE_INT_STATUS 0x4C
|
||||
|
||||
#define BPMP_CACHE_RB_CFG 0x80
|
||||
#define BPMP_CACHE_WB_CFG 0x84
|
||||
|
||||
#define BPMP_CACHE_MMU_FALLBACK_ENTRY 0xA0
|
||||
#define BPMP_CACHE_MMU_SHADOW_COPY_MASK 0xA4
|
||||
#define BPMP_CACHE_MMU_CFG 0xAC
|
||||
#define MMU_CFG_SEQ_EN (1 << 1)
|
||||
#define MMU_CFG_TLB_EN (1 << 2)
|
||||
#define MMU_CFG_ABORT_STORE_LAST (1 << 4)
|
||||
#define BPMP_CACHE_MMU_CMD 0xB0
|
||||
#define MMU_CMD_NOP 0
|
||||
#define MMU_CMD_INIT 1
|
||||
#define MMU_CMD_COPY_SHADOW 2
|
||||
#define BPMP_CACHE_MMU_ABORT_STAT 0xB4
|
||||
#define BPMP_CACHE_MMU_ABORT_ADDR 0xB8
|
||||
#define BPMP_CACHE_MMU_ACTIVE_ENTRIES 0xBC
|
||||
|
||||
#define BPMP_MMU_SHADOW_ENTRY_BASE (BPMP_CACHE_BASE + 0x400)
|
||||
#define BPMP_MMU_MAIN_ENTRY_BASE (BPMP_CACHE_BASE + 0x800)
|
||||
#define MMU_ENTRY_ADDR_MASK 0xFFFFFFE0
|
||||
|
||||
#define MMU_EN_CACHED (1 << 0)
|
||||
#define MMU_EN_EXEC (1 << 1)
|
||||
#define MMU_EN_READ (1 << 2)
|
||||
#define MMU_EN_WRITE (1 << 3)
|
||||
|
||||
bpmp_mmu_entry_t mmu_entries[] =
|
||||
{
|
||||
{ 0x80000000, 0xFFFFFFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true },
|
||||
{ IPL_LOAD_ADDR, 0x40040000, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true }
|
||||
};
|
||||
|
||||
void bpmp_mmu_maintenance(u32 op)
|
||||
{
|
||||
if (!(BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE))
|
||||
return;
|
||||
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = INT_CLR_MAINT_DONE;
|
||||
|
||||
// This is a blocking operation.
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_MAINT_REQ) = MAINT_REQ_WAY_BITMAP(0xF) | op;
|
||||
|
||||
while(!(BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT) & INT_RAW_EVENT_MAINT_DONE))
|
||||
;
|
||||
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT);
|
||||
}
|
||||
|
||||
void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply)
|
||||
{
|
||||
if (idx > 31)
|
||||
return;
|
||||
|
||||
volatile bpmp_mmu_entry_t *mmu_entry = (bpmp_mmu_entry_t *)(BPMP_MMU_SHADOW_ENTRY_BASE + sizeof(bpmp_mmu_entry_t) * idx);
|
||||
|
||||
if (entry->enable)
|
||||
{
|
||||
mmu_entry->min_addr = entry->min_addr & MMU_ENTRY_ADDR_MASK;
|
||||
mmu_entry->max_addr = entry->max_addr & MMU_ENTRY_ADDR_MASK;
|
||||
mmu_entry->attr = entry->attr;
|
||||
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) |= (1 << idx);
|
||||
|
||||
if (apply)
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW;
|
||||
}
|
||||
}
|
||||
|
||||
void bpmp_mmu_enable()
|
||||
{
|
||||
if (BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE)
|
||||
return;
|
||||
|
||||
// Init BPMP MMU.
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_INIT;
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_FALLBACK_ENTRY) = MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC; // RWX for non-defined regions.
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CFG) = MMU_CFG_SEQ_EN | MMU_CFG_TLB_EN | MMU_CFG_ABORT_STORE_LAST;
|
||||
|
||||
// Init BPMP MMU entries.
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) = 0;
|
||||
for (u32 idx = 0; idx < (sizeof(mmu_entries) / sizeof(bpmp_mmu_entry_t)); idx++)
|
||||
bpmp_mmu_set_entry(idx, &mmu_entries[idx], false);
|
||||
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW;
|
||||
|
||||
// Invalidate cache.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY);
|
||||
|
||||
// Enable cache.
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = CFG_ENABLE | CFG_FORCE_WRITE_THROUGH | CFG_TAG_CHK_ABRT_ON_ERR;
|
||||
|
||||
// HW bug. Invalidate cache again.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY);
|
||||
}
|
||||
|
||||
void bpmp_mmu_disable()
|
||||
{
|
||||
if (!(BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE))
|
||||
return;
|
||||
|
||||
// Clean and invalidate cache.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
|
||||
|
||||
// Disable cache.
|
||||
BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0;
|
||||
|
||||
// HW bug. Invalidate cache again.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY);
|
||||
}
|
||||
|
||||
const u8 pllc4_divn[] = {
|
||||
0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB.
|
||||
85, // BPMP_CLK_LOW_BOOST: 544MHz 33% - 136MHz APB.
|
||||
90, // BPMP_CLK_MID_BOOST: 576MHz 41% - 144MHz APB.
|
||||
94 // BPMP_CLK_SUPER_BOOST: 602MHz 48% - 150MHz APB.
|
||||
//95 // BPMP_CLK_SUPER_BOOST: 608MHz 49% - 152MHz APB.
|
||||
};
|
||||
|
||||
bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL;
|
||||
|
||||
void bpmp_clk_rate_set(bpmp_freq_t fid)
|
||||
{
|
||||
if (fid > (BPMP_CLK_MAX - 1))
|
||||
fid = BPMP_CLK_MAX - 1;
|
||||
|
||||
if (bpmp_clock_set == fid)
|
||||
return;
|
||||
|
||||
if (fid)
|
||||
{
|
||||
if (bpmp_clock_set)
|
||||
{
|
||||
// Restore to PLLP source during PLLC4 configuration.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
|
||||
// Wait a bit for clock source change.
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC4_MISC) = PLLC4_MISC_EN_LCKDET;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = 4 | (pllc4_divn[fid] << 8) | PLL_BASE_ENABLE; // DIVM: 4, DIVP: 1.
|
||||
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) & PLLC4_BASE_LOCK))
|
||||
;
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC4_OUT) = (1 << 8) | PLLC4_OUT3_CLKEN; // 1.5 div.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC4_OUT) |= PLLC4_OUT3_RSTN_CLR; // Get divider out of reset.
|
||||
|
||||
// Wait a bit for PLLC4 to stabilize.
|
||||
msleep(10);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / 4.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003323; // PLLC4_OUT3.
|
||||
|
||||
bpmp_clock_set = fid;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
|
||||
|
||||
// Wait a bit for clock source change.
|
||||
msleep(10);
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / 3.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLL_BASE_ENABLE;
|
||||
bpmp_clock_set = BPMP_CLK_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
// The following functions halt BPMP to reduce power while sleeping.
|
||||
// They are not as accurate as RTC at big values but they guarantee time+ delay.
|
||||
void bpmp_usleep(u32 us)
|
||||
{
|
||||
u32 delay;
|
||||
|
||||
// Each iteration takes 1us.
|
||||
while (us)
|
||||
{
|
||||
delay = (us > HALT_COP_MAX_CNT) ? HALT_COP_MAX_CNT : us;
|
||||
us -= delay;
|
||||
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_USEC | delay;
|
||||
}
|
||||
}
|
||||
|
||||
void bpmp_msleep(u32 ms)
|
||||
{
|
||||
u32 delay;
|
||||
|
||||
// Iteration time is variable. ~200 - 1000us.
|
||||
while (ms)
|
||||
{
|
||||
delay = (ms > HALT_COP_MAX_CNT) ? HALT_COP_MAX_CNT : ms;
|
||||
ms -= delay;
|
||||
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_MSEC | delay;
|
||||
}
|
||||
}
|
||||
|
||||
void bpmp_halt()
|
||||
{
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_JTAG;
|
||||
}
|
54
source/soc/bpmp.h
Normal file
54
source/soc/bpmp.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _BPMP_H_
|
||||
#define _BPMP_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
#define BPMP_MMU_MAINT_CLEAN_WAY 17
|
||||
#define BPMP_MMU_MAINT_INVALID_WAY 18
|
||||
#define BPMP_MMU_MAINT_CLN_INV_WAY 19
|
||||
|
||||
typedef struct _bpmp_mmu_entry_t
|
||||
{
|
||||
u32 min_addr;
|
||||
u32 max_addr;
|
||||
u32 attr;
|
||||
u32 enable;
|
||||
} bpmp_mmu_entry_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BPMP_CLK_NORMAL, // 408MHz 0% - 136MHz APB.
|
||||
BPMP_CLK_LOW_BOOST, // 544MHz 33% - 136MHz APB.
|
||||
BPMP_CLK_MID_BOOST, // 576MHz 41% - 144MHz APB.
|
||||
BPMP_CLK_SUPER_BOOST, // 608MHz 49% - 152MHz APB.
|
||||
BPMP_CLK_MAX
|
||||
} bpmp_freq_t;
|
||||
|
||||
void bpmp_mmu_maintenance(u32 op);
|
||||
void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply);
|
||||
void bpmp_mmu_enable();
|
||||
void bpmp_mmu_disable();
|
||||
void bpmp_clk_rate_set(bpmp_freq_t fid);
|
||||
void bpmp_usleep(u32 us);
|
||||
void bpmp_msleep(u32 ms);
|
||||
void bpmp_halt();
|
||||
|
||||
#endif
|
@ -22,57 +22,58 @@
|
||||
/* clock_t: reset, enable, source, index, clk_src, clk_div */
|
||||
|
||||
static const clock_t _clock_uart[] = {
|
||||
/* UART A */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, 6, 0, 0 },
|
||||
/* UART B */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, 7, 0, 0 },
|
||||
/* UART C */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, 0x17, 0, 0 },
|
||||
/* UART D */ { 0 },
|
||||
/* UART E */ { 0 }
|
||||
/* UART A */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, 6, 0, 2 },
|
||||
/* UART B */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, 7, 0, 2 },
|
||||
/* UART C */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, 23, 0, 2 },
|
||||
/* UART D */ { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, 1, 0, 2 },
|
||||
/* UART E */ { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, 20, 0, 2 }
|
||||
};
|
||||
|
||||
static const clock_t _clock_i2c[] = {
|
||||
/* I2C1 */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, 0xC, 6, 0 },
|
||||
/* I2C1 */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, 12, 6, 0 }, // 0, 19 }, // 100KHz
|
||||
/* I2C2 */ { 0 },
|
||||
/* I2C3 */ { 0 },
|
||||
/* I2C4 */ { 0 },
|
||||
/* I2C5 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, 0xF, 6, 0 },
|
||||
/* I2C5 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, 15, 6, 0 }, // 0, 4 }, // 400KHz
|
||||
/* I2C6 */ { 0 }
|
||||
};
|
||||
|
||||
static clock_t _clock_se = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, 0x1F, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, 31, 0, 0
|
||||
};
|
||||
static clock_t _clock_unk2 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, 0x1E, 0, 0
|
||||
|
||||
static clock_t _clock_tzram = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, 30, 0, 0
|
||||
};
|
||||
|
||||
static clock_t _clock_host1x = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, 0x1C, 4, 3
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, 28, 4, 3
|
||||
};
|
||||
static clock_t _clock_tsec = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, 0x13, 0, 2
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, 19, 0, 2
|
||||
};
|
||||
static clock_t _clock_sor_safe = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, 0x1E, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, 30, 0, 0
|
||||
};
|
||||
static clock_t _clock_sor0 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, 0x16, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, 22, 0, 0
|
||||
};
|
||||
static clock_t _clock_sor1 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, 0x17, 0, 2
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, 23, 0, 2
|
||||
};
|
||||
static clock_t _clock_kfuse = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, 8, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, 8, 0, 0
|
||||
};
|
||||
|
||||
static clock_t _clock_cl_dvfs = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, 0x1B, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, 27, 0, 0
|
||||
};
|
||||
static clock_t _clock_coresight = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, 9, 0, 4
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, 9, 0, 4
|
||||
};
|
||||
|
||||
static clock_t _clock_pwm = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 0x11, 6, 4
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 17, 6, 4 // Freference: 6.2MHz.
|
||||
};
|
||||
|
||||
void clock_enable(const clock_t *clk)
|
||||
@ -123,9 +124,9 @@ void clock_enable_se()
|
||||
clock_enable(&_clock_se);
|
||||
}
|
||||
|
||||
void clock_enable_unk2()
|
||||
void clock_enable_tzram()
|
||||
{
|
||||
clock_enable(&_clock_unk2);
|
||||
clock_enable(&_clock_tzram);
|
||||
}
|
||||
|
||||
void clock_enable_host1x()
|
||||
@ -365,49 +366,49 @@ static void _clock_sdmmc_clear_enable(u32 id)
|
||||
static u32 _clock_sdmmc_table[8] = { 0 };
|
||||
|
||||
#define PLLP_OUT0 0x0
|
||||
|
||||
static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val)
|
||||
{
|
||||
u32 divisor = 0;
|
||||
u32 source = PLLP_OUT0;
|
||||
|
||||
// Get IO clock divisor.
|
||||
switch (val)
|
||||
{
|
||||
case 25000:
|
||||
*pout = 24728;
|
||||
divisor = 31;
|
||||
divisor = 31; // 16.5 div.
|
||||
break;
|
||||
case 26000:
|
||||
*pout = 25500;
|
||||
divisor = 30;
|
||||
divisor = 30; // 16 div.
|
||||
break;
|
||||
case 40800:
|
||||
*pout = 40800;
|
||||
divisor = 18;
|
||||
divisor = 18; // 10 div.
|
||||
break;
|
||||
case 50000:
|
||||
*pout = 48000;
|
||||
divisor = 15;
|
||||
divisor = 15; // 8.5 div.
|
||||
break;
|
||||
case 52000:
|
||||
*pout = 51000;
|
||||
divisor = 14;
|
||||
divisor = 14; // 8 div.
|
||||
break;
|
||||
case 100000:
|
||||
*pout = 90667;
|
||||
divisor = 7;
|
||||
divisor = 7; // 4.5 div.
|
||||
break;
|
||||
case 200000:
|
||||
*pout = 163200;
|
||||
divisor = 3;
|
||||
divisor = 3; // 2.5 div.
|
||||
break;
|
||||
case 208000:
|
||||
*pout = 204000;
|
||||
divisor = 2;
|
||||
divisor = 2; // 2 div.
|
||||
break;
|
||||
default:
|
||||
*pout = 24728;
|
||||
divisor = 31;
|
||||
divisor = 31; // 16.5 div.
|
||||
}
|
||||
|
||||
_clock_sdmmc_table[2 * id] = val;
|
||||
|
@ -41,6 +41,8 @@
|
||||
#define CLK_RST_CONTROLLER_PLLM_MISC2 0x9C
|
||||
#define CLK_RST_CONTROLLER_PLLP_BASE 0xA0
|
||||
#define CLK_RST_CONTROLLER_PLLD_BASE 0xD0
|
||||
#define CLK_RST_CONTROLLER_PLLD_MISC1 0xD8
|
||||
#define CLK_RST_CONTROLLER_PLLD_MISC 0xDC
|
||||
#define CLK_RST_CONTROLLER_PLLX_BASE 0xE0
|
||||
#define CLK_RST_CONTROLLER_PLLX_MISC 0xE4
|
||||
#define CLK_RST_CONTROLLER_PLLE_BASE 0xE8
|
||||
@ -50,6 +52,7 @@
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_PWM 0x110
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 0x124
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 0x128
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 0x138
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_VI 0x148
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 0x150
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 0x154
|
||||
@ -57,11 +60,13 @@
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA 0x178
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB 0x17C
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X 0x180
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C2 0x198
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19C
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC 0x1A0
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 0x1B8
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 0x1BC
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTD 0x1C0
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE 0x1D4
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19C
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_TSEC 0x1F4
|
||||
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X 0x280
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_X_SET 0x284
|
||||
@ -95,9 +100,12 @@
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC 0x3A0
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 0x3C4
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_V_SET 0x440
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_V_CLR 0x444
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_W_SET 0x448
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR 0x44C
|
||||
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET 0x450
|
||||
@ -108,16 +116,30 @@
|
||||
#define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE 0x554
|
||||
#define CLK_RST_CONTROLLER_SPARE_REG0 0x55C
|
||||
#define CLK_RST_CONTROLLER_PLLC4_BASE 0x5A4
|
||||
#define CLK_RST_CONTROLLER_PLLC4_MISC 0x5A8
|
||||
#define CLK_RST_CONTROLLER_PLLC4_OUT 0x5E4
|
||||
#define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP 0x620
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIP_CAL 0x66C
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0
|
||||
#define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710
|
||||
|
||||
#define CLK_NO_SOURCE 0x0
|
||||
|
||||
/*! PLL control and status bits */
|
||||
#define PLL_BASE_ENABLE (1 << 30)
|
||||
|
||||
#define PLLC4_MISC_EN_LCKDET (1 << 30)
|
||||
#define PLLC4_BASE_LOCK (1 << 27)
|
||||
#define PLLC4_BASE_IDDQ (1 << 18)
|
||||
#define PLLC4_OUT3_CLKEN (1 << 1)
|
||||
#define PLLC4_OUT3_RSTN_CLR (1 << 0)
|
||||
|
||||
/*! Generic clock descriptor. */
|
||||
typedef struct _clock_t
|
||||
{
|
||||
@ -139,7 +161,7 @@ void clock_enable_uart(u32 idx);
|
||||
void clock_enable_i2c(u32 idx);
|
||||
void clock_disable_i2c(u32 idx);
|
||||
void clock_enable_se();
|
||||
void clock_enable_unk2();
|
||||
void clock_enable_tzram();
|
||||
void clock_enable_host1x();
|
||||
void clock_disable_host1x();
|
||||
void clock_enable_tsec();
|
||||
|
@ -32,18 +32,21 @@ void _cluster_enable_power()
|
||||
// Enable cores power.
|
||||
// 1-3.x: MAX77621_NFSR_ENABLE.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG,
|
||||
MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE);
|
||||
MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE | MAX77621_RAMP_12mV_PER_US);
|
||||
// 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | 0x37);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVC_REG, MAX77621_VOUT_ENABLE | 0x37);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVC_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
|
||||
}
|
||||
|
||||
int _cluster_pmc_enable_partition(u32 part, u32 toggle, bool enable)
|
||||
int _cluster_pmc_enable_partition(u32 part, int enable)
|
||||
{
|
||||
// Check if the partition has already been turned on.
|
||||
if (enable && PMC(APBDEV_PMC_PWRGATE_STATUS) & part)
|
||||
u32 part_mask = 1 << part;
|
||||
u32 desired_state = enable << part;
|
||||
|
||||
// Check if the partition has the state we want.
|
||||
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
|
||||
return 1;
|
||||
|
||||
u32 i = 5001;
|
||||
@ -55,12 +58,13 @@ int _cluster_pmc_enable_partition(u32 part, u32 toggle, bool enable)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PMC(APBDEV_PMC_PWRGATE_TOGGLE) = toggle | (enable ? 0x100 : 0);
|
||||
// Toggle power gating.
|
||||
PMC(APBDEV_PMC_PWRGATE_TOGGLE) = part | 0x100;
|
||||
|
||||
i = 5001;
|
||||
while (i > 0)
|
||||
{
|
||||
if (PMC(APBDEV_PMC_PWRGATE_STATUS) & part)
|
||||
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
|
||||
break;
|
||||
usleep(1);
|
||||
i--;
|
||||
@ -103,11 +107,11 @@ void cluster_boot_cpu0(u32 entry)
|
||||
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
|
||||
|
||||
// Enable CPU rail.
|
||||
_cluster_pmc_enable_partition(1, 0, true);
|
||||
_cluster_pmc_enable_partition(0, 1);
|
||||
// Enable cluster 0 non-CPU.
|
||||
_cluster_pmc_enable_partition(0x8000, 15, true);
|
||||
_cluster_pmc_enable_partition(15, 1);
|
||||
// Enable CE0.
|
||||
_cluster_pmc_enable_partition(0x4000, 14, true);
|
||||
_cluster_pmc_enable_partition(14, 1);
|
||||
|
||||
// Request and wait for RAM repair.
|
||||
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1;
|
||||
@ -117,10 +121,10 @@ void cluster_boot_cpu0(u32 entry)
|
||||
EXCP_VEC(EVP_CPU_RESET_VECTOR) = 0;
|
||||
|
||||
// Set reset vector.
|
||||
SB(SB_AA64_RESET_LOW) = entry | 1;
|
||||
SB(SB_AA64_RESET_LOW) = entry | SB_AA64_RST_AARCH64_MODE_EN;
|
||||
SB(SB_AA64_RESET_HIGH) = 0;
|
||||
// Non-secure reset vector write disable.
|
||||
SB(SB_CSR) = 2;
|
||||
SB(SB_CSR) = SB_CSR_NS_RST_VEC_WR_DIS;
|
||||
(void)SB(SB_CSR);
|
||||
|
||||
// Clear MSELECT reset.
|
||||
|
@ -19,19 +19,6 @@
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
/*! Flow controller registers. */
|
||||
#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0
|
||||
#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14
|
||||
#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C
|
||||
#define FLOW_CTLR_HALT_CPU3_EVENTS 0x24
|
||||
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
|
||||
#define FLOW_CTLR_CPU0_CSR 0x8
|
||||
#define FLOW_CTLR_CPU1_CSR 0x18
|
||||
#define FLOW_CTLR_CPU2_CSR 0x20
|
||||
#define FLOW_CTLR_CPU3_CSR 0x28
|
||||
#define FLOW_CTLR_RAM_REPAIR 0x40
|
||||
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
|
||||
|
||||
void cluster_boot_cpu0(u32 entry);
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "hw_init.h"
|
||||
#include "bpmp.h"
|
||||
#include "clock.h"
|
||||
#include "fuse.h"
|
||||
#include "gpio.h"
|
||||
@ -38,22 +39,36 @@
|
||||
extern sdmmc_t sd_sdmmc;
|
||||
extern boot_cfg_t b_cfg;
|
||||
|
||||
/*
|
||||
* CLK_OSC - 38.4 MHz crystal.
|
||||
* CLK_M - 19.2 MHz (osc/2).
|
||||
* CLK_S - 32.768 KHz (from PMIC).
|
||||
* SCLK - 204MHz init (-> 408MHz -> OC).
|
||||
* HCLK - 204MHz init (-> 408MHz -> OC).
|
||||
* PCLK - 68MHz init (-> 136MHz -> OC/4).
|
||||
*/
|
||||
|
||||
void _config_oscillators()
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4;
|
||||
SYSCTR0(SYSCTR0_CNTFID0) = 19200000;
|
||||
TMR(TIMERUS_USEC_CFG) = 0x45F; // For 19.2MHz clk_m.
|
||||
CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071;
|
||||
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81) | 0xE;
|
||||
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF) | 0x400000;
|
||||
PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | 0x1000;
|
||||
PMC(APBDEV_PMC_SCRATCH188) = (PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF) | 0x2000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF;
|
||||
CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2.
|
||||
SYSCTR0(SYSCTR0_CNTFID0) = 19200000; // Set counter frequency.
|
||||
TMR(TIMERUS_USEC_CFG) = 0x45F; // For 19.2MHz clk_m.
|
||||
CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; // Set OSC to 38.4MHz and drive strength.
|
||||
|
||||
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81) | 0xE; // Set LP0 OSC drive strength.
|
||||
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF) | PMC_OSC_EDPD_OVER_OSC_CTRL_OVER;
|
||||
PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | PMC_CNTRL2_HOLD_CKE_LOW_EN;
|
||||
PMC(APBDEV_PMC_SCRATCH188) = (PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF) | (4 << 23); // LP0 EMC2TMC_CFG_XM2COMP_PU_VREF_SEL_RANGE.
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; // Set HCLK div to 2 and PCLK div to 1.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; // PLLMB disable.
|
||||
|
||||
PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz)
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444;
|
||||
CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2;
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set SCLK div to 1.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set clk source to Run and PLLP_OUT2 (204MHz).
|
||||
CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; // Enable SUPER_SDIV to 1.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
|
||||
}
|
||||
|
||||
void _config_gpios()
|
||||
@ -61,11 +76,22 @@ void _config_gpios()
|
||||
PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0;
|
||||
PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0;
|
||||
|
||||
// Set Joy-Con IsAttached direction.
|
||||
PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE;
|
||||
PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE;
|
||||
|
||||
// Set pin mode for Joy-Con IsAttached and UARTB/C TX pins.
|
||||
#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_B
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
|
||||
#endif
|
||||
#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_C
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
#endif
|
||||
// Set Joy-Con IsAttached mode.
|
||||
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO);
|
||||
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO);
|
||||
|
||||
// Enable input logic for Joy-Con IsAttached and UARTB/C TX pins.
|
||||
gpio_output_enable(GPIO_PORT_G, GPIO_PIN_0, GPIO_OUTPUT_DISABLE);
|
||||
gpio_output_enable(GPIO_PORT_D, GPIO_PIN_1, GPIO_OUTPUT_DISABLE);
|
||||
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_6, GPIO_OUTPUT_DISABLE);
|
||||
@ -80,27 +106,36 @@ void _config_gpios()
|
||||
gpio_config(GPIO_PORT_X, GPIO_PIN_7, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_X, GPIO_PIN_6, GPIO_OUTPUT_DISABLE);
|
||||
gpio_output_enable(GPIO_PORT_X, GPIO_PIN_7, GPIO_OUTPUT_DISABLE);
|
||||
|
||||
// Configure HOME as inputs.
|
||||
// PINMUX_AUX(PINMUX_AUX_BUTTON_HOME) = PINMUX_PULL_UP | PINMUX_INPUT_ENABLE;
|
||||
// gpio_config(GPIO_PORT_Y, GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
}
|
||||
|
||||
void _config_pmc_scratch()
|
||||
{
|
||||
PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF;
|
||||
PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE;
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH21) |= 0x10;
|
||||
PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option.
|
||||
PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; // Unset DATA_DQ_E_IVREF EMC_PMACRO_DATA_PAD_TX_CTRL
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT;
|
||||
}
|
||||
|
||||
void _mbist_workaround()
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
|
||||
|
||||
// Set mux output to SOR1 clock switch.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) | 0x8000) & 0xFFFFBFFF;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) |= 0x40800000u;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = 0x40;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = 0x40000;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000;
|
||||
// Enabled PLLD and set csi to PLLD for test pattern generation.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) |= 0x40800000;
|
||||
|
||||
// Clear per-clock resets.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = 0x40; // Clear reset APE.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = 0x40000; // Clear reset VIC.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X.
|
||||
usleep(2);
|
||||
|
||||
// I2S channels to master and disable SLCG.
|
||||
I2S(I2S1_CTRL) |= I2S_CTRL_MASTER_EN;
|
||||
I2S(I2S1_CG) &= ~I2S_CG_SLCG_ENABLE;
|
||||
I2S(I2S2_CTRL) |= I2S_CTRL_MASTER_EN;
|
||||
@ -111,30 +146,39 @@ void _mbist_workaround()
|
||||
I2S(I2S4_CG) &= ~I2S_CG_SLCG_ENABLE;
|
||||
I2S(I2S5_CTRL) |= I2S_CTRL_MASTER_EN;
|
||||
I2S(I2S5_CG) &= ~I2S_CG_SLCG_ENABLE;
|
||||
DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= 4;
|
||||
|
||||
DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= 4; // DSC_SLCG_OVERRIDE.
|
||||
VIC(0x8C) = 0xFFFFFFFF;
|
||||
usleep(2);
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = 0x40;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = 0x40000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = 0xC0;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80000130;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = 0x1F00200;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = 0x80400808;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = 0x402000FC;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = 0x23000780;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = 0x300;
|
||||
// Set per-clock reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = 0x40; // Set reset APE.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1x.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = 0x40000; // Set reset VIC.
|
||||
|
||||
// Enable specific clocks and disable all others.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = 0xC0; // Enable clock PMC, FUSE.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80000130; // Enable clock RTC, TMR, GPIO, BPMP_CACHE.
|
||||
//CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80400130; // Keep USB data ON.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = 0x1F00200; // Enable clock CSITE, IRAMA, IRAMB, IRAMC, IRAMD, BPMP_CACHE_RAM.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = 0x80400808; // Enable clock MSELECT, APB2APE, SPDIF_DOUBLER, SE.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = 0x402000FC; // Enable clock PCIERX0, PCIERX1, PCIERX2, PCIERX3, PCIERX4, PCIERX5, ENTROPY, MC1.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = 0x23000780; // Enable clock MC_CAPA, MC_CAPB, MC_CPU, MC_BBC, DBGAPB, HPLL_ADSP, PLLG_REF.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = 0x300; // Enable clock MC_CDPA, MC_CCPA.
|
||||
|
||||
// Disable clock gate overrides.
|
||||
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA) = 0;
|
||||
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB) = 0;
|
||||
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC) = 0;
|
||||
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = 0;
|
||||
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE) = 0;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) & 0x1FFFFFFF) | 0x80000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000;
|
||||
|
||||
// Set child clock sources.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF; // Disable PLLD and set reference clock and csi clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF; // Set SOR1 to automatic muxing of safe clock (24MHz) or SOR1 clk switch.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
|
||||
}
|
||||
|
||||
void _config_se_brom()
|
||||
@ -170,13 +214,59 @@ void _config_se_brom()
|
||||
APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10);
|
||||
}
|
||||
|
||||
void _config_regulators()
|
||||
{
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1,
|
||||
(1 << 6) | (1 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0,
|
||||
(7 << MAX77620_FPS_TIME_PERIOD_SHIFT));
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1,
|
||||
(7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (1 << MAX77620_FPS_EN_SRC_SHIFT));
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG2,
|
||||
(7 << MAX77620_FPS_TIME_PERIOD_SHIFT));
|
||||
max77620_regulator_config_fps(REGULATOR_LDO4);
|
||||
max77620_regulator_config_fps(REGULATOR_LDO8);
|
||||
max77620_regulator_config_fps(REGULATOR_SD0);
|
||||
max77620_regulator_config_fps(REGULATOR_SD1);
|
||||
max77620_regulator_config_fps(REGULATOR_SD3);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3,
|
||||
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
|
||||
|
||||
// Set vdd_core voltage to 1.125V
|
||||
max77620_regulator_set_voltage(REGULATOR_SD0, 1125000);
|
||||
|
||||
// Fix CPU/GPU after a Linux warmboot.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVC_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVC_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
|
||||
|
||||
// Disable low battery shutdown monitor.
|
||||
max77620_low_battery_monitor_config();
|
||||
}
|
||||
|
||||
void config_hw()
|
||||
{
|
||||
// Bootrom stuff we skipped by going through rcm.
|
||||
_config_se_brom();
|
||||
//FUSE(FUSE_PRIVATEKEYDISABLE) = 0x11;
|
||||
SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F;
|
||||
PMC(APBDEV_PMC_SCRATCH49) = ((PMC(APBDEV_PMC_SCRATCH49) >> 1) << 1) & 0xFFFFFFFD;
|
||||
SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F; // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN.
|
||||
PMC(APBDEV_PMC_SCRATCH49) = PMC(APBDEV_PMC_SCRATCH49) & 0xFFFFFFFC;
|
||||
|
||||
_mbist_workaround();
|
||||
clock_enable_se();
|
||||
@ -197,49 +287,29 @@ void config_hw()
|
||||
clock_enable_i2c(I2C_1);
|
||||
clock_enable_i2c(I2C_5);
|
||||
|
||||
clock_enable_unk2();
|
||||
clock_enable_tzram();
|
||||
|
||||
i2c_init(I2C_1);
|
||||
i2c_init(I2C_5);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1,
|
||||
(1 << 6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0,
|
||||
(7 << MAX77620_FPS_TIME_PERIOD_SHIFT));
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1,
|
||||
(7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (1 << MAX77620_FPS_EN_SRC_SHIFT));
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG2,
|
||||
(7 << MAX77620_FPS_TIME_PERIOD_SHIFT));
|
||||
max77620_regulator_config_fps(REGULATOR_LDO4);
|
||||
max77620_regulator_config_fps(REGULATOR_LDO8);
|
||||
max77620_regulator_config_fps(REGULATOR_SD0);
|
||||
max77620_regulator_config_fps(REGULATOR_SD1);
|
||||
max77620_regulator_config_fps(REGULATOR_SD3);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3,
|
||||
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
|
||||
|
||||
max77620_regulator_set_voltage(REGULATOR_SD0, 1125000);
|
||||
|
||||
// Fix GPU after warmboot for Linux.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
|
||||
|
||||
// Disable low battery shutdown monitor.
|
||||
max77620_low_battery_monitor_config();
|
||||
_config_regulators();
|
||||
|
||||
_config_pmc_scratch(); // Missing from 4.x+
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = (CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888) | 0x3333;
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz).
|
||||
|
||||
sdram_init();
|
||||
|
||||
bpmp_mmu_enable();
|
||||
mc_enable_ahb_redirect();
|
||||
}
|
||||
|
||||
void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
|
||||
{
|
||||
// Flush and disable MMU.
|
||||
bpmp_mmu_disable();
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
|
||||
|
@ -44,10 +44,10 @@ static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
|
||||
memcpy(&tmp, buf, size);
|
||||
|
||||
vu32 *base = (vu32 *)i2c_addrs[idx];
|
||||
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
|
||||
base[I2C_CMD_DATA1] = tmp; //Set value.
|
||||
base[I2C_CNFG] = (2 * size - 2) | 0x2800; //Set size and send mode.
|
||||
_i2c_wait(base); //Kick transaction.
|
||||
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
|
||||
base[I2C_CMD_DATA1] = tmp; //Set value.
|
||||
base[I2C_CNFG] = ((size - 1) << 1) | 0x2800; //Set size and send mode.
|
||||
_i2c_wait(base); //Kick transaction.
|
||||
|
||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
|
||||
while (base[I2C_STATUS] & 0x100)
|
||||
@ -65,9 +65,9 @@ static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
|
||||
return 0;
|
||||
|
||||
vu32 *base = (vu32 *)i2c_addrs[idx];
|
||||
base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode).
|
||||
base[I2C_CNFG] = (size - 1) << 1 | 0x2840; // Set size and recv mode.
|
||||
_i2c_wait(base); // Kick transaction.
|
||||
base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode).
|
||||
base[I2C_CNFG] = ((size - 1) << 1) | 0x2840; // Set size and recv mode.
|
||||
_i2c_wait(base); // Kick transaction.
|
||||
|
||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
|
||||
while (base[I2C_STATUS] & 0x100)
|
||||
|
@ -26,31 +26,50 @@
|
||||
#define APB_MISC_GP_VGPIO_GPIO_MUX_SEL 0xB74
|
||||
|
||||
/*! Pinmux registers. */
|
||||
#define PINMUX_AUX_SDMMC1_CLK 0x00
|
||||
#define PINMUX_AUX_SDMMC1_CMD 0x04
|
||||
#define PINMUX_AUX_SDMMC1_DAT3 0x08
|
||||
#define PINMUX_AUX_SDMMC1_DAT2 0x0C
|
||||
#define PINMUX_AUX_SDMMC1_DAT1 0x10
|
||||
#define PINMUX_AUX_SDMMC1_DAT0 0x14
|
||||
#define PINMUX_AUX_SDMMC3_CLK 0x1C
|
||||
#define PINMUX_AUX_SDMMC3_CMD 0x20
|
||||
#define PINMUX_AUX_SDMMC3_DAT0 0x24
|
||||
#define PINMUX_AUX_SDMMC3_DAT1 0x28
|
||||
#define PINMUX_AUX_SDMMC3_DAT2 0x2C
|
||||
#define PINMUX_AUX_SDMMC3_DAT3 0x30
|
||||
#define PINMUX_AUX_DMIC3_CLK 0xB4
|
||||
#define PINMUX_AUX_UART2_TX 0xF4
|
||||
#define PINMUX_AUX_UART3_TX 0x104
|
||||
#define PINMUX_AUX_WIFI_EN 0x1B4
|
||||
#define PINMUX_AUX_WIFI_RST 0x1B8
|
||||
#define PINMUX_AUX_NFC_EN 0x1D0
|
||||
#define PINMUX_AUX_NFC_INT 0x1D4
|
||||
#define PINMUX_AUX_LCD_BL_PWM 0x1FC
|
||||
#define PINMUX_AUX_LCD_BL_EN 0x200
|
||||
#define PINMUX_AUX_LCD_RST 0x204
|
||||
#define PINMUX_AUX_GPIO_PE6 0x248
|
||||
#define PINMUX_AUX_GPIO_PH6 0x250
|
||||
#define PINMUX_AUX_GPIO_PZ1 0x280
|
||||
#define PINMUX_AUX_SDMMC1_CLK 0x00
|
||||
#define PINMUX_AUX_SDMMC1_CMD 0x04
|
||||
#define PINMUX_AUX_SDMMC1_DAT3 0x08
|
||||
#define PINMUX_AUX_SDMMC1_DAT2 0x0C
|
||||
#define PINMUX_AUX_SDMMC1_DAT1 0x10
|
||||
#define PINMUX_AUX_SDMMC1_DAT0 0x14
|
||||
#define PINMUX_AUX_SDMMC3_CLK 0x1C
|
||||
#define PINMUX_AUX_SDMMC3_CMD 0x20
|
||||
#define PINMUX_AUX_SDMMC3_DAT0 0x24
|
||||
#define PINMUX_AUX_SDMMC3_DAT1 0x28
|
||||
#define PINMUX_AUX_SDMMC3_DAT2 0x2C
|
||||
#define PINMUX_AUX_SDMMC3_DAT3 0x30
|
||||
#define PINMUX_AUX_SATA_LED_ACTIVE 0x4C
|
||||
#define PINMUX_AUX_DMIC3_CLK 0xB4
|
||||
#define PINMUX_AUX_DMIC3_DAT 0xB8
|
||||
#define PINMUX_AUX_CAM_I2C_SCL 0xD4
|
||||
#define PINMUX_AUX_CAM_I2C_SDA 0xD8
|
||||
#define PINMUX_AUX_UART2_TX 0xF4
|
||||
#define PINMUX_AUX_UART3_TX 0x104
|
||||
#define PINMUX_AUX_DAP4_DIN 0x148
|
||||
#define PINMUX_AUX_DAP4_SCLK 0x150
|
||||
#define PINMUX_AUX_GPIO_X1_AUD 0x18C
|
||||
#define PINMUX_AUX_GPIO_X3_AUD 0x190
|
||||
#define PINMUX_AUX_SPDIF_IN 0x1A4
|
||||
#define PINMUX_AUX_USB_VBUS_EN0 0x1A8
|
||||
#define PINMUX_AUX_USB_VBUS_EN1 0x1AC
|
||||
#define PINMUX_AUX_WIFI_EN 0x1B4
|
||||
#define PINMUX_AUX_WIFI_RST 0x1B8
|
||||
#define PINMUX_AUX_AP_WAKE_NFC 0x1CC
|
||||
#define PINMUX_AUX_NFC_EN 0x1D0
|
||||
#define PINMUX_AUX_NFC_INT 0x1D4
|
||||
#define PINMUX_AUX_CAM1_PWDN 0x1EC
|
||||
#define PINMUX_AUX_CAM2_PWDN 0x1F0
|
||||
#define PINMUX_AUX_LCD_BL_PWM 0x1FC
|
||||
#define PINMUX_AUX_LCD_BL_EN 0x200
|
||||
#define PINMUX_AUX_LCD_RST 0x204
|
||||
#define PINMUX_AUX_LCD_GPIO2 0x20C
|
||||
#define PINMUX_AUX_TOUCH_INT 0x220
|
||||
#define PINMUX_AUX_MOTION_INT 0x224
|
||||
#define PINMUX_AUX_BUTTON_HOME 0x240
|
||||
#define PINMUX_AUX_GPIO_PE6 0x248
|
||||
#define PINMUX_AUX_GPIO_PH6 0x250
|
||||
#define PINMUX_AUX_GPIO_PK3 0x260
|
||||
#define PINMUX_AUX_GPIO_PZ1 0x280
|
||||
/*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */
|
||||
#define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x))
|
||||
#define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x))
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define APBDEV_PMC_PWRGATE_TOGGLE 0x30
|
||||
#define APBDEV_PMC_PWRGATE_STATUS 0x38
|
||||
#define APBDEV_PMC_NO_IOPOWER 0x44
|
||||
#define PMC_NO_IOPOWER_SDMMC1_IO_EN (1 << 12)
|
||||
#define APBDEV_PMC_SCRATCH0 0x50
|
||||
#define APBDEV_PMC_SCRATCH1 0x54
|
||||
#define APBDEV_PMC_SCRATCH20 0xA0
|
||||
@ -37,6 +38,7 @@
|
||||
#define APBDEV_PMC_SCRATCH33 0x120
|
||||
#define APBDEV_PMC_SCRATCH40 0x13C
|
||||
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
|
||||
#define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER 0x400000
|
||||
#define APBDEV_PMC_RST_STATUS 0x1B4
|
||||
#define APBDEV_PMC_IO_DPD_REQ 0x1B8
|
||||
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
|
||||
@ -51,9 +53,11 @@
|
||||
#define APBDEV_PMC_REG_SHORT 0x2CC
|
||||
#define APBDEV_PMC_SEC_DISABLE3 0x2D8
|
||||
#define APBDEV_PMC_SECURE_SCRATCH21 0x334
|
||||
#define PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT 0x10
|
||||
#define APBDEV_PMC_SECURE_SCRATCH32 0x360
|
||||
#define APBDEV_PMC_SECURE_SCRATCH49 0x3A4
|
||||
#define APBDEV_PMC_CNTRL2 0x440
|
||||
#define PMC_CNTRL2_HOLD_CKE_LOW_EN 0x1000
|
||||
#define APBDEV_PMC_IO_DPD3_REQ 0x45C
|
||||
#define APBDEV_PMC_IO_DPD4_REQ 0x464
|
||||
#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "../utils/types.h"
|
||||
|
||||
#define BOOTROM_BASE 0x100000
|
||||
#define IRAM_BASE 0x40000000
|
||||
#define HOST1X_BASE 0x50000000
|
||||
#define BPMP_CACHE_BASE 0x50040000
|
||||
#define DISPLAY_A_BASE 0x54200000
|
||||
@ -100,15 +101,22 @@
|
||||
#define CL_DVFS(off) _REG(CL_DVFS_BASE, off)
|
||||
#define TEST_REG(off) _REG(0x0, off)
|
||||
|
||||
/* HOST1X registers. */
|
||||
#define HOST1X_CH0_SYNC_BASE 0x2100
|
||||
#define HOST1X_CH0_SYNC_SYNCPT_9 (HOST1X_CH0_SYNC_BASE + 0xFA4)
|
||||
#define HOST1X_CH0_SYNC_SYNCPT_160 (HOST1X_CH0_SYNC_BASE + 0x1200)
|
||||
|
||||
/*! EVP registers. */
|
||||
#define EVP_CPU_RESET_VECTOR 0x100
|
||||
|
||||
/*! Misc registers. */
|
||||
#define APB_MISC_PP_STRAPPING_OPT_A 0x08
|
||||
#define APB_MISC_PP_PINMUX_GLOBAL 0x40
|
||||
#define APB_MISC_GP_HIDREV 0x804
|
||||
#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34
|
||||
#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98
|
||||
#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4
|
||||
#define APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL 0xABC
|
||||
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64
|
||||
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68
|
||||
|
||||
@ -118,7 +126,10 @@
|
||||
|
||||
/*! Secure boot registers. */
|
||||
#define SB_CSR 0x0
|
||||
#define SB_CSR_NS_RST_VEC_WR_DIS (1 << 1)
|
||||
#define SB_CSR_PIROM_DISABLE (1 << 4)
|
||||
#define SB_AA64_RESET_LOW 0x30
|
||||
#define SB_AA64_RST_AARCH64_MODE_EN (1 << 0)
|
||||
#define SB_AA64_RESET_HIGH 0x34
|
||||
|
||||
/*! SOR registers. */
|
||||
@ -182,10 +193,31 @@
|
||||
/*! PWM registers. */
|
||||
#define PWM_CONTROLLER_PWM_CSR_0 0x00
|
||||
#define PWM_CONTROLLER_PWM_CSR_1 0x10
|
||||
#define PWM_CSR_EN (1 << 31)
|
||||
|
||||
/*! Special registers. */
|
||||
#define EMC_SCRATCH0 0x324
|
||||
#define EMC_HEKA_UPD (1 << 30)
|
||||
#define EMC_SEPT_RUN (1 << 31)
|
||||
|
||||
/*! Flow controller registers. */
|
||||
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
|
||||
#define HALT_COP_SEC (1 << 23)
|
||||
#define HALT_COP_MSEC (1 << 24)
|
||||
#define HALT_COP_USEC (1 << 25)
|
||||
#define HALT_COP_JTAG (1 << 28)
|
||||
#define HALT_COP_WAIT_EVENT (1 << 30)
|
||||
#define HALT_COP_WAIT_IRQ (1 << 31)
|
||||
#define HALT_COP_MAX_CNT 0xFF
|
||||
#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0
|
||||
#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14
|
||||
#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C
|
||||
#define FLOW_CTLR_HALT_CPU3_EVENTS 0x24
|
||||
#define FLOW_CTLR_CPU0_CSR 0x8
|
||||
#define FLOW_CTLR_CPU1_CSR 0x18
|
||||
#define FLOW_CTLR_CPU2_CSR 0x20
|
||||
#define FLOW_CTLR_CPU3_CSR 0x28
|
||||
#define FLOW_CTLR_RAM_REPAIR 0x40
|
||||
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (C) 2018 CTCaer
|
||||
* Copyright (C) 2018-2019 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@ -26,8 +26,6 @@
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
extern boot_cfg_t b_cfg;
|
||||
|
||||
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||
{
|
||||
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
|
||||
@ -71,6 +69,7 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
|
||||
if (_sdmmc_storage_check_result(*resp))
|
||||
if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -84,6 +83,7 @@ static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
|
||||
|
||||
return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0);
|
||||
}
|
||||
|
||||
@ -93,7 +93,9 @@ static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
|
||||
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -108,7 +110,9 @@ static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -146,8 +150,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
||||
u32 tmp = 0;
|
||||
sdmmc_stop_transmission(storage->sdmmc, &tmp);
|
||||
_sdmmc_storage_get_status(storage, &tmp, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -155,7 +161,9 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
|
||||
{
|
||||
if (!_sdmmc_storage_go_idle_state(storage))
|
||||
return 0;
|
||||
|
||||
sdmmc_end(storage->sdmmc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -177,14 +185,16 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
|
||||
|
||||
msleep(100);
|
||||
} while (retries);
|
||||
|
||||
return 0;
|
||||
|
||||
out:;
|
||||
DPRINTF("readwrite: %08X\n", blkcnt);
|
||||
DPRINTF("readwrite: %08X\n", blkcnt);
|
||||
sector += blkcnt;
|
||||
num_sectors -= blkcnt;
|
||||
bbuf += 512 * blkcnt;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -235,14 +245,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
|
||||
u32 cond = 0;
|
||||
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
|
||||
break;
|
||||
|
||||
if (cond & MMC_CARD_BUSY)
|
||||
{
|
||||
if (cond & 0x40000000)
|
||||
storage->has_sector_access = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (get_tmr_ms() > timeout)
|
||||
break;
|
||||
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
@ -372,6 +385,7 @@ static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
|
||||
if (_sdmmc_storage_check_status(storage))
|
||||
{
|
||||
sdmmc_set_bus_width(storage->sdmmc, bus_width);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -382,14 +396,19 @@ static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, int check)
|
||||
{
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS)))
|
||||
return 0;
|
||||
|
||||
if (check && !_sdmmc_storage_check_status(storage))
|
||||
return 0;
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 2))
|
||||
return 0;
|
||||
DPRINTF("[MMC] switched to HS\n");
|
||||
|
||||
DPRINTF("[MMC] switched to HS\n");
|
||||
storage->csd.busspeed = 52;
|
||||
|
||||
if (check || _sdmmc_storage_check_status(storage))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -397,12 +416,16 @@ static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage)
|
||||
{
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200)))
|
||||
return 0;
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 3))
|
||||
return 0;
|
||||
|
||||
if (!sdmmc_config_tuning(storage->sdmmc, 3, MMC_SEND_TUNING_BLOCK_HS200))
|
||||
return 0;
|
||||
DPRINTF("[MMC] switched to HS200\n");
|
||||
|
||||
DPRINTF("[MMC] switched to HS200\n");
|
||||
storage->csd.busspeed = 200;
|
||||
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
}
|
||||
|
||||
@ -410,17 +433,24 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage)
|
||||
{
|
||||
if (!_mmc_storage_enable_HS200(storage))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_venclkctl(storage->sdmmc);
|
||||
|
||||
if (!_mmc_storage_enable_HS(storage, 0))
|
||||
return 0;
|
||||
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8)))
|
||||
return 0;
|
||||
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400)))
|
||||
return 0;
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 4))
|
||||
return 0;
|
||||
DPRINTF("[MMC] switched to HS400\n");
|
||||
|
||||
DPRINTF("[MMC] switched to HS400\n");
|
||||
storage->csd.busspeed = 400;
|
||||
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
}
|
||||
|
||||
@ -432,8 +462,7 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
|
||||
goto out;
|
||||
|
||||
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 &&
|
||||
card_type & EXT_CSD_CARD_TYPE_HS400_1_8V &&
|
||||
type == 4)
|
||||
card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && type == 4)
|
||||
return _mmc_storage_enable_HS400(storage);
|
||||
|
||||
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 ||
|
||||
@ -445,6 +474,7 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
|
||||
out:;
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_52)
|
||||
return _mmc_storage_enable_HS(storage, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -452,6 +482,7 @@ static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
|
||||
{
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2)))
|
||||
return 0;
|
||||
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
}
|
||||
|
||||
@ -463,42 +494,42 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
|
||||
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, 0, 0))
|
||||
return 0;
|
||||
DPRINTF("[MMC] after init\n");
|
||||
DPRINTF("[MMC] after init\n");
|
||||
|
||||
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor);
|
||||
|
||||
if (!_sdmmc_storage_go_idle_state(storage))
|
||||
return 0;
|
||||
DPRINTF("[MMC] went to idle state\n");
|
||||
DPRINTF("[MMC] went to idle state\n");
|
||||
|
||||
if (!_mmc_storage_get_op_cond(storage, SDMMC_POWER_1_8))
|
||||
return 0;
|
||||
DPRINTF("[MMC] got op cond\n");
|
||||
DPRINTF("[MMC] got op cond\n");
|
||||
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
||||
return 0;
|
||||
DPRINTF("[MMC] got cid\n");
|
||||
DPRINTF("[MMC] got cid\n");
|
||||
|
||||
if (!_mmc_storage_set_relative_addr(storage))
|
||||
return 0;
|
||||
DPRINTF("[MMC] set relative addr\n");
|
||||
DPRINTF("[MMC] set relative addr\n");
|
||||
|
||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
||||
return 0;
|
||||
DPRINTF("[MMC] got csd\n");
|
||||
DPRINTF("[MMC] got csd\n");
|
||||
_mmc_storage_parse_csd(storage);
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 1))
|
||||
return 0;
|
||||
DPRINTF("[MMC] after setup clock\n");
|
||||
DPRINTF("[MMC] after setup clock\n");
|
||||
|
||||
if (!_sdmmc_storage_select_card(storage))
|
||||
return 0;
|
||||
DPRINTF("[MMC] card selected\n");
|
||||
DPRINTF("[MMC] card selected\n");
|
||||
|
||||
if (!_sdmmc_storage_set_blocklen(storage, 512))
|
||||
return 0;
|
||||
DPRINTF("[MMC] set blocklen to 512\n");
|
||||
DPRINTF("[MMC] set blocklen to 512\n");
|
||||
|
||||
u32 *csd = (u32 *)storage->raw_csd;
|
||||
//Check system specification version, only version 4.0 and later support below features.
|
||||
@ -510,7 +541,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
|
||||
if (!_mmc_storage_switch_buswidth(storage, bus_width))
|
||||
return 0;
|
||||
DPRINTF("[MMC] switched buswidth\n");
|
||||
DPRINTF("[MMC] switched buswidth\n");
|
||||
|
||||
u8 *ext_csd = (u8 *)malloc(512);
|
||||
if (!_mmc_storage_get_ext_csd(storage, ext_csd))
|
||||
@ -519,7 +550,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
return 0;
|
||||
}
|
||||
free(ext_csd);
|
||||
DPRINTF("[MMC] got ext_csd\n");
|
||||
DPRINTF("[MMC] got ext_csd\n");
|
||||
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
|
||||
//gfx_hexdump(0, ext_csd, 512);
|
||||
|
||||
@ -529,16 +560,16 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2) && 0)
|
||||
{
|
||||
_mmc_storage_enable_bkops(storage);
|
||||
DPRINTF("[MMC] BKOPS enabled\n");
|
||||
DPRINTF("[MMC] BKOPS enabled\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF("[MMC] BKOPS disabled\n");
|
||||
DPRINTF("[MMC] BKOPS disabled\n");
|
||||
}
|
||||
|
||||
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
|
||||
return 0;
|
||||
DPRINTF("[MMC] succesfully switched to highspeed mode\n");
|
||||
DPRINTF("[MMC] succesfully switched to highspeed mode\n");
|
||||
|
||||
sdmmc_sd_clock_ctrl(storage->sdmmc, 1);
|
||||
|
||||
@ -549,8 +580,10 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
|
||||
{
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_PART_CONFIG, partition)))
|
||||
return 0;
|
||||
|
||||
if (!_sdmmc_storage_check_status(storage))
|
||||
return 0;
|
||||
|
||||
storage->partition = partition;
|
||||
return 1;
|
||||
}
|
||||
@ -564,6 +597,7 @@ static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_st
|
||||
u32 tmp;
|
||||
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
|
||||
return 0;
|
||||
|
||||
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out);
|
||||
}
|
||||
|
||||
@ -571,6 +605,7 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
|
||||
{
|
||||
if (!_sdmmc_storage_execute_cmd_type1(storage, MMC_APP_CMD, storage->rca << 16, 0, R1_STATE_TRAN))
|
||||
return 0;
|
||||
|
||||
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
|
||||
}
|
||||
|
||||
@ -602,6 +637,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int
|
||||
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0))
|
||||
return 0;
|
||||
|
||||
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
|
||||
}
|
||||
|
||||
@ -629,7 +665,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
|
||||
return 0;
|
||||
storage->is_low_voltage = 1;
|
||||
|
||||
DPRINTF("-> switched to low voltage\n");
|
||||
DPRINTF("-> switched to low voltage\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -783,17 +819,17 @@ void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u8 *buf)
|
||||
switch (pwr)
|
||||
{
|
||||
case SD_SET_CURRENT_LIMIT_800:
|
||||
DPRINTF("[SD] Power limit raised to 800mA\n");
|
||||
DPRINTF("[SD] Power limit raised to 800mA\n");
|
||||
break;
|
||||
case SD_SET_CURRENT_LIMIT_600:
|
||||
DPRINTF("[SD] Power limit raised to 600mA\n");
|
||||
DPRINTF("[SD] Power limit raised to 600mA\n");
|
||||
break;
|
||||
case SD_SET_CURRENT_LIMIT_400:
|
||||
DPRINTF("[SD] Power limit raised to 800mA\n");
|
||||
DPRINTF("[SD] Power limit raised to 800mA\n");
|
||||
break;
|
||||
default:
|
||||
case SD_SET_CURRENT_LIMIT_200:
|
||||
DPRINTF("[SD] Power limit defaulted to 200mA\n");
|
||||
DPRINTF("[SD] Power limit defaulted to 200mA\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -802,10 +838,12 @@ int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf)
|
||||
{
|
||||
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type))
|
||||
return 0;
|
||||
DPRINTF("[SD] SD supports switch to (U)HS check\n");
|
||||
|
||||
u32 type_out = buf[16] & 0xF;
|
||||
if (type_out != hs_type)
|
||||
return 0;
|
||||
DPRINTF("[SD] SD supports selected (U)HS mode\n");
|
||||
|
||||
if ((((u16)buf[0] << 8) | buf[1]) < 0x320)
|
||||
{
|
||||
@ -834,31 +872,31 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
|
||||
u32 hs_type = 0;
|
||||
switch (type)
|
||||
{
|
||||
case 11:
|
||||
case 11: // SDR104.
|
||||
// Fall through if not supported.
|
||||
if (buf[13] & SD_MODE_UHS_SDR104)
|
||||
{
|
||||
type = 11;
|
||||
hs_type = UHS_SDR104_BUS_SPEED;
|
||||
DPRINTF("[SD] Bus speed set to SDR104\n");
|
||||
DPRINTF("[SD] Bus speed set to SDR104\n");
|
||||
storage->csd.busspeed = 104;
|
||||
break;
|
||||
}
|
||||
case 10:
|
||||
case 10: // SDR50.
|
||||
if (buf[13] & SD_MODE_UHS_SDR50)
|
||||
{
|
||||
type = 10;
|
||||
hs_type = UHS_SDR50_BUS_SPEED;
|
||||
DPRINTF("[SD] Bus speed set to SDR50\n");
|
||||
DPRINTF("[SD] Bus speed set to SDR50\n");
|
||||
storage->csd.busspeed = 50;
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
case 8: // SDR12.
|
||||
if (!(buf[13] & SD_MODE_UHS_SDR12))
|
||||
return 0;
|
||||
type = 8;
|
||||
hs_type = UHS_SDR12_BUS_SPEED;
|
||||
DPRINTF("[SD] Bus speed set to SDR12\n");
|
||||
DPRINTF("[SD] Bus speed set to SDR12\n");
|
||||
storage->csd.busspeed = 12;
|
||||
break;
|
||||
default:
|
||||
@ -868,10 +906,13 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
|
||||
|
||||
if (!_sd_storage_enable_highspeed(storage, hs_type, buf))
|
||||
return 0;
|
||||
DPRINTF("[SD] SD card accepted UHS\n");
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, type))
|
||||
return 0;
|
||||
DPRINTF("[SD] setup clock\n");
|
||||
if (!sdmmc_config_tuning(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK))
|
||||
return 0;
|
||||
DPRINTF("[SD] config tuning\n");
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
}
|
||||
|
||||
@ -885,8 +926,10 @@ int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||
|
||||
if (!_sd_storage_enable_highspeed(storage, 1, buf))
|
||||
return 0;
|
||||
|
||||
if (!_sdmmc_storage_check_status(storage))
|
||||
return 0;
|
||||
|
||||
return sdmmc_setup_clock(storage->sdmmc, 7);
|
||||
}
|
||||
|
||||
@ -949,7 +992,7 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||
|
||||
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
|
||||
{
|
||||
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
||||
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1011,49 +1054,54 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
}
|
||||
}
|
||||
|
||||
void sdmmc_storage_init_wait_sd()
|
||||
{
|
||||
u32 sd_poweroff_time = (u32)get_tmr_ms() - sd_power_cycle_time_start;
|
||||
if (sd_poweroff_time < 100)
|
||||
msleep(100 - sd_poweroff_time);
|
||||
}
|
||||
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type)
|
||||
{
|
||||
int is_version_1 = 0;
|
||||
|
||||
|
||||
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
||||
u32 sd_poweroff_time = (u32)get_tmr_ms() - b_cfg.sd_timeoff;
|
||||
if (id == SDMMC_1 && (sd_poweroff_time < 100))
|
||||
msleep(100 - sd_poweroff_time);
|
||||
sdmmc_storage_init_wait_sd();
|
||||
|
||||
memset(storage, 0, sizeof(sdmmc_storage_t));
|
||||
storage->sdmmc = sdmmc;
|
||||
|
||||
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0))
|
||||
return 0;
|
||||
DPRINTF("[SD] after init\n");
|
||||
DPRINTF("[SD] after init\n");
|
||||
|
||||
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor);
|
||||
|
||||
if (!_sdmmc_storage_go_idle_state(storage))
|
||||
return 0;
|
||||
DPRINTF("[SD] went to idle state\n");
|
||||
DPRINTF("[SD] went to idle state\n");
|
||||
|
||||
is_version_1 = _sd_storage_send_if_cond(storage);
|
||||
if (is_version_1 == 2)
|
||||
return 0;
|
||||
DPRINTF("[SD] after send if cond\n");
|
||||
DPRINTF("[SD] after send if cond\n");
|
||||
|
||||
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_width == SDMMC_BUS_WIDTH_4 && type == 11))
|
||||
return 0;
|
||||
DPRINTF("[SD] got op cond\n");
|
||||
DPRINTF("[SD] got op cond\n");
|
||||
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
||||
return 0;
|
||||
DPRINTF("[SD] got cid\n");
|
||||
DPRINTF("[SD] got cid\n");
|
||||
_sd_storage_parse_cid(storage);
|
||||
|
||||
if (!_sd_storage_get_rca(storage))
|
||||
return 0;
|
||||
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
|
||||
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
|
||||
|
||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
||||
return 0;
|
||||
DPRINTF("[SD] got csd\n");
|
||||
DPRINTF("[SD] got csd\n");
|
||||
|
||||
//Parse CSD.
|
||||
_sd_storage_parse_csd(storage);
|
||||
@ -1066,7 +1114,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
storage->sec_cnt = storage->csd.c_size << 10;
|
||||
break;
|
||||
default:
|
||||
DPRINTF("[SD] Unknown CSD structure %d\n", storage->csd.structure);
|
||||
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1074,21 +1122,21 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
{
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 6))
|
||||
return 0;
|
||||
DPRINTF("[SD] after setup clock\n");
|
||||
DPRINTF("[SD] after setup clock\n");
|
||||
}
|
||||
|
||||
if (!_sdmmc_storage_select_card(storage))
|
||||
return 0;
|
||||
DPRINTF("[SD] card selected\n");
|
||||
DPRINTF("[SD] card selected\n");
|
||||
|
||||
if (!_sdmmc_storage_set_blocklen(storage, 512))
|
||||
return 0;
|
||||
DPRINTF("[SD] set blocklen to 512\n");
|
||||
DPRINTF("[SD] set blocklen to 512\n");
|
||||
|
||||
u32 tmp = 0;
|
||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
|
||||
return 0;
|
||||
DPRINTF("[SD] cleared card detect\n");
|
||||
DPRINTF("[SD] cleared card detect\n");
|
||||
|
||||
u8 *buf = (u8 *)malloc(512);
|
||||
if (!_sd_storage_get_scr(storage, buf))
|
||||
@ -1098,7 +1146,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
}
|
||||
|
||||
//gfx_hexdump(0, storage->raw_scr, 8);
|
||||
DPRINTF("[SD] got scr\n");
|
||||
DPRINTF("[SD] got scr\n");
|
||||
|
||||
// Check if card supports a wider bus and if it's not SD Version 1.X
|
||||
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
|
||||
@ -1109,11 +1157,11 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
return 0;
|
||||
}
|
||||
sdmmc_set_bus_width(storage->sdmmc, SDMMC_BUS_WIDTH_4);
|
||||
DPRINTF("[SD] switched to wide bus width\n");
|
||||
DPRINTF("[SD] switched to wide bus width\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF("[SD] SD does not support wide bus width\n");
|
||||
DPRINTF("[SD] SD does not support wide bus width\n");
|
||||
}
|
||||
|
||||
if (storage->is_low_voltage)
|
||||
@ -1123,7 +1171,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
DPRINTF("[SD] enabled highspeed (low voltage)\n");
|
||||
DPRINTF("[SD] enabled UHS\n");
|
||||
}
|
||||
else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0)
|
||||
{
|
||||
@ -1132,7 +1180,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
DPRINTF("[SD] enabled highspeed (high voltage)\n");
|
||||
DPRINTF("[SD] enabled HS\n");
|
||||
storage->csd.busspeed = 25;
|
||||
}
|
||||
|
||||
@ -1141,7 +1189,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
// Parse additional card info from sd status.
|
||||
if (_sd_storage_get_ssr(storage, buf))
|
||||
{
|
||||
DPRINTF("[SD] got sd status\n");
|
||||
DPRINTF("[SD] got sd status\n");
|
||||
}
|
||||
|
||||
free(buf);
|
||||
@ -1186,13 +1234,13 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
|
||||
|
||||
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, 14, 0))
|
||||
return 0;
|
||||
DPRINTF("[gc] after init\n");
|
||||
DPRINTF("[gc] after init\n");
|
||||
|
||||
usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor);
|
||||
|
||||
if (!sdmmc_config_tuning(storage->sdmmc, 14, MMC_SEND_TUNING_BLOCK_HS200))
|
||||
return 0;
|
||||
DPRINTF("[gc] after tuning\n");
|
||||
DPRINTF("[gc] after tuning\n");
|
||||
|
||||
sdmmc_sd_clock_ctrl(sdmmc, 1);
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "../utils/types.h"
|
||||
#include "sdmmc_driver.h"
|
||||
|
||||
u32 sd_power_cycle_time_start;
|
||||
|
||||
typedef struct _mmc_cid
|
||||
{
|
||||
u32 manfid;
|
||||
@ -47,7 +49,7 @@ typedef struct _mmc_csd
|
||||
u32 read_blkbits;
|
||||
u32 write_blkbits;
|
||||
u32 capacity;
|
||||
u8 write_protect;
|
||||
u8 write_protect;
|
||||
u16 busspeed;
|
||||
} mmc_csd_t;
|
||||
|
||||
@ -107,6 +109,7 @@ int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, vo
|
||||
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
|
||||
void sdmmc_storage_init_wait_sd();
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "sdmmc.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../power/max7762x.h"
|
||||
#include "../soc/bpmp.h"
|
||||
#include "../soc/clock.h"
|
||||
#include "../soc/gpio.h"
|
||||
#include "../soc/pinmux.h"
|
||||
@ -31,8 +32,6 @@
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
extern boot_cfg_t b_cfg;
|
||||
|
||||
/*! SCMMC controller base addresses. */
|
||||
static const u32 _sdmmc_bases[4] = {
|
||||
0x700B0000,
|
||||
@ -123,6 +122,7 @@ static int _sdmmc_config_ven_ceata_clk(sdmmc_t *sdmmc, u32 id)
|
||||
{
|
||||
if (!sdmmc->venclkctl_set)
|
||||
return 0;
|
||||
|
||||
tap_val = sdmmc->venclkctl_tap;
|
||||
}
|
||||
else
|
||||
@ -201,7 +201,7 @@ out:;
|
||||
|
||||
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
|
||||
{
|
||||
//Disable the SD clock if it was enabled, and reenable it later.
|
||||
// Disable the SD clock if it was enabled, and reenable it later.
|
||||
bool should_enable_sd_clock = false;
|
||||
if (sdmmc->regs->clkcon & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)
|
||||
{
|
||||
@ -217,7 +217,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
|
||||
case 1:
|
||||
case 5:
|
||||
case 6:
|
||||
sdmmc->regs->hostctl &= 0xFB; //Should this be 0xFFFB (~4) ?
|
||||
sdmmc->regs->hostctl &= 0xFB; // Should this be 0xFFFB (~4) ?
|
||||
sdmmc->regs->hostctl2 &= SDHCI_CTRL_VDD_330;
|
||||
break;
|
||||
case 2:
|
||||
@ -233,7 +233,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
|
||||
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
case 4:
|
||||
//Non standard
|
||||
// Non standard.
|
||||
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | HS400_BUS_SPEED;
|
||||
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
@ -242,7 +242,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
|
||||
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
case 10:
|
||||
//T210 Errata for SDR50, the host must be set to SDR104.
|
||||
// T210 Errata for SDR50, the host must be set to SDR104.
|
||||
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR104_BUS_SPEED;
|
||||
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
@ -264,7 +264,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
|
||||
divisor = div >> 8;
|
||||
sdmmc->regs->clkcon = (sdmmc->regs->clkcon & 0x3F) | (div << 8) | (divisor << 6);
|
||||
|
||||
//Enable the SD clock again.
|
||||
// Enable the SD clock again.
|
||||
if (should_enable_sd_clock)
|
||||
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
|
||||
|
||||
@ -398,7 +398,7 @@ static int _sdmmc_wait_prnsts_type0(sdmmc_t *sdmmc, u32 wait_dat)
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
|
||||
u32 timeout = get_tmr_ms() + 2000;
|
||||
while(sdmmc->regs->prnsts & 1) //CMD inhibit.
|
||||
while(sdmmc->regs->prnsts & 1) // CMD inhibit.
|
||||
if (get_tmr_ms() > timeout)
|
||||
{
|
||||
_sdmmc_reset(sdmmc);
|
||||
@ -408,7 +408,7 @@ static int _sdmmc_wait_prnsts_type0(sdmmc_t *sdmmc, u32 wait_dat)
|
||||
if (wait_dat)
|
||||
{
|
||||
timeout = get_tmr_ms() + 2000;
|
||||
while (sdmmc->regs->prnsts & 2) //DAT inhibit.
|
||||
while (sdmmc->regs->prnsts & 2) // DAT inhibit.
|
||||
if (get_tmr_ms() > timeout)
|
||||
{
|
||||
_sdmmc_reset(sdmmc);
|
||||
@ -424,7 +424,7 @@ static int _sdmmc_wait_prnsts_type1(sdmmc_t *sdmmc)
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
|
||||
u32 timeout = get_tmr_ms() + 2000;
|
||||
while (!(sdmmc->regs->prnsts & 0x100000)) //DAT0 line level.
|
||||
while (!(sdmmc->regs->prnsts & 0x100000)) // DAT0 line level.
|
||||
if (get_tmr_ms() > timeout)
|
||||
{
|
||||
_sdmmc_reset(sdmmc);
|
||||
@ -511,13 +511,17 @@ static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
|
||||
return 0;
|
||||
|
||||
_sdmmc_setup_read_small_block(sdmmc);
|
||||
|
||||
sdmmc->regs->norintstsen |= TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY;
|
||||
sdmmc->regs->norintsts = sdmmc->regs->norintsts;
|
||||
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
|
||||
|
||||
_sdmmc_parse_cmd_48(sdmmc, cmd);
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
usleep(1);
|
||||
|
||||
_sdmmc_reset(sdmmc);
|
||||
|
||||
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
|
||||
@ -533,10 +537,13 @@ static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
_sdmmc_reset(sdmmc);
|
||||
|
||||
sdmmc->regs->norintstsen &= 0xFFDF;
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -563,8 +570,8 @@ int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag;
|
||||
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | 0x40;
|
||||
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries.
|
||||
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | 0x40; // Multiplier.
|
||||
sdmmc->regs->ventunctl0 |= 0x20000;
|
||||
sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING;
|
||||
|
||||
@ -577,6 +584,7 @@ int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd)
|
||||
|
||||
if (sdmmc->regs->hostctl2 & SDHCI_CTRL_TUNED_CLK)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -666,7 +674,7 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
|
||||
{
|
||||
if (get_tmr_ms() > timeout)
|
||||
{
|
||||
//In case autocalibration fails, we load suggested standard values.
|
||||
// In case autocalibration fails, we load suggested standard values.
|
||||
_sdmmc_pad_config_fallback(sdmmc, power);
|
||||
sdmmc->regs->autocalcfg &= 0xDFFFFFFF;
|
||||
break;
|
||||
@ -703,7 +711,7 @@ static int _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
|
||||
if (pout)
|
||||
*pout = norintsts;
|
||||
|
||||
//Check for error interrupt.
|
||||
// Check for error interrupt.
|
||||
if (norintsts & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT)
|
||||
{
|
||||
sdmmc->regs->errintsts = errintsts;
|
||||
@ -746,11 +754,14 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
|
||||
return 0;
|
||||
|
||||
_sdmmc_enable_interrupts(sdmmc);
|
||||
|
||||
cmd.cmd = MMC_STOP_TRANSMISSION;
|
||||
cmd.arg = 0;
|
||||
cmd.rsp_type = SDMMC_RSP_TYPE_1;
|
||||
cmd.check_busy = 1;
|
||||
|
||||
_sdmmc_parse_cmdbuf(sdmmc, &cmd, false);
|
||||
|
||||
int res = _sdmmc_wait_request(sdmmc);
|
||||
_sdmmc_mask_interrupts(sdmmc);
|
||||
|
||||
@ -758,6 +769,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
|
||||
return 0;
|
||||
|
||||
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1);
|
||||
|
||||
return _sdmmc_wait_prnsts_type1(sdmmc);
|
||||
}
|
||||
|
||||
@ -777,6 +789,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
|
||||
|
||||
int res = _sdmmc_stop_transmission_inner(sdmmc, rsp);
|
||||
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
|
||||
|
||||
if (should_disable_sd_clock)
|
||||
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
|
||||
|
||||
@ -793,7 +806,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
|
||||
blkcnt = 0xFFFF;
|
||||
u32 admaaddr = (u32)req->buf;
|
||||
|
||||
//Check alignment.
|
||||
// Check alignment.
|
||||
if (admaaddr << 29)
|
||||
return 0;
|
||||
|
||||
@ -817,7 +830,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
|
||||
trnmode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ;
|
||||
if (req->is_auto_cmd12)
|
||||
trnmode = (trnmode & 0xFFF3) | TEGRA_MMC_TRNMOD_AUTO_CMD12;
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
|
||||
sdmmc->regs->trnmod = trnmode;
|
||||
|
||||
return 1;
|
||||
@ -836,15 +849,18 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc)
|
||||
while (1)
|
||||
{
|
||||
u16 intr = 0;
|
||||
res = _sdmmc_check_mask_interrupt(sdmmc, &intr,
|
||||
res = _sdmmc_check_mask_interrupt(sdmmc, &intr,
|
||||
TEGRA_MMC_NORINTSTS_XFER_COMPLETE | TEGRA_MMC_NORINTSTS_DMA_INTERRUPT);
|
||||
if (res < 0)
|
||||
break;
|
||||
if (intr & TEGRA_MMC_NORINTSTS_XFER_COMPLETE)
|
||||
return 1; //Transfer complete.
|
||||
{
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
|
||||
return 1; // Transfer complete.
|
||||
}
|
||||
if (intr & TEGRA_MMC_NORINTSTS_DMA_INTERRUPT)
|
||||
{
|
||||
//Update DMA.
|
||||
// Update DMA.
|
||||
sdmmc->regs->admaaddr = sdmmc->dma_addr_next;
|
||||
sdmmc->regs->admaaddr_hi = 0;
|
||||
sdmmc->dma_addr_next += 0x80000;
|
||||
@ -906,6 +922,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
||||
{
|
||||
if (blkcnt_out)
|
||||
*blkcnt_out = blkcnt;
|
||||
|
||||
if (req->is_auto_cmd12)
|
||||
sdmmc->rsp3 = sdmmc->regs->rspreg3;
|
||||
}
|
||||
@ -919,12 +936,14 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
||||
|
||||
static int _sdmmc_config_sdmmc1()
|
||||
{
|
||||
//Configure SD card detect.
|
||||
// Configure SD card detect.
|
||||
PINMUX_AUX(PINMUX_AUX_GPIO_PZ1) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP | 1; //GPIO control, pull up.
|
||||
APB_MISC(APB_MISC_GP_VGPIO_GPIO_MUX_SEL) = 0;
|
||||
gpio_config(GPIO_PORT_Z, GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE);
|
||||
usleep(100);
|
||||
|
||||
// Check if SD card is inserted.
|
||||
if(!!gpio_read(GPIO_PORT_Z, GPIO_PIN_1))
|
||||
return 0;
|
||||
|
||||
@ -937,8 +956,8 @@ static int _sdmmc_config_sdmmc1()
|
||||
* APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK
|
||||
*/
|
||||
|
||||
//Configure SDMMC1 pinmux.
|
||||
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1;
|
||||
// Configure SDMMC1 pinmux.
|
||||
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Enable deep loopback for SDMMC1 CLK pad.
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED;
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
|
||||
@ -946,12 +965,12 @@ static int _sdmmc_config_sdmmc1()
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
|
||||
|
||||
//Make sure the SDMMC1 controller is powered.
|
||||
// Make sure the SDMMC1 controller is powered.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(1 << 12);
|
||||
//Assume 3.3V SD card voltage.
|
||||
// Assume 3.3V SD card voltage.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= (1 << 12);
|
||||
|
||||
//Set enable SD card power.
|
||||
// Set enable SD card power.
|
||||
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN | 1; //GPIO control, pull down.
|
||||
gpio_config(GPIO_PORT_E, GPIO_PIN_4, GPIO_MODE_GPIO);
|
||||
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
|
||||
@ -959,13 +978,13 @@ static int _sdmmc_config_sdmmc1()
|
||||
|
||||
usleep(1000);
|
||||
|
||||
//Enable SD card power.
|
||||
// Enable SD card power.
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000);
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 1);
|
||||
|
||||
usleep(1000);
|
||||
|
||||
//For good measure.
|
||||
// For good measure.
|
||||
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = 0x10000000;
|
||||
|
||||
usleep(1000);
|
||||
@ -1009,18 +1028,23 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int n
|
||||
sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & 0xF) | 7;
|
||||
if (!_sdmmc_autocal_config_offset(sdmmc, power))
|
||||
return 0;
|
||||
|
||||
_sdmmc_autocal_execute(sdmmc, power);
|
||||
|
||||
if (_sdmmc_enable_internal_clock(sdmmc))
|
||||
{
|
||||
sdmmc_set_bus_width(sdmmc, bus_width);
|
||||
_sdmmc_set_voltage(sdmmc, power);
|
||||
|
||||
if (sdmmc_setup_clock(sdmmc, type))
|
||||
{
|
||||
sdmmc_sd_clock_ctrl(sdmmc, no_sd);
|
||||
_sdmmc_sd_clock_enable(sdmmc);
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
@ -1039,8 +1063,8 @@ void sdmmc_end(sdmmc_t *sdmmc)
|
||||
{
|
||||
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 0);
|
||||
b_cfg.sd_timeoff = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle.
|
||||
msleep(1); // To power cycle, min 1ms without power is needed.
|
||||
sd_power_cycle_time_start = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle.
|
||||
usleep(1000); // To power cycle, min 1ms without power is needed.
|
||||
}
|
||||
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
@ -1062,7 +1086,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
|
||||
if (!sdmmc->sd_clock_enabled)
|
||||
return 0;
|
||||
|
||||
//Recalibrate periodically for SDMMC1.
|
||||
// Recalibrate periodically for SDMMC1.
|
||||
if (sdmmc->id == SDMMC_1 && sdmmc->no_sd)
|
||||
_sdmmc_autocal_execute(sdmmc, sdmmc_get_voltage(sdmmc));
|
||||
|
||||
@ -1077,6 +1101,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
|
||||
|
||||
int res = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out);
|
||||
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
|
||||
|
||||
if (should_disable_sd_clock)
|
||||
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
|
||||
|
||||
@ -1093,6 +1118,14 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
|
||||
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
|
||||
// Enable schmitt trigger for better duty cycle and low jitter clock.
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_SCHMT;
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) |= PINMUX_SCHMT;
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) |= PINMUX_SCHMT;
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) |= PINMUX_SCHMT;
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) |= PINMUX_SCHMT;
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) |= PINMUX_SCHMT;
|
||||
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(1 << 12);
|
||||
|
||||
@ -1106,7 +1139,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
|
||||
{
|
||||
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
msleep(1);
|
||||
usleep(1000);
|
||||
if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000)
|
||||
return 1;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ u8 btn_read()
|
||||
res |= BTN_VOL_DOWN;
|
||||
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
|
||||
res |= BTN_VOL_UP;
|
||||
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, 0x15) & 0x4)
|
||||
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & 0x4)
|
||||
res |= BTN_POWER;
|
||||
return res;
|
||||
}
|
||||
|
@ -1,122 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2019 shchmue
|
||||
*
|
||||
* 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 "types.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void _putc(char *buffer, const char c) {
|
||||
*buffer = c;
|
||||
}
|
||||
|
||||
static u32 _puts(char *buffer, const char *s) {
|
||||
u32 count = 0;
|
||||
for (; *s; s++, count++)
|
||||
_putc(buffer + count, *s);
|
||||
return count;
|
||||
}
|
||||
|
||||
static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) {
|
||||
char buf[0x121];
|
||||
static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
char *p;
|
||||
int c = fcnt;
|
||||
|
||||
if (base > 36)
|
||||
return 0;
|
||||
|
||||
p = buf + 0x120;
|
||||
*p = 0;
|
||||
do {
|
||||
c--;
|
||||
*--p = digits[v % base];
|
||||
v /= base;
|
||||
} while (v);
|
||||
|
||||
if (fill != 0) {
|
||||
while (c > 0) {
|
||||
*--p = fill;
|
||||
c--;
|
||||
}
|
||||
}
|
||||
|
||||
return _puts(buffer, p);
|
||||
}
|
||||
|
||||
u32 sprintf(char *buffer, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
int fill, fcnt;
|
||||
u32 count = 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
while(*fmt) {
|
||||
if (*fmt == '%') {
|
||||
fmt++;
|
||||
fill = 0;
|
||||
fcnt = 0;
|
||||
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') {
|
||||
fcnt = *fmt;
|
||||
fmt++;
|
||||
if (*fmt >= '0' && *fmt <= '9') {
|
||||
fill = fcnt;
|
||||
fcnt = *fmt - '0';
|
||||
fmt++;
|
||||
} else {
|
||||
fill = ' ';
|
||||
fcnt -= '0';
|
||||
}
|
||||
}
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
_putc(buffer + count, va_arg(ap, u32));
|
||||
count++;
|
||||
break;
|
||||
case 's':
|
||||
count += _puts(buffer + count, va_arg(ap, char *));
|
||||
break;
|
||||
case 'd':
|
||||
count += _putn(buffer + count, va_arg(ap, u32), 10, fill, fcnt);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
case 'x':
|
||||
case 'X':
|
||||
count += _putn(buffer + count, va_arg(ap, u32), 16, fill, fcnt);
|
||||
break;
|
||||
case '%':
|
||||
_putc(buffer + count, '%');
|
||||
count++;
|
||||
break;
|
||||
case '\0':
|
||||
goto out;
|
||||
default:
|
||||
_putc(buffer + count, '%');
|
||||
_putc(buffer + count, *fmt);
|
||||
count += 2;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
_putc(buffer + count, *fmt);
|
||||
count++;
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
|
||||
out:
|
||||
buffer[count] = 0;
|
||||
va_end(ap);
|
||||
return count;
|
||||
/*
|
||||
* Copyright (c) 2019 shchmue
|
||||
*
|
||||
* 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 "sprintf.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void _putc(char *buffer, const char c) {
|
||||
*buffer = c;
|
||||
}
|
||||
|
||||
static u32 _puts(char *buffer, const char *s) {
|
||||
u32 count = 0;
|
||||
for (; *s; s++, count++)
|
||||
_putc(buffer + count, *s);
|
||||
return count;
|
||||
}
|
||||
|
||||
static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) {
|
||||
char buf[0x121];
|
||||
static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
char *p;
|
||||
int c = fcnt;
|
||||
|
||||
if (base > 36)
|
||||
return 0;
|
||||
|
||||
p = buf + 0x120;
|
||||
*p = 0;
|
||||
do {
|
||||
c--;
|
||||
*--p = digits[v % base];
|
||||
v /= base;
|
||||
} while (v);
|
||||
|
||||
if (fill != 0) {
|
||||
while (c > 0) {
|
||||
*--p = fill;
|
||||
c--;
|
||||
}
|
||||
}
|
||||
|
||||
return _puts(buffer, p);
|
||||
}
|
||||
|
||||
u32 sprintf(char *buffer, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
int fill, fcnt;
|
||||
u32 count = 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
while(*fmt) {
|
||||
if (*fmt == '%') {
|
||||
fmt++;
|
||||
fill = 0;
|
||||
fcnt = 0;
|
||||
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') {
|
||||
fcnt = *fmt;
|
||||
fmt++;
|
||||
if (*fmt >= '0' && *fmt <= '9') {
|
||||
fill = fcnt;
|
||||
fcnt = *fmt - '0';
|
||||
fmt++;
|
||||
} else {
|
||||
fill = ' ';
|
||||
fcnt -= '0';
|
||||
}
|
||||
}
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
_putc(buffer + count, va_arg(ap, u32));
|
||||
count++;
|
||||
break;
|
||||
case 's':
|
||||
count += _puts(buffer + count, va_arg(ap, char *));
|
||||
break;
|
||||
case 'd':
|
||||
count += _putn(buffer + count, va_arg(ap, u32), 10, fill, fcnt);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
case 'x':
|
||||
case 'X':
|
||||
count += _putn(buffer + count, va_arg(ap, u32), 16, fill, fcnt);
|
||||
break;
|
||||
case '%':
|
||||
_putc(buffer + count, '%');
|
||||
count++;
|
||||
break;
|
||||
case '\0':
|
||||
goto out;
|
||||
default:
|
||||
_putc(buffer + count, '%');
|
||||
count++;
|
||||
_putc(buffer + count, *fmt);
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
_putc(buffer + count, *fmt);
|
||||
count++;
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
|
||||
out:
|
||||
buffer[count] = 0;
|
||||
va_end(ap);
|
||||
return count;
|
||||
}
|
@ -1,22 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 shchmue
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SPRINTF_H_
|
||||
#define _SPRINTF_H_
|
||||
|
||||
u32 sprintf(char *buffer, const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Copyright (c) 2019 shchmue
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SPRINTF_H_
|
||||
#define _SPRINTF_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
u32 sprintf(char *buffer, const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
|
@ -78,12 +78,18 @@ typedef int bool;
|
||||
|
||||
typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||
{
|
||||
u8 boot_cfg;
|
||||
u8 autoboot;
|
||||
u8 autoboot_list;
|
||||
u8 extra_cfg;
|
||||
u32 sd_timeoff;
|
||||
u8 rsvd[124];
|
||||
u8 boot_cfg;
|
||||
u8 autoboot;
|
||||
u8 autoboot_list;
|
||||
u8 extra_cfg;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
char id[8];
|
||||
};
|
||||
u8 xt_str[0x80];
|
||||
};
|
||||
} boot_cfg_t;
|
||||
|
||||
typedef struct __attribute__((__packed__)) _reloc_meta_t
|
||||
|
@ -19,10 +19,13 @@
|
||||
#include "../gfx/di.h"
|
||||
#include "../power/max77620.h"
|
||||
#include "../rtc/max77620-rtc.h"
|
||||
#include "../soc/bpmp.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../soc/t210.h"
|
||||
|
||||
#define USE_RTC_TIMER
|
||||
|
||||
extern void sd_unmount();
|
||||
|
||||
u32 get_tmr_s()
|
||||
@ -34,7 +37,7 @@ u32 get_tmr_ms()
|
||||
{
|
||||
// The registers must be read with the following order:
|
||||
// RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0xC)
|
||||
return (RTC(APBDEV_RTC_MILLI_SECONDS) | (RTC(APBDEV_RTC_SHADOW_SECONDS) << 10));
|
||||
return (RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000));
|
||||
}
|
||||
|
||||
u32 get_tmr_us()
|
||||
@ -42,19 +45,32 @@ u32 get_tmr_us()
|
||||
return TMR(TIMERUS_CNTR_1US); //TIMERUS_CNTR_1US
|
||||
}
|
||||
|
||||
void msleep(u32 milliseconds)
|
||||
void msleep(u32 ms)
|
||||
{
|
||||
u32 start = RTC(APBDEV_RTC_MILLI_SECONDS) | (RTC(APBDEV_RTC_SHADOW_SECONDS) << 10);
|
||||
while (((RTC(APBDEV_RTC_MILLI_SECONDS) | (RTC(APBDEV_RTC_SHADOW_SECONDS) << 10)) - start) <= milliseconds)
|
||||
#ifdef USE_RTC_TIMER
|
||||
u32 start = RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000);
|
||||
// Casting to u32 is important!
|
||||
while (((u32)(RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000)) - start) <= ms)
|
||||
;
|
||||
#else
|
||||
bpmp_msleep(ms);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usleep(u32 microseconds)
|
||||
void usleep(u32 us)
|
||||
{
|
||||
#ifdef USE_RTC_TIMER
|
||||
u32 start = TMR(TIMERUS_CNTR_1US);
|
||||
// Casting to u32 is important!
|
||||
while ((u32)(TMR(TIMERUS_CNTR_1US) - start) <= microseconds)
|
||||
;
|
||||
|
||||
// Check if timer is at upper limits and use BPMP sleep so it doesn't wake up immediately.
|
||||
if ((start + us) < start)
|
||||
bpmp_usleep(us);
|
||||
else
|
||||
while ((u32)(TMR(TIMERUS_CNTR_1US) - start) <= us) // Casting to u32 is important!
|
||||
;
|
||||
#else
|
||||
bpmp_usleep(us);
|
||||
#endif
|
||||
}
|
||||
|
||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops)
|
||||
@ -72,12 +88,15 @@ void panic(u32 val)
|
||||
TMR(TIMER_TMR9_TMR_PTV) = TIMER_EN | TIMER_PER_EN;
|
||||
TMR(TIMER_WDT4_CONFIG) = TIMER_SRC(9) | TIMER_PER(1) | TIMER_PMCRESET_EN;
|
||||
TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT;
|
||||
while (1)
|
||||
;
|
||||
|
||||
while (true)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
void reboot_normal()
|
||||
{
|
||||
bpmp_mmu_disable();
|
||||
|
||||
sd_unmount();
|
||||
display_end();
|
||||
|
||||
@ -86,6 +105,8 @@ void reboot_normal()
|
||||
|
||||
void reboot_rcm()
|
||||
{
|
||||
bpmp_mmu_disable();
|
||||
|
||||
sd_unmount();
|
||||
display_end();
|
||||
|
||||
@ -93,16 +114,19 @@ void reboot_rcm()
|
||||
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
|
||||
|
||||
while (true)
|
||||
usleep(1);
|
||||
bpmp_halt();
|
||||
}
|
||||
|
||||
void power_off()
|
||||
{
|
||||
sd_unmount();
|
||||
display_end();
|
||||
|
||||
// Stop the alarm, in case we injected and powered off too fast.
|
||||
max77620_rtc_stop_alarm();
|
||||
|
||||
//TODO: we should probably make sure all regulators are powered off properly.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ typedef struct _cfg_op_t
|
||||
u32 get_tmr_us();
|
||||
u32 get_tmr_ms();
|
||||
u32 get_tmr_s();
|
||||
void usleep(u32 ticks);
|
||||
void msleep(u32 milliseconds);
|
||||
void usleep(u32 us);
|
||||
void msleep(u32 ms);
|
||||
void panic(u32 val);
|
||||
void reboot_normal();
|
||||
void reboot_rcm();
|
||||
|
Loading…
Reference in New Issue
Block a user