From 8709e3aa2e3fe4ee337e0995033375345f5f3364 Mon Sep 17 00:00:00 2001 From: suchmememanyskill Date: Tue, 12 Jan 2021 00:30:14 +0100 Subject: [PATCH] Update bdk to hekate 5.5.2 --- bdk/{gfx => display}/di.c | 47 +++-- bdk/{gfx => display}/di.h | 8 +- bdk/{gfx => display}/di.inl | 0 bdk/input/als.c | 11 +- bdk/input/joycon.c | 118 ++++++++---- bdk/input/touch.c | 73 +++++--- bdk/input/touch.h | 30 ++- bdk/mem/mc.c | 18 +- bdk/mem/minerva.c | 5 +- bdk/mem/sdram.c | 27 +-- bdk/mem/sdram.h | 10 +- bdk/mem/sdram_config.inl | 18 +- bdk/mem/sdram_config_t210b01.inl | 30 +-- bdk/power/max77620.h | 244 ++++++++++++++---------- bdk/power/max7762x.c | 307 +++++++++++++++++++++++-------- bdk/power/max7762x.h | 104 +++++++---- bdk/power/max77812.h | 29 +-- bdk/power/regulator_5v.c | 17 +- bdk/power/regulator_5v.h | 7 +- bdk/soc/ccplex.c | 61 +++--- bdk/soc/clock.c | 86 +++++++-- bdk/soc/clock.h | 164 ++++++++++++++++- bdk/soc/fuse.c | 32 +++- bdk/soc/fuse.h | 12 +- bdk/soc/hw_init.c | 61 +++--- bdk/soc/hw_init.h | 2 +- bdk/soc/i2c.c | 8 +- bdk/soc/irq.c | 14 +- bdk/soc/pmc.c | 60 +++++- bdk/soc/pmc.h | 52 +++++- bdk/storage/mmc.h | 3 + bdk/storage/sd.h | 6 +- bdk/storage/sdmmc.c | 137 +++++++++----- bdk/storage/sdmmc.h | 20 +- bdk/storage/sdmmc_driver.c | 24 +-- bdk/thermal/fan.c | 4 +- bdk/usb/usb_gadget_hid.c | 2 +- bdk/usb/usb_gadget_ums.c | 177 +++++++++--------- bdk/usb/usb_t210.h | 1 + bdk/usb/usbd.c | 26 +-- bdk/usb/usbd.h | 14 +- bdk/usb/xusbd.c | 40 ++-- bdk/utils/types.h | 3 + bdk/utils/util.c | 85 +++++---- bdk/utils/util.h | 39 ++-- source/hid/hid.c | 7 +- source/hos/sept.c | 2 +- source/keys/keys.c | 2 +- source/main.c | 2 +- source/tegraexplorer/mainmenu.c | 1 + source/utils/utils.c | 8 + source/utils/utils.h | 5 +- 52 files changed, 1541 insertions(+), 722 deletions(-) rename bdk/{gfx => display}/di.c (95%) rename bdk/{gfx => display}/di.h (99%) rename bdk/{gfx => display}/di.inl (100%) diff --git a/bdk/gfx/di.c b/bdk/display/di.c similarity index 95% rename from bdk/gfx/di.c rename to bdk/display/di.c index 9d95349..26e905a 100644 --- a/bdk/gfx/di.c +++ b/bdk/display/di.c @@ -20,6 +20,7 @@ #include "di.h" #include #include +#include #include #include #include @@ -170,9 +171,9 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled) void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) { + u8 *fifo8; + u32 *fifo32; u32 host_control; - u32 fifo32[DSI_STATUS_RX_FIFO_SIZE] = {0}; - u8 *fifo8 = (u8 *)fifo32; // Enable host cmd packets during video and save host control. if (video_enabled) @@ -193,6 +194,8 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) break; default: + fifo32 = calloc(DSI_STATUS_RX_FIFO_SIZE * 8, 4); + fifo8 = (u8 *)fifo32; fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE; fifo8[4] = cmd; memcpy(&fifo8[5], data, len); @@ -200,6 +203,7 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++) DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i]; DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; + free(fifo32); break; } @@ -215,29 +219,30 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) void display_init() { // Check if display is already initialized. - if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & BIT(CLK_L_DISP1)) + if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1)) _display_panel_and_hw_end(true); // Get Chip ID. bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; - // T210B01: Power on SD2 regulator for supplying LD0. + // T210B01: Power on SD2 regulator for supplying LDO0. if (!tegra_t210) { // Set SD2 regulator voltage. - max77620_regulator_set_voltage(REGULATOR_SD2, 1325000); + max7762x_regulator_set_voltage(REGULATOR_SD2, 1325000); // Set slew rate and enable SD2 regulator. i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE); - max77620_regulator_enable(REGULATOR_SD2, 1); + max7762x_regulator_enable(REGULATOR_SD2, true); } // Enable power to display panel controller. - max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V. + max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000); + max7762x_regulator_enable(REGULATOR_LDO0, true); + if (tegra_t210) - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, - MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); // T210: LD0 -> GPIO7 -> Display panel. + max77620_config_gpio(7, MAX77620_GPIO_OUTPUT_ENABLE); // T210: LD0 -> GPIO7 -> Display panel. // Enable Display Interface specific clocks. CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI); @@ -293,7 +298,7 @@ void display_init() // Set DISP1 clock source and parent clock. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT. - u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 96 MHz. + u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 97.5 MHz (offset). CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; if (tegra_t210) @@ -335,9 +340,12 @@ void display_init() #if 0 // Get Display ID. - _display_id = 0xCCCCCC; + _display_id = 0xCCCCCC; // Set initial value. 4th byte cleared. display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED); #else + // Drain RX FIFO. + _display_dsi_read_rx_fifo(NULL); + // Set reply size. _display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0); _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); @@ -407,11 +415,11 @@ void display_init() _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000); // Configure PLLD for DISP1. - plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 230.4 MHz. + plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset). CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; if (tegra_t210) - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP + CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP. else CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0; CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN. @@ -420,7 +428,7 @@ void display_init() DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0; DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 19); - // Set pixel clock dividers: 230.4 / 3 / 1 = 76.8 MHz. 60 Hz. + // Set pixel clock dividers: 234 / 3 / 1 = 78 MHz (offset) for 60 Hz. DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3. exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10); usleep(10000); @@ -600,11 +608,20 @@ skip_panel_deinit: void display_end() { _display_panel_and_hw_end(false); }; -u16 display_get_decoded_lcd_id() +u16 display_get_decoded_panel_id() { return _display_id; } +void display_set_decoded_panel_id(u32 id) +{ + // Decode Display ID. + _display_id = ((id >> 8) & 0xFF00) | (id & 0xFF); + + if ((_display_id & 0xFF) == PANEL_JDI_XXX062M) + _display_id = PANEL_JDI_XXX062M; +} + void display_color_screen(u32 color) { exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8); diff --git a/bdk/gfx/di.h b/bdk/display/di.h similarity index 99% rename from bdk/gfx/di.h rename to bdk/display/di.h index e304fb6..5db7b67 100644 --- a/bdk/gfx/di.h +++ b/bdk/display/di.h @@ -651,6 +651,7 @@ * [10] 96 [09]: JDI LAM062M109A * [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1) * [20] 95 [0F]: InnoLux P062CCA-AZ2 + * [20] 96 [0F]: InnoLux P062CCA-AZ3 * [30] 94 [0F]: AUO A062TAN01 (59.06A33.001) * [30] 95 [0F]: AUO A062TAN02 (59.06A33.002) * @@ -671,10 +672,12 @@ * 20h: InnoLux Corporation * 30h: AU Optronics * 40h: Unknown1 + * 50h: Unknown2 (OLED? Samsung? LG?) * * Boards, Panel Size: * 0Fh: Icosa/Iowa, 6.2" * 10h: Hoag, 5.5" + * 20h: Unknown, x.x" */ enum @@ -693,8 +696,9 @@ void display_init(); void display_backlight_pwm_init(); void display_end(); -/*! Get Display panel ID. */ -u16 display_get_decoded_lcd_id(); +/*! Get/Set Display panel ID. */ +u16 display_get_decoded_panel_id(); +void display_set_decoded_panel_id(u32 id); /*! Show one single color on the display. */ void display_color_screen(u32 color); diff --git a/bdk/gfx/di.inl b/bdk/display/di.inl similarity index 100% rename from bdk/gfx/di.inl rename to bdk/display/di.inl diff --git a/bdk/input/als.c b/bdk/input/als.c index 97d6432..918661b 100644 --- a/bdk/input/als.c +++ b/bdk/input/als.c @@ -17,7 +17,6 @@ */ #include "als.h" -#include #include #include #include @@ -98,14 +97,16 @@ void get_als_lux(als_table_t *als_val) u8 als_init(als_table_t *als_val) { + // Enable power to ALS IC. + max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); + max7762x_regulator_enable(REGULATOR_LDO6, true); + + // Init I2C2. pinmux_config_i2c(I2C_2); clock_enable_i2c(I2C_2); i2c_init(I2C_2); - max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, - (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE)); - + // Initialize ALS. u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12)); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), HOS_GAIN); diff --git a/bdk/input/joycon.c b/bdk/input/joycon.c index 9a3e11a..9da1071 100644 --- a/bdk/input/joycon.c +++ b/bdk/input/joycon.c @@ -39,6 +39,9 @@ #define JC_WIRED_INIT_REPLY 0x94 #define JC_INIT_HANDSHAKE 0xA5 +#define JC_HORI_INPUT_RPT_CMD 0x9A +#define JC_HORI_INPUT_RPT 0x00 + #define JC_WIRED_CMD_MAC 0x01 #define JC_WIRED_CMD_10 0x10 @@ -61,8 +64,12 @@ #define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status. #define JC_BTN_MASK_R 0x0056FF -#define JC_ID_L 1 -#define JC_ID_R 2 +#define JC_ID_L 0x01 +#define JC_ID_R 0x02 +#define JC_ID_HORI 0x20 + +#define JC_CRC8_INIT 0x00 +#define JC_CRC8_POLY 0x8D enum { @@ -80,25 +87,31 @@ static const u8 init_jc[] = { static const u8 init_handshake[] = { 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. JC_INIT_HANDSHAKE, 0x02, // Wired cmd and wired subcmd. - 0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data. + 0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data and crc. }; static const u8 init_get_info[] = { 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd. - 0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data. + 0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc. }; -static const u8 init_finilize[] = { +static const u8 init_finalize[] = { 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd. - 0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data. + 0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data and crc. }; static const u8 nx_pad_status[] = { 0x19, 0x01, 0x03, 0x08, 0x00, // Uart header. JC_WIRED_HID, 0x00, // Wired cmd and hid cmd. - 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data. + 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data and crc. +}; + +static const u8 hori_pad_status[] = { + 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. + JC_HORI_INPUT_RPT_CMD, 0x01, // Hori cmd and hori subcmd. + 0x00, 0x00, 0x00, 0x00, 0x48 // Hori cmd data and crc. }; typedef struct _jc_uart_hdr_t @@ -185,8 +198,8 @@ typedef struct _joycon_ctxt_t u8 connected; } joycon_ctxt_t; -static joycon_ctxt_t jc_l; -static joycon_ctxt_t jc_r; +static joycon_ctxt_t jc_l = {0}; +static joycon_ctxt_t jc_r = {0}; static bool jc_init_done = false; static u32 hid_pkt_inc = 0; @@ -195,13 +208,29 @@ static jc_gamepad_rpt_t jc_gamepad; void jc_power_supply(u8 uart, bool enable); +static u8 jc_crc(u8 *data, u16 len) +{ + u8 crc = JC_CRC8_INIT; + u16 i, j; + for (i = 0; i < len; i++) { + crc ^= data[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) + crc = (u8)((crc << 1) ^ JC_CRC8_POLY); + else + crc <<= 1; + } + } + return crc; +} + void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size) { uart_send(uart_port, buf, size); uart_wait_idle(uart_port, UART_TX_IDLE); } -static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size) +static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc) { out->uart_hdr.magic[0] = 0x19; out->uart_hdr.magic[1] = 0x01; @@ -214,14 +243,14 @@ static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u if (data) memcpy(out->data, data, size); - out->crc = 0; // wired crc8ccit can be skipped. + out->crc = crc ? jc_crc(&out->uart_hdr.total_size_msb, sizeof(out->uart_hdr.total_size_msb) + sizeof(out->cmd) + sizeof(out->data)) : 0; return sizeof(jc_wired_hdr_t); } -static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size) +static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc) { - u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0); + u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc); pkt_size += size; rpt->uart_hdr.total_size_lsb += size; @@ -234,12 +263,12 @@ static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size) return pkt_size; } -void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size) +void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc) { u8 rpt[0x50]; memset(rpt, 0, sizeof(rpt)); - u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size); + u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc); joycon_send_raw(uart, rpt, rpt_size); } @@ -275,18 +304,18 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL; hid_pkt->subcmd_data[0] = 1; if (send_r_rumble) - jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10); + jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false); if (send_l_rumble) - jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10); + jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false); // Send rumble. hid_pkt->cmd = JC_HID_RUMBLE_RPT; hid_pkt->pkt_id = jc_hid_pkt_id_incr(); memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init)); if (send_r_rumble) - jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10); + jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false); if (send_l_rumble) - jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10); + jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false); msleep(15); @@ -297,21 +326,21 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) hid_pkt->subcmd_data[0] = 0; memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral)); if (send_r_rumble) - jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10); + jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false); if (send_l_rumble) - jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10); + jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false); } else { + bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI); + hid_pkt->cmd = JC_HID_OUTPUT_RPT; hid_pkt->pkt_id = jc_hid_pkt_id_incr(); hid_pkt->subcmd = subcmd; if (data) memcpy(hid_pkt->subcmd_data, data, size); - u8 pkt_size = sizeof(jc_hid_out_rpt_t) + size; - - jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, pkt_size); + jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed); } } @@ -333,6 +362,7 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size) switch (hid_pkt->cmd) { + case JC_HORI_INPUT_RPT: case JC_HID_INPUT_RPT: btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16; @@ -412,6 +442,7 @@ static void jc_uart_pkt_parse(joycon_ctxt_t *jc, const u8* packet, size_t size) jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet; switch (pkt->cmd) { + case JC_HORI_INPUT_RPT_CMD: case JC_WIRED_HID: jc_parse_wired_hid(jc, pkt->payload, (pkt->data[0] << 8) | pkt->data[1]); break; @@ -474,10 +505,15 @@ static bool jc_send_init_rumble(joycon_ctxt_t *jc) static void jc_req_nx_pad_status(joycon_ctxt_t *jc) { - bool sent_rumble = jc_send_init_rumble(jc); + bool is_nxpad = !(jc->type & JC_ID_HORI); - if (sent_rumble) - return; + if (is_nxpad) + { + bool sent_rumble = jc_send_init_rumble(jc); + + if (sent_rumble) + return; + } if (jc->last_status_req_time > get_tmr_ms() || !jc->connected) return; @@ -488,7 +524,10 @@ static void jc_req_nx_pad_status(joycon_ctxt_t *jc) else gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); - joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status)); + if (is_nxpad) + joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status)); + else + joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status)); // Turn Joy-Con detect on. if (jc->uart == UART_B) @@ -660,12 +699,12 @@ void jc_deinit() u8 data = HCI_STATE_SLEEP; - if (jc_r.connected) + if (jc_r.connected && !(jc_r.type & JC_ID_HORI)) { jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1); jc_rcv_pkt(&jc_r); } - if (jc_l.connected) + if (jc_l.connected && !(jc_l.type & JC_ID_HORI)) { jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1); jc_rcv_pkt(&jc_l); @@ -709,9 +748,12 @@ static void jc_init_conn(joycon_ctxt_t *jc) msleep(5); jc_rcv_pkt(jc); - joycon_send_raw(jc->uart, init_finilize, sizeof(init_finilize)); - msleep(5); - jc_rcv_pkt(jc); + if (!(jc->type & JC_ID_HORI)) + { + joycon_send_raw(jc->uart, init_finalize, sizeof(init_finalize)); + msleep(5); + jc_rcv_pkt(jc); + } // Turn Joy-Con detect on. if (jc->uart == UART_B) @@ -766,10 +808,10 @@ void jc_power_supply(u8 uart, bool enable) { if (enable) { - if (regulator_get_5v_dev_enabled(1 << uart)) + if (regulator_5v_get_dev_enabled(1 << uart)) return; - regulator_enable_5v(1 << uart); + regulator_5v_enable(1 << uart); if (jc_init_done) { @@ -799,10 +841,10 @@ void jc_power_supply(u8 uart, bool enable) } else { - if (!regulator_get_5v_dev_enabled(1 << uart)) + if (!regulator_5v_get_dev_enabled(1 << uart)) return; - regulator_disable_5v(1 << uart); + regulator_5v_disable(1 << uart); if (uart == UART_C) gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW); @@ -816,10 +858,10 @@ void jc_init_hw() jc_l.uart = UART_C; jc_r.uart = UART_B; +#if !defined(DEBUG_UART_PORT) || !(DEBUG_UART_PORT) if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG) return; -#ifndef DEBUG_UART_PORT jc_power_supply(UART_C, true); jc_power_supply(UART_B, true); diff --git a/bdk/input/touch.c b/bdk/input/touch.c index f24b53a..11efed0 100644 --- a/bdk/input/touch.c +++ b/bdk/input/touch.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -34,6 +33,16 @@ #include #define DPRINTF(...) gfx_printf(__VA_ARGS__) +static touch_panel_info_t _panels[] = +{ + { 0, 1, 1, 1, "NISSHA NFT-K12D" }, + { 1, 0, 1, 1, "GiS GGM6 B2X" }, + { 2, 0, 0, 0, "NISSHA NBF-K9A" }, + { 3, 1, 0, 0, "GiS 5.5\"" }, + { 4, 0, 0, 1, "Unknown" }, + { -1, 1, 0, 1, "GiS VA 6.2\"" } +}; + static int touch_command(u8 cmd, u8 *buf, u8 size) { int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd, buf, size); @@ -53,7 +62,7 @@ static int touch_read_reg(u8 *cmd, u32 csize, u8 *buf, u32 size) return 0; } -static int touch_wait_event(u8 event, u8 status, u32 timeout) +static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf) { u32 timer = get_tmr_ms() + timeout; while (true) @@ -61,7 +70,11 @@ static int touch_wait_event(u8 event, u8 status, u32 timeout) u8 tmp[8] = {0}; i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT); if (tmp[1] == event && tmp[2] == status) + { + if (buf) + memcpy(buf, &tmp[3], 5); return 0; + } if (get_tmr_ms() > timer) return 1; @@ -147,10 +160,10 @@ static void _touch_parse_event(touch_event *event) event->type = STMFTS_EV_MULTI_TOUCH_LEAVE; } - // gfx_con_setpos(&gfx_con, 0, 300); + // gfx_con_setpos(0, 300); // DPRINTF("x = %d \ny = %d \nz = %d \n", event->x, event->y, event->z); - // DPRINTF("0 = %02X\n1 = %02x\n2 = %02x\n3 = %02x\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]); - // DPRINTF("4 = %02X\n5 = %02x\n6 = %02x\n7 = %02x\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]); + // DPRINTF("0 = %02X\n1 = %02X\n2 = %02X\n3 = %02X\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]); + // DPRINTF("4 = %02X\n5 = %02X\n6 = %02X\n7 = %02X\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]); } void touch_poll(touch_event *event) @@ -183,12 +196,33 @@ touch_info touch_get_info() info.config_id = buf[4]; info.config_ver = buf[5]; - //DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02x, Cfg Ver: %d\n", + //DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02X, Cfg Ver: %d\n", // info.chip_id, info.fw_ver >> 8, info.fw_ver & 0xFF, info.config_id, info.config_ver); return info; } +touch_panel_info_t *touch_get_panel_vendor() +{ + u8 buf[5] = {0}; + u8 cmd = STMFTS_VENDOR_GPIO_STATE; + + if (touch_command(STMFTS_VENDOR, &cmd, 1)) + return NULL; + + if (touch_wait_event(STMFTS_EV_VENDOR, STMFTS_VENDOR_GPIO_STATE, 2000, buf)) + return NULL; + + for (u32 i = 0; i < ARRAY_SIZE(_panels); i++) + { + touch_panel_info_t *panel = &_panels[i]; + if (buf[0] == panel->gpio0 && buf[1] == panel->gpio1 && buf[2] == panel->gpio2) + return panel; + } + + return NULL; +} + int touch_get_fw_info(touch_fw_info_t *fw) { u8 buf[8] = {0}; @@ -227,7 +261,7 @@ int touch_sys_reset() continue; } msleep(10); - if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20)) + if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL)) continue; else return 0; @@ -301,9 +335,9 @@ int touch_get_fb_info(u8 *buf) int touch_sense_enable() { - // Enable auto tuning calibration and multi-touch sensing. - u8 cmd = 1; - if (touch_command(STMFTS_AUTO_CALIBRATION, &cmd, 1)) + // Switch sense mode and enable multi-touch sensing. + u8 cmd = STMFTS_FINGER_MODE; + if (touch_command(STMFTS_SWITCH_SENSE_MODE, &cmd, 1)) return 0; if (touch_command(STMFTS_MS_MT_SENSE_ON, NULL, 0)) @@ -329,19 +363,19 @@ int touch_execute_autotune() // Apply Mutual Sense Compensation tuning. if (touch_command(STMFTS_MS_CX_TUNING, NULL, 0)) return 0; - if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000)) + if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000, NULL)) return 0; // Apply Self Sense Compensation tuning. if (touch_command(STMFTS_SS_CX_TUNING, NULL, 0)) return 0; - if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000)) + if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000, NULL)) return 0; // Save Compensation data to EEPROM. if (touch_command(STMFTS_SAVE_CX_TUNING, NULL, 0)) return 0; - if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000)) + if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000, NULL)) return 0; return touch_sense_enable(); @@ -358,10 +392,9 @@ static int touch_init() int touch_power_on() { - // Enables LDO6 for touchscreen VDD/AVDD supply - max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, - (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE)); + // Enable LDO6 for touchscreen VDD/AVDD supply. + max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); + max7762x_regulator_enable(REGULATOR_LDO6, true); // Configure touchscreen GPIO. PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; @@ -385,7 +418,7 @@ int touch_power_on() i2c_init(I2C_3); // Wait for the touchscreen module to get ready. - touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20); + touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL); // Check for forced boot time calibration. if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) @@ -414,9 +447,7 @@ void touch_power_off() gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW); // Disables LDO6 for touchscreen VDD, AVDD supply - max77620_regulator_enable(REGULATOR_LDO6, 0); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, - MAX77620_LDO_CFG2_ADE_ENABLE | (2 << 3) | (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT)); + max7762x_regulator_enable(REGULATOR_LDO6, false); clock_disable_i2c(I2C_3); } \ No newline at end of file diff --git a/bdk/input/touch.h b/bdk/input/touch.h index 9245be3..3345faa 100644 --- a/bdk/input/touch.h +++ b/bdk/input/touch.h @@ -47,19 +47,26 @@ #define STMFTS_ITO_CHECK 0xA7 #define STMFTS_RELEASEINFO 0xAA #define STMFTS_WRITE_REG 0xB6 -#define STMFTS_AUTO_CALIBRATION 0xC3 +#define STMFTS_SWITCH_SENSE_MODE 0xC3 #define STMFTS_NOISE_WRITE 0xC7 #define STMFTS_NOISE_READ 0xC8 #define STMFTS_RW_FRAMEBUFFER_REG 0xD0 #define STMFTS_SAVE_CX_TUNING 0xFC -#define STMFTS_UNK0 0xB8 //Request compensation -#define STMFTS_UNK1 0xCF -#define STMFTS_UNK2 0xF7 -#define STMFTS_UNK3 0xFA -#define STMFTS_UNK4 0xF9 +#define STMFTS_REQU_COMP_DATA 0xB8 +#define STMFTS_VENDOR 0xCF +#define STMFTS_FLASH_UNLOCK 0xF7 +#define STMFTS_FLASH_WRITE_64K 0xF8 +#define STMFTS_FLASH_STATUS 0xF9 +#define STMFTS_FLASH_OP 0xFA #define STMFTS_UNK5 0x62 +/* cmd parameters */ +#define STMFTS_VENDOR_GPIO_STATE 0x01 +#define STMFTS_VENDOR_SENSE_MODE 0x02 +#define STMFTS_STYLUS_MODE 0x00 +#define STMFTS_FINGER_MODE 0x01 +#define STMFTS_HOVER_MODE 0x02 /* events */ #define STMFTS_EV_NO_EVENT 0x00 @@ -74,6 +81,7 @@ #define STMFTS_EV_ERROR 0x0f #define STMFTS_EV_NOISE_READ 0x17 #define STMFTS_EV_NOISE_WRITE 0x18 +#define STMFTS_EV_VENDOR 0x20 #define STMFTS_EV_CONTROLLER_READY 0x10 #define STMFTS_EV_STATUS 0x16 @@ -131,6 +139,15 @@ typedef struct _touch_event { bool touch; } touch_event; +typedef struct _touch_panel_info_t +{ + u8 idx; + u8 gpio0; + u8 gpio1; + u8 gpio2; + char *vendor; +} touch_panel_info_t; + typedef struct _touch_info { u16 chip_id; u16 fw_ver; @@ -146,6 +163,7 @@ typedef struct _touch_fw_info_t { void touch_poll(touch_event *event); touch_event touch_poll_wait(); +touch_panel_info_t *touch_get_panel_vendor(); int touch_get_fw_info(touch_fw_info_t *fw); touch_info touch_get_info(); int touch_panel_ito_test(u8 *err); diff --git a/bdk/mem/mc.c b/bdk/mem/mc.c index cc136dc..c695987 100644 --- a/bdk/mem/mc.c +++ b/bdk/mem/mc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2020 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, @@ -20,6 +20,8 @@ #include #include +//#define CONFIG_ENABLE_AHB_REDIRECT + void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock) { MC(MC_SEC_CARVEOUT_BOM) = bom; @@ -143,17 +145,19 @@ void mc_disable_ahb_redirect() void mc_enable() { + // Reset EMC source to PLLP. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; // Enable memory clocks. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_EMC)) | BIT(CLK_H_EMC); - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_MEM)) | BIT(CLK_H_MEM); - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & ~BIT(CLK_X_EMC_DLL)) | BIT(CLK_X_EMC_DLL); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL); // Clear clock resets for memory. CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); usleep(5); - //#ifdef CONFIG_ENABLE_AHB_REDIRECT +#ifdef CONFIG_ENABLE_AHB_REDIRECT + mc_enable_ahb_redirect(); +#else mc_disable_ahb_redirect(); - //mc_enable_ahb_redirect(); - //#endif +#endif } diff --git a/bdk/mem/minerva.c b/bdk/mem/minerva.c index 183b633..6136d73 100644 --- a/bdk/mem/minerva.c +++ b/bdk/mem/minerva.c @@ -60,7 +60,7 @@ u32 minerva_init() mtc_config_t mtc_tmp; mtc_tmp.mtc_table = mtc_cfg->mtc_table; - mtc_tmp.sdram_id = (fuse_read_odm(4) >> 3) & 0x1F; + mtc_tmp.sdram_id = fuse_read_dramid(false); mtc_tmp.init_done = MTC_NEW_MAGIC; u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp); @@ -81,7 +81,7 @@ u32 minerva_init() // Set table to nyx storage. mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table; - mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F; + mtc_cfg->sdram_id = fuse_read_dramid(false); mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table. u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); @@ -129,6 +129,7 @@ void minerva_change_freq(minerva_freq_t freq) if (!minerva_cfg) return; + // Check if requested frequency is different. Do not allow otherwise because it will hang. mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; if (mtc_cfg->rate_from != freq) { diff --git a/bdk/mem/sdram.c b/bdk/mem/sdram.c index aad98db..b119f46 100644 --- a/bdk/mem/sdram.c +++ b/bdk/mem/sdram.c @@ -54,11 +54,6 @@ typedef struct _sdram_vendor_patch_t #include "sdram_config_t210b01.inl" -static u32 _sdram_get_id() -{ - return ((fuse_read_odm(4) & 0xF8) >> 3); -} - static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel) { bool err = true; @@ -1374,9 +1369,7 @@ static void _sdram_patch_model_params_t210b01(u32 dramid, u32 *params) static void *_sdram_get_params_t210() { // Check if id is proper. - u32 dramid = _sdram_get_id(); - if (dramid > 6) - dramid = 0; + u32 dramid = fuse_read_dramid(false); #ifdef CONFIG_SDRAM_COMPRESS_CFG @@ -1413,9 +1406,7 @@ static void *_sdram_get_params_t210() void *sdram_get_params_t210b01() { // Check if id is proper. - u32 dramid = _sdram_get_id(); - if (dramid > 27) - dramid = 8; + u32 dramid = fuse_read_dramid(false); u32 *buf = (u32 *)SDRAM_PARAMS_ADDR; memcpy(buf, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t)); @@ -1439,12 +1430,12 @@ void *sdram_get_params_t210b01() case LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X: case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y: case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y: - case LPDDR4X_SDS_4GB_SAMSUNG_1Y_A: - case LPDDR4X_SDS_8GB_SAMSUNG_1Y_X: - case LPDDR4X_SDS_4GB_SAMSUNG_1Y_X: + case LPDDR4X_AULA_4GB_SAMSUNG_1Y_A: + case LPDDR4X_AULA_8GB_SAMSUNG_1Y_X: + case LPDDR4X_AULA_4GB_SAMSUNG_1Y_X: case LPDDR4X_IOWA_4GB_MICRON_1Y_A: case LPDDR4X_HOAG_4GB_MICRON_1Y_A: - case LPDDR4X_SDS_4GB_MICRON_1Y_A: + case LPDDR4X_AULA_4GB_MICRON_1Y_A: _sdram_patch_model_params_t210b01(dramid, (u32 *)buf); break; } @@ -1494,7 +1485,7 @@ static void _sdram_init_t210() const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210(); // Set DRAM voltage. - max77620_regulator_set_voltage(REGULATOR_SD1, 1100000); + max7762x_regulator_set_voltage(REGULATOR_SD1, 1100000); // VDDP Select. PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; @@ -1539,8 +1530,8 @@ static void _sdram_init_t210b01() void sdram_init() { - // Configure SD regulator for DRAM. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05); + // Disable remote sense for SD1. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0 | MAX77620_SD_CNF2_RSVD); if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) _sdram_init_t210(); diff --git a/bdk/mem/sdram.h b/bdk/mem/sdram.h index 77db819..8455862 100644 --- a/bdk/mem/sdram.h +++ b/bdk/mem/sdram.h @@ -45,7 +45,7 @@ enum sdram_ids_erista LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, - LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, + LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to AULA Hynix 4GB 1Y-A. LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, @@ -76,14 +76,14 @@ enum sdram_ids_mariko LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20, LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21, - LPDDR4X_SDS_4GB_SAMSUNG_1Y_A = 22, + LPDDR4X_AULA_4GB_SAMSUNG_1Y_A = 22, - LPDDR4X_SDS_8GB_SAMSUNG_1Y_X = 23, - LPDDR4X_SDS_4GB_SAMSUNG_1Y_X = 24, + LPDDR4X_AULA_8GB_SAMSUNG_1Y_X = 23, + LPDDR4X_AULA_4GB_SAMSUNG_1Y_X = 24, LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25, LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26, - LPDDR4X_SDS_4GB_MICRON_1Y_A = 27 + LPDDR4X_AULA_4GB_MICRON_1Y_A = 27 }; void sdram_init(); diff --git a/bdk/mem/sdram_config.inl b/bdk/mem/sdram_config.inl index 727ec60..97c723a 100644 --- a/bdk/mem/sdram_config.inl +++ b/bdk/mem/sdram_config.inl @@ -97,7 +97,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { * DRAM size information * Specifies the value for EMC_ADR_CFG */ - .emc_adr_cfg = 0x00000001, // 2 populated DRAM Devices. + .emc_adr_cfg = 0x00000001, // 2 Ranks. /* * Specifies the time to wait after asserting pin @@ -243,7 +243,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .emc_cfg_dig_dll = 0x002C00A0, .emc_cfg_dig_dll_1 = 0x00003701, .emc_cfg_dig_dll_period = 0x00008000, - .emc_dev_select = 0x00000000, // Both devices. + .emc_dev_select = 0x00000000, // Both Ranks. .emc_sel_dpd_ctrl = 0x00040008, /* Pads trimmer delays */ @@ -406,7 +406,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .pmc_ddr_ctrl = 0x0007FF8B, .emc_acpd_control = 0x00000000, - .emc_swizzle_rank0_byte0 = 0x76543201, + .emc_swizzle_rank0_byte0 = 0x76543201, // Overridden to 0x76543201 by spare6/7. .emc_swizzle_rank0_byte1 = 0x65324710, .emc_swizzle_rank0_byte2 = 0x25763410, .emc_swizzle_rank0_byte3 = 0x25673401, @@ -454,7 +454,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .emc_pmacro_data_rx_term_mode = 0x00000010, .emc_pmacro_cmd_rx_term_mode = 0x00003000, .emc_pmacro_data_pad_tx_ctrl = 0x02000111, - .emc_pmacro_common_pad_tx_ctrl = 0x00000008, + .emc_pmacro_common_pad_tx_ctrl = 0x00000008, // Overridden to 0x0000000A by spare4/5. .emc_pmacro_cmd_pad_tx_ctrl = 0x0A000000, .emc_cfg3 = 0x00000040, @@ -490,9 +490,9 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A, /* DRAM size information */ - .mc_emem_adr_cfg = 0x00000001, // 2 populated DRAM Devices. - .mc_emem_adr_cfg_dev0 = 0x00070302, // Density 512MB. - .mc_emem_adr_cfg_dev1 = 0x00070302, // Density 512MB. + .mc_emem_adr_cfg = 0x00000001, // 2 Ranks. + .mc_emem_adr_cfg_dev0 = 0x00070302, // Rank 0 Density 512MB. + .mc_emem_adr_cfg_dev1 = 0x00070302, // Rank 1 Density 512MB. .mc_emem_adr_cfg_channel_mask = 0xFFFF2400, .mc_emem_adr_cfg_bank_mask0 = 0x6E574400, .mc_emem_adr_cfg_bank_mask1 = 0x39722800, @@ -653,8 +653,8 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = { { 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w. // Samsung 6GB density config. - { 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density. - { 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density. + { 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB Rank 0 density. + { 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density. { 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. #ifdef CONFIG_SDRAM_COPPER_SUPPORT diff --git a/bdk/mem/sdram_config_t210b01.inl b/bdk/mem/sdram_config_t210b01.inl index 983c93a..e5c197e 100644 --- a/bdk/mem/sdram_config_t210b01.inl +++ b/bdk/mem/sdram_config_t210b01.inl @@ -122,7 +122,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { * DRAM size information * Specifies the value for EMC_ADR_CFG */ - .emc_adr_cfg = 0x00000000, // 1 populated DRAM Device. + .emc_adr_cfg = 0x00000000, // 1 Rank. /* * Specifies the time to wait after asserting pin @@ -273,7 +273,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { .emc_cfg_dig_dll = 0x002C00A0, .emc_cfg_dig_dll_1 = 0x000F3701, .emc_cfg_dig_dll_period = 0x00008000, - .emc_dev_select = 0x00000002, // Dev0 only. + .emc_dev_select = 0x00000002, // Rank 0 only. .emc_sel_dpd_ctrl = 0x0004000C, /* Pads trimmer delays */ @@ -543,9 +543,9 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { .emc_pmacro_cmd_ctrl2 = 0x00000000, /* DRAM size information */ - .mc_emem_adr_cfg = 0x00000000, // 1 populated DRAM Device. - .mc_emem_adr_cfg_dev0 = 0x00080302, // Density 1024MB. - .mc_emem_adr_cfg_dev1 = 0x00080302, // Density 1024MB. + .mc_emem_adr_cfg = 0x00000000, // 1 Rank. + .mc_emem_adr_cfg_dev0 = 0x00080302, // Rank 0 Density 1024MB. + .mc_emem_adr_cfg_dev1 = 0x00080302, // Rank 1 Density 1024MB. .mc_emem_adr_cfg_channel_mask = 0xFFFF2400, .mc_emem_adr_cfg_bank_mask0 = 0x6E574400, .mc_emem_adr_cfg_bank_mask1 = 0x39722800, @@ -733,7 +733,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { // Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ for SDEV Iowa and Hoag. { 0x05500000, 0x0D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 Ranks. { 0x00000006, 0x1CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse. { 0x00000005, 0x1D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse_width. { 0x00000003, 0x1DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput. @@ -764,7 +764,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x40000001, 0x45C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_init_dev1. { 0x00000000, 0x594 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd4. { 0x00001000, 0x598 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00002000, 0x64C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_cfg. 8GB total density. { 0x00000002, 0x680 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_timing_r2r. { 0x02020001, 0x694 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_da_turns. @@ -810,7 +810,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x2A800000, 0x6DC / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override0. { 0x00000002, 0x6E0 / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override1. - // Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and SDS. + // Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and Aula. { 0x05500000, 0x0D4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_vref_sel0. { 0x00000006, 0x1CC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse. @@ -822,10 +822,10 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x2A800000, 0x6DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override0. { 0x00000002, 0x6E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override1. - // Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and SDS. + // Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and Aula. { 0x05500000, 0x0D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 Ranks. { 0x00000006, 0x1CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse. { 0x00000005, 0x1D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse_width. { 0x00000003, 0x1DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput. @@ -847,7 +847,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x40000001, 0x45C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_init_dev1. { 0x00000000, 0x594 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd4. { 0x00001000, 0x598 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00002000, 0x64C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_cfg. 8GB total density. { 0x00000001, 0x670 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_faw. { 0x00000002, 0x680 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_r2r. @@ -881,7 +881,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { // Samsung LPDDR4X 8GB 10nm-class (1y) Die-Y for SDEV Iowa. { 0x05500000, 0x0D4 / 4, DRAM_ID2(21) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(21) }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 Ranks. { 0x00000008, 0x24C / 4, DRAM_ID2(21) }, // emc_tfaw. { 0x08010004, 0x2B8 / 4, DRAM_ID2(21) }, // emc_mrw1. { 0x08020000, 0x2BC / 4, DRAM_ID2(21) }, // emc_mrw2. @@ -914,7 +914,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x40000001, 0x45C / 4, DRAM_ID2(21) }, // emc_zcal_init_dev1. { 0x00000000, 0x594 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd4. { 0x00001000, 0x598 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00002000, 0x64C / 4, DRAM_ID2(21) }, // mc_emem_cfg. 8GB total density. { 0x00000001, 0x670 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_faw. { 0x00000002, 0x680 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_r2r. @@ -922,7 +922,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x2A800000, 0x6DC / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override0. { 0x00000002, 0x6E0 / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override1. - // Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown SDS. + // Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Aula. { 0x05500000, 0x0D4 / 4, DRAM_ID2(22) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0. { 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw. @@ -986,7 +986,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1. { 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode. - // Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/SDS. + // Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/Aula. { 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_vref_sel0. { 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse. diff --git a/bdk/power/max77620.h b/bdk/power/max77620.h index 23ee299..d54909f 100644 --- a/bdk/power/max77620.h +++ b/bdk/power/max77620.h @@ -1,8 +1,7 @@ /* * Defining registers address and its bit definitions of MAX77620 and MAX20024 * - * Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved. - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 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, @@ -30,24 +29,33 @@ #define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4) #define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4) #define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4) -#define MAX77620_CNFGGLBL1_LBHYST (BIT(5) | BIT(4)) #define MAX77620_CNFGGLBL1_MPPLD BIT(6) #define MAX77620_CNFGGLBL1_LBDAC_EN BIT(7) #define MAX77620_REG_CNFGGLBL2 0x01 -#define MAX77620_REG_CNFGGLBL3 0x02 -#define MAX77620_WDTC_MASK 0x3 -#define MAX77620_WDTEN BIT(2) -#define MAX77620_WDTSLPC BIT(3) -#define MAX77620_WDTOFFC BIT(4) #define MAX77620_TWD_MASK 0x3 #define MAX77620_TWD_2s 0x0 #define MAX77620_TWD_16s 0x1 #define MAX77620_TWD_64s 0x2 #define MAX77620_TWD_128s 0x3 +#define MAX77620_WDTEN BIT(2) +#define MAX77620_WDTSLPC BIT(3) +#define MAX77620_WDTOFFC BIT(4) +#define MAX77620_GLBL_LPM BIT(5) +#define MAX77620_I2CTWD_MASK 0xC0 +#define MAX77620_I2CTWD_DISABLED 0x00 +#define MAX77620_I2CTWD_1_33ms 0x40 +#define MAX77620_I2CTWD_35_7ms 0x80 +#define MAX77620_I2CTWD_41_7ms 0xC0 + +#define MAX77620_REG_CNFGGLBL3 0x02 +#define MAX77620_WDTC_MASK 0x3 #define MAX77620_REG_CNFG1_32K 0x03 +#define MAX77620_CNFG1_PWR_MD_32K_MASK 0x3 #define MAX77620_CNFG1_32K_OUT0_EN BIT(2) +#define MAX77620_CNFG1_32KLOAD_MASK 0x30 +#define MAX77620_CNFG1_32K_OK BIT(7) #define MAX77620_REG_CNFGBBC 0x04 #define MAX77620_CNFGBBC_ENABLE BIT(0) @@ -64,6 +72,7 @@ #define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT) #define MAX77620_REG_IRQTOP 0x05 +#define MAX77620_REG_IRQTOPM 0x0D #define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1) #define MAX77620_IRQ_TOP_32K_MASK BIT(2) #define MAX77620_IRQ_TOP_RTC_MASK BIT(3) @@ -73,28 +82,53 @@ #define MAX77620_IRQ_TOP_GLBL_MASK BIT(7) #define MAX77620_REG_INTLBT 0x06 -#define MAX77620_REG_IRQTOPM 0x0D +#define MAX77620_REG_INTENLBT 0x0E +#define MAX77620_IRQ_GLBLM_MASK BIT(0) #define MAX77620_IRQ_TJALRM2_MASK BIT(1) #define MAX77620_IRQ_TJALRM1_MASK BIT(2) #define MAX77620_IRQ_LBM_MASK BIT(3) #define MAX77620_REG_IRQSD 0x07 -#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 -#define MAX77620_REG_IRQ_LVL2_L8 0x09 -#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A -#define MAX77620_REG_ONOFFIRQ 0x0B -#define MAX77620_REG_NVERC 0x0C - -#define MAX77620_REG_INTENLBT 0x0E -#define MAX77620_GLBLM_MASK BIT(0) - #define MAX77620_REG_IRQMASKSD 0x0F +#define MAX77620_IRQSD_PFI_SD3 BIT(4) +#define MAX77620_IRQSD_PFI_SD2 BIT(5) +#define MAX77620_IRQSD_PFI_SD1 BIT(6) +#define MAX77620_IRQSD_PFI_SD0 BIT(7) + +#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 // LDO number that irq occured. #define MAX77620_REG_IRQ_MSK_L0_7 0x10 +#define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occured. Only bit0: LDO8 is valid. #define MAX77620_REG_IRQ_MSK_L8 0x11 +#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt. + +#define MAX77620_REG_ONOFFIRQ 0x0B #define MAX77620_REG_ONOFFIRQM 0x12 +#define MAX77620_ONOFFIRQ_MRWRN BIT(0) +#define MAX77620_ONOFFIRQ_EN0_1SEC BIT(1) +#define MAX77620_ONOFFIRQ_EN0_F BIT(2) +#define MAX77620_ONOFFIRQ_EN0_R BIT(3) +#define MAX77620_ONOFFIRQ_LID_F BIT(4) +#define MAX77620_ONOFFIRQ_LID_R BIT(5) +#define MAX77620_ONOFFIRQ_ACOK_F BIT(6) +#define MAX77620_ONOFFIRQ_ACOK_R BIT(7) + +#define MAX77620_REG_NVERC 0x0C // Shutdown reason (non-volatile). +#define MAX77620_NVERC_SHDN BIT(0) +#define MAX77620_NVERC_WTCHDG BIT(1) +#define MAX77620_NVERC_HDRST BIT(2) +#define MAX77620_NVERC_TOVLD BIT(3) +#define MAX77620_NVERC_MBLSD BIT(4) +#define MAX77620_NVERC_MBO BIT(5) +#define MAX77620_NVERC_MBU BIT(6) +#define MAX77620_NVERC_RSTIN BIT(7) + #define MAX77620_REG_STATLBT 0x13 #define MAX77620_REG_STATSD 0x14 + #define MAX77620_REG_ONOFFSTAT 0x15 +#define MAX77620_ONOFFSTAT_LID BIT(0) +#define MAX77620_ONOFFSTAT_ACOK BIT(1) +#define MAX77620_ONOFFSTAT_EN0 BIT(2) /* SD and LDO Registers */ #define MAX77620_REG_SD0 0x16 @@ -102,18 +136,42 @@ #define MAX77620_REG_SD2 0x18 #define MAX77620_REG_SD3 0x19 #define MAX77620_REG_SD4 0x1A +#define MAX77620_REG_DVSSD0 0x1B +#define MAX77620_REG_DVSSD1 0x1C #define MAX77620_SDX_VOLT_MASK 0xFF #define MAX77620_SD0_VOLT_MASK 0x3F #define MAX77620_SD1_VOLT_MASK 0x7F #define MAX77620_LDO_VOLT_MASK 0x3F -#define MAX77620_REG_DVSSD0 0x1B -#define MAX77620_REG_DVSSD1 0x1C -#define MAX77620_REG_SD0_CFG 0x1D // SD CNFG1. -#define MAX77620_REG_SD1_CFG 0x1E // SD CNFG1. -#define MAX77620_REG_SD2_CFG 0x1F // SD CNFG1. -#define MAX77620_REG_SD3_CFG 0x20 // SD CNFG1. -#define MAX77620_REG_SD4_CFG 0x21 // SD CNFG1. + +#define MAX77620_REG_SD0_CFG 0x1D +#define MAX77620_REG_SD1_CFG 0x1E +#define MAX77620_REG_SD2_CFG 0x1F +#define MAX77620_REG_SD3_CFG 0x20 +#define MAX77620_REG_SD4_CFG 0x21 +#define MAX77620_SD_SR_MASK 0xC0 +#define MAX77620_SD_SR_SHIFT 6 +#define MAX77620_SD_POWER_MODE_MASK 0x30 +#define MAX77620_SD_POWER_MODE_SHIFT 4 +#define MAX77620_SD_CFG1_ADE_MASK BIT(3) +#define MAX77620_SD_CFG1_ADE_DISABLE 0 +#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3) +#define MAX77620_SD_FPWM_MASK 0x04 +#define MAX77620_SD_FPWM_SHIFT 2 +#define MAX77620_SD_FSRADE_MASK 0x01 +#define MAX77620_SD_FSRADE_SHIFT 0 +#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2) +#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 +#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2) +#define MAX77620_SD_CFG1_MPOK_MASK BIT(1) +#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0) +#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 +#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0) + #define MAX77620_REG_SD_CFG2 0x22 +#define MAX77620_SD_CNF2_RSVD BIT(0) +#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1) +#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2) + #define MAX77620_REG_LDO0_CFG 0x23 #define MAX77620_REG_LDO0_CFG2 0x24 #define MAX77620_REG_LDO1_CFG 0x25 @@ -132,26 +190,36 @@ #define MAX77620_REG_LDO7_CFG2 0x32 #define MAX77620_REG_LDO8_CFG 0x33 #define MAX77620_REG_LDO8_CFG2 0x34 -#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) -#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) -#define MAX77620_LDO_CFG2_SS_SLOW 0 -#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) -#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1) -#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) -#define MAX20024_LDO_CFG2_MPOK_MASK BIT(2) -#define MAX77620_LDO_POWER_MODE_MASK 0xC0 +/*! LDO CFG */ #define MAX77620_LDO_POWER_MODE_SHIFT 6 +#define MAX77620_LDO_POWER_MODE_MASK (3 << MAX77620_LDO_POWER_MODE_SHIFT) #define MAX77620_POWER_MODE_NORMAL 3 #define MAX77620_POWER_MODE_LPM 2 #define MAX77620_POWER_MODE_GLPM 1 #define MAX77620_POWER_MODE_DISABLE 0 +/*! LDO CFG2 */ +#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) +#define MAX77620_LDO_CFG2_SS_FAST (0 << 0) +#define MAX77620_LDO_CFG2_SS_SLOW (1 << 0) +#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) +#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1) +#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) +#define MAX77620_LDO_CFG2_MPOK_MASK BIT(2) +#define MAX77620_LDO_CFG2_POK_MASK BIT(3) +#define MAX77620_LDO_CFG2_COMP_SHIFT 4 +#define MAX77620_LDO_CFG2_COMP_MASK (3 << MAX77620_LDO_COMP_SHIFT) +#define MAX77620_LDO_CFG2_COMP_SLOW 3 +#define MAX77620_LDO_CFG2_COMP_MID_SLOW 2 +#define MAX77620_LDO_CFG2_COMP_MID_FAST 1 +#define MAX77620_LDO_CFG2_COMP_FAST 0 +#define MAX77620_LDO_CFG2_ALPM_EN_MASK BIT(6) +#define MAX77620_LDO_CFG2_OVCLMP_MASK BIT(7) #define MAX77620_REG_LDO_CFG3 0x35 +#define MAX77620_LDO_BIAS_EN BIT(0) #define MAX77620_TRACK4_SHIFT 5 #define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT) -#define MAX77620_LDO_SLEW_RATE_MASK 0x1 - #define MAX77620_REG_GPIO0 0x36 #define MAX77620_REG_GPIO1 0x37 #define MAX77620_REG_GPIO2 0x38 @@ -160,9 +228,6 @@ #define MAX77620_REG_GPIO5 0x3B #define MAX77620_REG_GPIO6 0x3C #define MAX77620_REG_GPIO7 0x3D -#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) @@ -181,6 +246,13 @@ #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_GPIO_OUTPUT_DISABLE 0 +#define MAX77620_GPIO_OUTPUT_ENABLE 1 + +#define MAX77620_REG_PUE_GPIO 0x3E // Gpio Pullup resistor enable. +#define MAX77620_REG_PDE_GPIO 0x3F // Gpio Pulldown resistor enable. + +#define MAX77620_REG_AME_GPIO 0x40 // Gpio pinmuxing. Clear bits are Standard GPIO. #define MAX77620_REG_ONOFFCNFG1 0x41 #define MAX20024_ONOFFCNFG1_CLRSE 0x18 @@ -188,19 +260,30 @@ #define MAX77620_ONOFFCNFG1_SLPEN BIT(2) #define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 #define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 +#define MAX77620_ONOFFCNFG1_RSVD BIT(6) #define MAX77620_ONOFFCNFG1_SFT_RST BIT(7) #define MAX77620_REG_ONOFFCNFG2 0x42 #define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0) +#define MAX77620_ONOFFCNFG2_WK_ALARM2 BIT(1) #define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2) +#define MAX77620_ONOFFCNFG2_WK_MBATT BIT(3) // MBATT event generates a wakeup signal. use it in android/l4t? +#define MAX77620_ONOFFCNFG2_WK_ACOK BIT(4) #define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5) #define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6) #define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7) /* FPS Registers */ -#define MAX77620_REG_FPS_CFG0 0x43 -#define MAX77620_REG_FPS_CFG1 0x44 -#define MAX77620_REG_FPS_CFG2 0x45 +#define MAX77620_REG_FPS_CFG0 0x43 // FPS0. +#define MAX77620_REG_FPS_CFG1 0x44 // FPS1. +#define MAX77620_REG_FPS_CFG2 0x45 // FPS2. +#define MAX77620_FPS_ENFPS_SW_MASK 0x01 +#define MAX77620_FPS_ENFPS_SW 0x01 +#define MAX77620_FPS_EN_SRC_SHIFT 1 +#define MAX77620_FPS_EN_SRC_MASK 0x06 +#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 +#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 + #define MAX77620_REG_FPS_LDO0 0x46 #define MAX77620_REG_FPS_LDO1 0x47 #define MAX77620_REG_FPS_LDO2 0x48 @@ -215,77 +298,39 @@ #define MAX77620_REG_FPS_SD2 0x51 #define MAX77620_REG_FPS_SD3 0x52 #define MAX77620_REG_FPS_SD4 0x53 -#define MAX77620_REG_FPS_NONE 0 -#define MAX77620_FPS_SRC_MASK 0xC0 -#define MAX77620_FPS_SRC_SHIFT 6 -#define MAX77620_FPS_PU_PERIOD_MASK 0x38 -#define MAX77620_FPS_PU_PERIOD_SHIFT 3 -#define MAX77620_FPS_PD_PERIOD_MASK 0x07 -#define MAX77620_FPS_PD_PERIOD_SHIFT 0 - -/* Minimum and maximum FPS period time (in microseconds) are - * different for MAX77620 and Max20024. - */ -#define MAX77620_FPS_COUNT 3 - -#define MAX77620_FPS_PERIOD_MIN_US 40 -#define MAX20024_FPS_PERIOD_MIN_US 20 - -#define MAX77620_FPS_PERIOD_MAX_US 2560 -#define MAX20024_FPS_PERIOD_MAX_US 5120 - #define MAX77620_REG_FPS_GPIO1 0x54 #define MAX77620_REG_FPS_GPIO2 0x55 #define MAX77620_REG_FPS_GPIO3 0x56 -#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 -#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 -#define MAX77620_FPS_EN_SRC_MASK 0x06 -#define MAX77620_FPS_EN_SRC_SHIFT 1 -#define MAX77620_FPS_ENFPS_SW_MASK 0x01 -#define MAX77620_FPS_ENFPS_SW 0x01 - #define MAX77620_REG_FPS_RSO 0x57 +#define MAX77620_FPS_PD_PERIOD_SHIFT 0 +#define MAX77620_FPS_PD_PERIOD_MASK 0x07 +#define MAX77620_FPS_PU_PERIOD_SHIFT 3 +#define MAX77620_FPS_PU_PERIOD_MASK 0x38 +#define MAX77620_FPS_SRC_SHIFT 6 +#define MAX77620_FPS_SRC_MASK 0xC0 + +#define MAX77620_FPS_COUNT 3 +#define MAX77620_FPS_PERIOD_MIN_US 40 +#define MAX77620_FPS_PERIOD_MAX_US 2560 + #define MAX77620_REG_CID0 0x58 #define MAX77620_REG_CID1 0x59 #define MAX77620_REG_CID2 0x5A #define MAX77620_REG_CID3 0x5B -#define MAX77620_REG_CID4 0x5C +#define MAX77620_REG_CID4 0x5C // OTP version. #define MAX77620_REG_CID5 0x5D - -#define MAX77620_REG_DVSSD4 0x5E -#define MAX20024_REG_MAX_ADD 0x70 - -#define MAX77620_CID_DIDM_MASK 0xF0 -#define MAX77620_CID_DIDM_SHIFT 4 - -/* CNCG2SD */ -#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1) -#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2) +#define MAX77620_CID_DIDO_MASK 0xF +#define MAX77620_CID_DIDO_SHIFT 0 +#define MAX77620_CID_DIDM_MASK 0xF0 +#define MAX77620_CID_DIDM_SHIFT 4 /* Device Identification Metal */ #define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) /* Device Indentification OTP */ #define MAX77620_CID5_DIDO(n) ((n) & 0xF) -/* SD CNFG1 */ -#define MAX77620_SD_SR_MASK 0xC0 -#define MAX77620_SD_SR_SHIFT 6 -#define MAX77620_SD_POWER_MODE_MASK 0x30 -#define MAX77620_SD_POWER_MODE_SHIFT 4 -#define MAX77620_SD_CFG1_ADE_MASK BIT(3) -#define MAX77620_SD_CFG1_ADE_DISABLE 0 -#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3) -#define MAX77620_SD_FPWM_MASK 0x04 -#define MAX77620_SD_FPWM_SHIFT 2 -#define MAX77620_SD_FSRADE_MASK 0x01 -#define MAX77620_SD_FSRADE_SHIFT 0 -#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2) -#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 -#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2) -#define MAX20024_SD_CFG1_MPOK_MASK BIT(1) -#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0) -#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 -#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0) +#define MAX77620_REG_DVSSD4 0x5E +#define MAX20024_REG_MAX_ADD 0x70 #define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0) #define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1) @@ -332,9 +377,4 @@ enum max77620_fps_src { MAX77620_FPS_SRC_DEF, }; -enum max77620_chip_id { - MAX77620, - MAX20024, -}; - #endif /* _MFD_MAX77620_H_ */ diff --git a/bdk/power/max7762x.c b/bdk/power/max7762x.c index c32cf76..6a41512 100644 --- a/bdk/power/max7762x.c +++ b/bdk/power/max7762x.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 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, @@ -17,163 +17,322 @@ #include #include +#include +#include #include +#include #include -#define REGULATOR_SD 0 +#define REGULATOR_SD 0 #define REGULATOR_LDO 1 +#define REGULATOR_BC0 2 +#define REGULATOR_BC1 3 -typedef struct _max77620_regulator_t +typedef struct _max77620_fps_t { - u8 type; - const char *name; - u8 reg_sd; - - u32 mv_step; - u32 mv_min; - u32 mv_default; - u32 mv_max; - - u8 volt_addr; - u8 cfg_addr; - - u8 volt_mask; - u8 enable_mask; - u8 enable_shift; - u8 status_mask; - u8 fps_addr; u8 fps_src; u8 pd_period; u8 pu_period; +} max77620_fps_t; + +typedef struct _max77621_ctrl_t +{ + u8 ctrl1_por; + u8 ctrl1_hos; + u8 ctrl2_por; + u8 ctrl2_hos; +} max77621_ctrl_t; + +typedef struct _max77812_ctrl_t +{ + u8 mask; + u8 shift; + u8 rsvd0; + u8 rsvd1; +} max77812_en_t; + +typedef struct _max77620_regulator_t +{ + const char *name; + + u32 uv_step; + u32 uv_min; + u32 uv_default; + u32 uv_max; + + u8 type; + u8 volt_addr; + u8 cfg_addr; + u8 volt_mask; + + union { + max77620_fps_t fps; + max77621_ctrl_t ctrl; + max77812_en_t enable; + }; } max77620_regulator_t; static const max77620_regulator_t _pmic_regulators[] = { - { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x80, MAX77620_REG_FPS_SD0, 1, 7, 1 }, - { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x40, MAX77620_REG_FPS_SD1, 0, 1, 5 }, - { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x20, MAX77620_REG_FPS_SD2, 1, 5, 2 }, - { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x10, MAX77620_REG_FPS_SD3, 0, 3, 3 }, - { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO0, 3, 7, 0 }, - { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO1, 3, 7, 0 }, - { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO2, 3, 7, 0 }, - { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO3, 3, 7, 0 }, - { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO4, 0, 7, 1 }, - { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO5, 3, 7, 0 }, - { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO6, 3, 7, 0 }, - { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO7, 1, 4, 3 }, - { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 2800000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 } + { "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} }, + { "sd1", 12500, 600000, 1125000, 1125000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} }, + { "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} }, + { "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} }, + { "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} }, + { "ldo1", 25000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO1, 3, 7, 0 }} }, + { "ldo2", 50000, 800000, 1800000, 3300000, REGULATOR_LDO, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO2, 3, 7, 0 }} }, + { "ldo3", 50000, 800000, 3100000, 3100000, REGULATOR_LDO, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO3, 3, 7, 0 }} }, + { "ldo4", 12500, 800000, 850000, 1000000, REGULATOR_LDO, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO4, 0, 7, 1 }} }, + { "ldo5", 50000, 800000, 1800000, 1800000, REGULATOR_LDO, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO5, 3, 7, 0 }} }, + { "ldo6", 50000, 800000, 2900000, 2900000, REGULATOR_LDO, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO6, 3, 7, 0 }} }, + { "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} }, + { "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} }, + + { "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, + { "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, + { "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} }, + //{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} }, + //{ "max77812_RAM", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration. }; -static void _max77620_set_reg(u8 reg, u8 val) +static u8 _max77812_get_address() +{ + static u8 max77812_i2c_addr = 0; + + if (max77812_i2c_addr) + return max77812_i2c_addr; + + max77812_i2c_addr = + !(FUSE(FUSE_RESERVED_ODM28_T210B01) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR; + + return max77812_i2c_addr; +} + +static u8 _max7762x_get_i2c_address(u32 id) +{ + const max77620_regulator_t *reg = &_pmic_regulators[id]; + + // Choose the correct i2c address. + switch (reg->type) + { + case REGULATOR_SD: + case REGULATOR_LDO: + return MAX77620_I2C_ADDR; + case REGULATOR_BC0: + return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR); + case REGULATOR_BC1: + return _max77812_get_address(); + default: + return 0; + } +} + +static void _max7762x_set_reg(u8 addr, u8 reg, u8 val) { u32 retries = 100; while (retries) { - if (i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val)) + if (i2c_send_byte(I2C_5, addr, reg, val)) break; - usleep(100); + + usleep(50); retries--; } } int max77620_regulator_get_status(u32 id) { - if (id > REGULATOR_MAX) + if (id > REGULATOR_LDO8) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; + // SD power OK status. if (reg->type == REGULATOR_SD) - return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1; - return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & 8) ? 1 : 0; + { + u8 mask = 1u << (7 - id); + return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & mask) ? 0 : 1; + } + + // LDO power OK status. + return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & MAX77620_LDO_CFG2_POK_MASK) ? 1 : 0; } int max77620_regulator_config_fps(u32 id) { - if (id > REGULATOR_MAX) + if (id > REGULATOR_LDO8) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; - _max77620_set_reg(reg->fps_addr, - (reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period)); + // Set FPS configuration. + _max7762x_set_reg(MAX77620_I2C_ADDR, + reg->fps.fps_addr, + (reg->fps.fps_src << MAX77620_FPS_SRC_SHIFT) | + (reg->fps.pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | + (reg->fps.pd_period << MAX77620_FPS_PD_PERIOD_SHIFT)); return 1; } -int max77620_regulator_set_voltage(u32 id, u32 mv) +int max7762x_regulator_set_voltage(u32 id, u32 mv) { if (id > REGULATOR_MAX) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; - if (mv < reg->mv_min || mv > reg->mv_max) + if (mv < reg->uv_min || mv > reg->uv_max) return 0; - u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; - u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr); + u8 addr = _max7762x_get_i2c_address(id); + + // Calculate voltage multiplier. + u32 mult = (mv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step; + u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr); val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); - _max77620_set_reg(reg->volt_addr, val); + + // Set voltage. + _max7762x_set_reg(addr, reg->volt_addr, val); + + // If max77621 set DVS voltage also. + if (reg->type == REGULATOR_BC0) + _max7762x_set_reg(addr, reg->cfg_addr, MAX77621_VOUT_ENABLE_MASK | val); + + // Wait for ramp up/down delay. usleep(1000); return 1; } -int max77620_regulator_enable(u32 id, int enable) +int max7762x_regulator_enable(u32 id, bool enable) { + u8 reg_addr; + u8 enable_val; + u8 enable_mask; + u8 enable_shift; + if (id > REGULATOR_MAX) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; - u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr; - u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, addr); + // Choose the correct i2c and register addresses and mask/shift for each type. + switch (reg->type) + { + case REGULATOR_SD: + reg_addr = reg->cfg_addr; + enable_val = MAX77620_POWER_MODE_NORMAL; + enable_mask = MAX77620_SD_POWER_MODE_MASK; + enable_shift = MAX77620_SD_POWER_MODE_SHIFT; + break; + case REGULATOR_LDO: + reg_addr = reg->volt_addr; + enable_val = MAX77620_POWER_MODE_NORMAL; + enable_mask = MAX77620_LDO_POWER_MODE_MASK; + enable_shift = MAX77620_LDO_POWER_MODE_SHIFT; + break; + case REGULATOR_BC0: + reg_addr = reg->volt_addr; + enable_val = MAX77621_VOUT_ENABLE; + enable_mask = MAX77621_DVC_DVS_ENABLE_MASK; + enable_shift = MAX77621_DVC_DVS_ENABLE_SHIFT; + break; + case REGULATOR_BC1: + reg_addr = reg->cfg_addr; + enable_val = MAX77812_EN_CTRL_ENABLE; + enable_mask = reg->enable.mask; + enable_shift = reg->enable.shift; + break; + default: + return 0; + } + + u8 addr = _max7762x_get_i2c_address(id); + + // Read and enable/disable. + u8 val = i2c_recv_byte(I2C_5, addr, reg_addr); + val &= ~enable_mask; + if (enable) - val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask); - else - val &= ~reg->enable_mask; - _max77620_set_reg(addr, val); + val |= (enable_val << enable_shift); + + // Set enable. + _max7762x_set_reg(addr, reg_addr, val); + + // Wait for enable/disable ramp delay. usleep(1000); return 1; } -// LDO only. -int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags) +void max77620_config_gpio(u32 gpio_id, bool enable) { - if (id > REGULATOR_MAX) - return 0; + if (gpio_id > 7) + return; + // Configure as standard GPIO. + u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, val & ~BIT(gpio_id)); + + // Set GPIO configuration. + if (enable) + val = MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DIR_OUTPUT | MAX77620_CNFG_GPIO_DRV_PUSHPULL; + else + val = MAX77620_CNFG_GPIO_DIR_INPUT | MAX77620_CNFG_GPIO_DRV_OPENDRAIN; + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO0 + gpio_id, val); +} + +void max77621_config_default(u32 id, bool por) +{ const max77620_regulator_t *reg = &_pmic_regulators[id]; - if (mv < reg->mv_min || mv > reg->mv_max) - return 0; + if (reg->type != REGULATOR_BC0) + return; - u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; - u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask); - _max77620_set_reg(reg->volt_addr, val); - usleep(1000); + u8 addr = _max7762x_get_i2c_address(id); - return 1; + if (por) + { + // Set voltage and disable power before changing the inductor. + max7762x_regulator_set_voltage(id, 1000000); + max7762x_regulator_enable(id, false); + + // Configure to default. + i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_por); + i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_por); + } + else + { + i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_hos); + i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_hos); + } } void max77620_config_default() { - for (u32 i = 1; i <= REGULATOR_MAX; i++) + // Check if Erista OTP. + if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4) != 0x35) + return; + + // Set default voltages and enable regulators. + for (u32 i = 1; i <= REGULATOR_LDO8; i++) { - i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4); max77620_regulator_config_fps(i); - max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); - if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) - max77620_regulator_enable(i, 1); + max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default); + if (_pmic_regulators[i].fps.fps_src != MAX77620_FPS_SRC_NONE) + max7762x_regulator_enable(i, true); } - _max77620_set_reg(MAX77620_REG_SD_CFG2, 4); + + // Enable SD0 output voltage sense and disable for SD1. Additionally disable the reserved bit. + _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0); } void max77620_low_battery_monitor_config(bool enable) { - _max77620_set_reg(MAX77620_REG_CNFGGLBL1, - MAX77620_CNFGGLBL1_LBDAC_EN | (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) | - MAX77620_CNFGGLBL1_LBHYST_200 | MAX77620_CNFGGLBL1_LBDAC_2800); + _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1, + MAX77620_CNFGGLBL1_LBDAC_EN | + (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) | + MAX77620_CNFGGLBL1_LBHYST_200 | + MAX77620_CNFGGLBL1_LBDAC_2800); } diff --git a/bdk/power/max7762x.h b/bdk/power/max7762x.h index dd06bf7..8261336 100644 --- a/bdk/power/max7762x.h +++ b/bdk/power/max7762x.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 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, @@ -45,10 +45,10 @@ */ /*! MAX77620 partitions. */ -#define REGULATOR_SD0 0 -#define REGULATOR_SD1 1 -#define REGULATOR_SD2 2 -#define REGULATOR_SD3 3 +#define REGULATOR_SD0 0 +#define REGULATOR_SD1 1 +#define REGULATOR_SD2 2 +#define REGULATOR_SD3 3 #define REGULATOR_LDO0 4 #define REGULATOR_LDO1 5 #define REGULATOR_LDO2 6 @@ -58,26 +58,40 @@ #define REGULATOR_LDO6 10 #define REGULATOR_LDO7 11 #define REGULATOR_LDO8 12 -#define REGULATOR_MAX 12 +#define REGULATOR_CPU0 13 +#define REGULATOR_GPU0 14 +#define REGULATOR_CPU1 15 +//#define REGULATOR_GPU1 16 +//#define REGULATOR_GPU1 17 +#define REGULATOR_MAX 15 #define MAX77621_CPU_I2C_ADDR 0x1B #define MAX77621_GPU_I2C_ADDR 0x1C -#define MAX77621_VOUT_REG 0 -#define MAX77621_VOUT_DVS_REG 1 -#define MAX77621_CONTROL1_REG 2 -#define MAX77621_CONTROL2_REG 3 - -/* MAX77621_VOUT */ -#define MAX77621_VOUT_ENABLE BIT(7) -#define MAX77621_VOUT_MASK 0x7F -#define MAX77621_VOUT_0_95V 0x37 -#define MAX77621_VOUT_1_09V 0x4F +#define MAX77621_VOUT_REG 0x00 +#define MAX77621_VOUT_DVS_REG 0x01 +#define MAX77621_CONTROL1_REG 0x02 +#define MAX77621_CONTROL2_REG 0x03 +#define MAX77621_CHIPID1_REG 0x04 +#define MAX77621_CHIPID2_REG 0x05 /* MAX77621_VOUT_DVC_DVS */ -#define MAX77621_DVS_VOUT_MASK 0x7F +#define MAX77621_DVC_DVS_VOLT_MASK 0x7F +#define MAX77621_DVC_DVS_ENABLE_SHIFT 7 +#define MAX77621_DVC_DVS_ENABLE_MASK (1 << MAX77621_DVC_DVS_ENABLE_SHIFT) + +/* MAX77621_VOUT */ +#define MAX77621_VOUT_DISABLE 0 +#define MAX77621_VOUT_ENABLE 1 +#define MAX77621_VOUT_ENABLE_MASK (MAX77621_VOUT_ENABLE << MAX77621_DVC_DVS_ENABLE_SHIFT) /* MAX77621_CONTROL1 */ +#define MAX77621_RAMP_12mV_PER_US 0x0 +#define MAX77621_RAMP_25mV_PER_US 0x1 +#define MAX77621_RAMP_50mV_PER_US 0x2 +#define MAX77621_RAMP_200mV_PER_US 0x3 +#define MAX77621_RAMP_MASK 0x3 + #define MAX77621_FREQSHIFT_9PER BIT(2) #define MAX77621_BIAS_ENABLE BIT(3) #define MAX77621_AD_ENABLE BIT(4) @@ -85,34 +99,50 @@ #define MAX77621_FPWM_EN_M BIT(6) #define MAX77621_SNS_ENABLE BIT(7) -#define MAX77621_RAMP_12mV_PER_US 0x0 -#define MAX77621_RAMP_25mV_PER_US 0x1 -#define MAX77621_RAMP_50mV_PER_US 0x2 -#define MAX77621_RAMP_200mV_PER_US 0x3 -#define MAX77621_RAMP_MASK 0x3 - /* MAX77621_CONTROL2 */ -#define MAX77621_FT_ENABLE BIT(4) -#define MAX77621_DISCH_ENBABLE BIT(5) -#define MAX77621_WDTMR_ENABLE BIT(6) -#define MAX77621_T_JUNCTION_120 BIT(7) +#define MAX77621_INDUCTOR_MIN_30_PER 0 +#define MAX77621_INDUCTOR_NOMINAL 1 +#define MAX77621_INDUCTOR_PLUS_30_PER 2 +#define MAX77621_INDUCTOR_PLUS_60_PER 3 +#define MAX77621_INDUCTOR_MASK 3 -#define MAX77621_CKKADV_TRIP_DISABLE 0xC #define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0 -#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4 -#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8 +#define MAX77621_CKKADV_TRIP_150mV_PER_US BIT(2) +#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS BIT(3) +#define MAX77621_CKKADV_TRIP_DISABLE (BIT(2) | BIT(3)) +#define MAX77621_CKKADV_TRIP_MASK (BIT(2) | BIT(3)) -#define MAX77621_INDUCTOR_MIN_30_PER 0x0 -#define MAX77621_INDUCTOR_NOMINAL 0x1 -#define MAX77621_INDUCTOR_PLUS_30_PER 0x2 -#define MAX77621_INDUCTOR_PLUS_60_PER 0x3 +#define MAX77621_FT_ENABLE BIT(4) +#define MAX77621_DISCH_ENABLE BIT(5) +#define MAX77621_WDTMR_ENABLE BIT(6) +#define MAX77621_T_JUNCTION_120 BIT(7) + +#define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US) +#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \ + MAX77621_NFSR_ENABLE | \ + MAX77621_SNS_ENABLE | \ + MAX77621_RAMP_12mV_PER_US) +#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \ + MAX77621_FT_ENABLE | \ + MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | \ + MAX77621_CKKADV_TRIP_150mV_PER_US | \ + MAX77621_INDUCTOR_NOMINAL) +#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \ + MAX77621_WDTMR_ENABLE | \ + MAX77621_CKKADV_TRIP_75mV_PER_US | \ + MAX77621_INDUCTOR_NOMINAL) + +#define MAX77621_CTRL_HOS_CFG 0 +#define MAX77621_CTRL_POR_CFG 1 int max77620_regulator_get_status(u32 id); int max77620_regulator_config_fps(u32 id); -int max77620_regulator_set_voltage(u32 id, u32 mv); -int max77620_regulator_enable(u32 id, int enable); -int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags); +int max7762x_regulator_set_voltage(u32 id, u32 mv); +int max7762x_regulator_enable(u32 id, bool enable); +void max77620_config_gpio(u32 id, bool enable); void max77620_config_default(); void max77620_low_battery_monitor_config(bool enable); +void max77621_config_default(u32 id, bool por); + #endif diff --git a/bdk/power/max77812.h b/bdk/power/max77812.h index f8ac3fb..89c3baf 100644 --- a/bdk/power/max77812.h +++ b/bdk/power/max77812.h @@ -17,8 +17,8 @@ #ifndef _MAX77812_H_ #define _MAX77812_H_ -#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 -#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 +#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // 2 Outputs: 3-phase M1 + 1-phase M4. +#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4. #define MAX77812_REG_RSET 0x00 #define MAX77812_REG_INT_SRC 0x01 @@ -27,7 +27,15 @@ #define MAX77812_REG_TOPSYS_INT_M 0x04 #define MAX77812_REG_TOPSYS_STAT 0x05 #define MAX77812_REG_EN_CTRL 0x06 -#define MAX77812_EN_CTRL_EN_M4 BIT(6) +#define MAX77812_EN_CTRL_ENABLE 1 +#define MAX77812_EN_CTRL_EN_M1_SHIFT 0 +#define MAX77812_EN_CTRL_EN_M1_MASK (1 << MAX77812_EN_CTRL_EN_M1_SHIFT) +#define MAX77812_EN_CTRL_EN_M2_SHIFT 2 +#define MAX77812_EN_CTRL_EN_M2_MASK (1 << MAX77812_EN_CTRL_EN_M2_SHIFT) +#define MAX77812_EN_CTRL_EN_M3_SHIFT 4 +#define MAX77812_EN_CTRL_EN_M3_MASK (1 << MAX77812_EN_CTRL_EN_M3_SHIFT) +#define MAX77812_EN_CTRL_EN_M4_SHIFT 6 +#define MAX77812_EN_CTRL_EN_M4_MASK (1 << MAX77812_EN_CTRL_EN_M4_SHIFT) #define MAX77812_REG_STUP_DLY2 0x07 #define MAX77812_REG_STUP_DLY3 0x08 #define MAX77812_REG_STUP_DLY4 0x09 @@ -46,11 +54,10 @@ #define MAX77812_REG_BUCK_INT 0x20 #define MAX77812_REG_BUCK_INT_M 0x21 #define MAX77812_REG_BUCK_STAT 0x22 -#define MAX77812_REG_M1_VOUT 0x23 +#define MAX77812_REG_M1_VOUT 0x23 // GPU. #define MAX77812_REG_M2_VOUT 0x24 -#define MAX77812_REG_M3_VOUT 0x25 -#define MAX77812_REG_M4_VOUT 0x26 -#define MAX77812_M4_VOUT_0_80V 0x6E +#define MAX77812_REG_M3_VOUT 0x25 // DRAM on PHASE211. +#define MAX77812_REG_M4_VOUT 0x26 // CPU. #define MAX77812_REG_M1_VOUT_D 0x27 #define MAX77812_REG_M2_VOUT_D 0x28 #define MAX77812_REG_M3_VOUT_D 0x29 @@ -66,6 +73,8 @@ #define MAX77812_REG_GLB_CFG1 0x33 #define MAX77812_REG_GLB_CFG2 0x34 #define MAX77812_REG_GLB_CFG3 0x35 + +/*! Protected area and settings only for MAX77812_REG_VERSION 4 */ #define MAX77812_REG_GLB_CFG4 0x36 #define MAX77812_REG_GLB_CFG5 0x37 #define MAX77812_REG_GLB_CFG6 0x38 @@ -91,10 +100,6 @@ #define MAX77812_ES2_VERSION 0x04 #define MAX77812_QS_VERSION 0x05 -#define MAX77812_VOUT_MASK 0xFF -#define MAX77812_VOUT_N_VOLTAGE 0xFF -#define MAX77812_VOUT_VMIN 250000 -#define MAX77812_VOUT_VMAX 1525000 -#define MAX77812_VOUT_STEP 5000 +#define MAX77812_BUCK_VOLT_MASK 0xFF #endif diff --git a/bdk/power/regulator_5v.c b/bdk/power/regulator_5v.c index c61db64..31d32f6 100644 --- a/bdk/power/regulator_5v.c +++ b/bdk/power/regulator_5v.c @@ -21,8 +21,9 @@ #include static u8 reg_5v_dev = 0; +static bool batt_src = false; -void regulator_enable_5v(u8 dev) +void regulator_5v_enable(u8 dev) { // The power supply selection from battery or USB is automatic. if (!reg_5v_dev) @@ -32,6 +33,7 @@ void regulator_enable_5v(u8 dev) gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO); gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE); gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); + batt_src = true; // Fan and Rail power from USB 5V VDD. PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1; @@ -47,7 +49,7 @@ void regulator_enable_5v(u8 dev) reg_5v_dev |= dev; } -void regulator_disable_5v(u8 dev) +void regulator_5v_disable(u8 dev) { reg_5v_dev &= ~dev; @@ -58,6 +60,7 @@ void regulator_disable_5v(u8 dev) gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE); gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO); PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE; + batt_src = false; // Rail power from USB 5V VDD. gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); @@ -70,7 +73,15 @@ void regulator_disable_5v(u8 dev) } } -bool regulator_get_5v_dev_enabled(u8 dev) +bool regulator_5v_get_dev_enabled(u8 dev) { return (reg_5v_dev & dev); } + +void regulator_5v_batt_src_enable(bool enable) +{ + if (enable && !batt_src) + gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); + else if (!enable && batt_src) + gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW); +} diff --git a/bdk/power/regulator_5v.h b/bdk/power/regulator_5v.h index 6bb837a..b7d7490 100644 --- a/bdk/power/regulator_5v.h +++ b/bdk/power/regulator_5v.h @@ -27,8 +27,9 @@ enum REGULATOR_5V_ALL = 0xFF }; -void regulator_enable_5v(u8 dev); -void regulator_disable_5v(u8 dev); -bool regulator_get_5v_dev_enabled(u8 dev); +void regulator_5v_enable(u8 dev); +void regulator_5v_disable(u8 dev); +bool regulator_5v_get_dev_enabled(u8 dev); +void regulator_5v_batt_src_enable(bool enable); #endif \ No newline at end of file diff --git a/bdk/soc/ccplex.c b/bdk/soc/ccplex.c index a8d782d..894cb28 100644 --- a/bdk/soc/ccplex.c +++ b/bdk/soc/ccplex.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include @@ -29,27 +28,24 @@ void _ccplex_enable_power_t210() { - u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); // Get current pinmuxing - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~BIT(5)); // Disable GPIO5 pinmuxing. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH); + // Configure GPIO5 and enable output in order to power CPU pmic. + max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_ENABLE); - // Enable cores power. + // Configure CPU pmic. // 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_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 | MAX77621_VOUT_0_95V); - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V); + max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_HOS_CFG); + + // Set voltage and enable cores power. + max7762x_regulator_set_voltage(REGULATOR_CPU0, 950000); + max7762x_regulator_enable(REGULATOR_CPU0, true); } void _ccplex_enable_power_t210b01() { - u8 pmic_cpu_addr = !(FUSE(FUSE_RESERVED_ODM28) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR; - u8 tmp = i2c_recv_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL); - i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL, tmp | MAX77812_EN_CTRL_EN_M4); - i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_M4_VOUT, MAX77812_M4_VOUT_0_80V); + // Set voltage and enable cores power. + max7762x_regulator_set_voltage(REGULATOR_CPU1, 800000); + max7762x_regulator_enable(REGULATOR_CPU1, true); } void ccplex_boot_cpu0(u32 entry) @@ -62,24 +58,31 @@ void ccplex_boot_cpu0(u32 entry) else _ccplex_enable_power_t210b01(); - if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE. + // Enable PLLX and set it to 300 MHz. + if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE. { CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ. usleep(2); - CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02; - CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02; + + // Bypass dividers. + CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | (4 << 20) | (78 << 8) | 2; // P div: 4 (5), N div: 78, M div: 2. + // Disable bypass + CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = (4 << 20) | (78 << 8) | 2; + // Set PLLX_LOCK_ENABLE. CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000; - CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02; + // Enable PLLX. + CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | (4 << 20) | (78 << 8) | 2; } - while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000)) + // Wait for PLL to stabilize. + while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK)) ; - // Configure MSELECT source and enable clock. + // Configure MSELECT source and enable clock to 102MHz. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6; - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & ~BIT(CLK_V_MSELECT)) | BIT(CLK_V_MSELECT); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT); // Configure initial CPU clock frequency and enable clock. - CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; + CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ. CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG); @@ -88,12 +91,12 @@ void ccplex_boot_cpu0(u32 entry) // CAR2PMC_CPU_ACK_WIDTH should be set to 0. CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000; - // Enable CPU rail. - pmc_enable_partition(0, 1); + // Enable CPU main rail. + pmc_enable_partition(POWER_RAIL_CRAIL, ENABLE); // Enable cluster 0 non-CPU rail. - pmc_enable_partition(15, 1); - // Enable CE0 rail. - pmc_enable_partition(14, 1); + pmc_enable_partition(POWER_RAIL_C0NC, ENABLE); + // Enable CPU0 rail. + pmc_enable_partition(POWER_RAIL_CE0, ENABLE); // Request and wait for RAM repair. FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; @@ -113,7 +116,7 @@ void ccplex_boot_cpu0(u32 entry) // MC(MC_TZ_SECURITY_CTRL) = 1; // Clear MSELECT reset. - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= ~BIT(CLK_V_MSELECT); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT); // Clear NONCPU reset. CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000; // Clear CPU0 reset. diff --git a/bdk/soc/clock.c b/bdk/soc/clock.c index cf0007e..31bdb8f 100644 --- a/bdk/soc/clock.c +++ b/bdk/soc/clock.c @@ -21,6 +21,23 @@ #include #include +typedef struct _clock_osc_t +{ + u32 freq; + u16 min; + u16 max; +} clock_osc_t; + +static const clock_osc_t _clock_osc_cnt[] = { + { 12000, 706, 757 }, + { 13000, 766, 820 }, + { 16800, 991, 1059 }, + { 19200, 1133, 1210 }, + { 26000, 1535, 1638 }, + { 38400, 2268, 2418 }, + { 48000, 2836, 3023 } +}; + /* clock_t: reset, enable, source, index, clk_src, clk_div */ static const clock_t _clock_uart[] = { @@ -42,7 +59,7 @@ static const clock_t _clock_i2c[] = { }; static clock_t _clock_se = { - CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz. }; static clock_t _clock_tzram = { @@ -50,19 +67,19 @@ static clock_t _clock_tzram = { }; static clock_t _clock_host1x = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz. }; static clock_t _clock_tsec = { - CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 + CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz. }; static clock_t _clock_sor_safe = { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0 }; static clock_t _clock_sor0 = { - CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, CLK_X_SOR0, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 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, CLK_X_SOR1, 0, 2 + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 //204MHz. }; static clock_t _clock_kfuse = { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0 @@ -72,11 +89,11 @@ static clock_t _clock_cl_dvfs = { CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 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, CLK_U_CSITE, 0, 4 + CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz. }; static clock_t _clock_pwm = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. Stock PLLP / 54: 7.55MHz. + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz. }; static clock_t _clock_sdmmc_legacy_tm = { @@ -218,13 +235,13 @@ void clock_disable_sor1() void clock_enable_kfuse() { - u32 kfuse_clk_unmask = ~BIT(CLK_H_KFUSE); - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE); - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= kfuse_clk_unmask; - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE); - usleep(10); - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= kfuse_clk_unmask; - usleep(20); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_KFUSE); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_KFUSE); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_KFUSE); + usleep(10); // Wait 10s to prevent glitching. + + CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_KFUSE); + usleep(20); // Wait 20s fo kfuse hw to init. } void clock_disable_kfuse() @@ -721,3 +738,44 @@ void clock_sdmmc_disable(u32 id) _clock_sdmmc_is_reset(id); _clock_disable_pllc4(BIT(id)); } + +u32 clock_get_osc_freq() +{ + CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = OSC_FREQ_DET_TRIG | (2 - 1); // 2 periods of 32.76KHz window. + while (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY) + ; + u32 cnt = (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_CNT); + CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = 0; + + // Return frequency in KHz. + for (u32 i = 0; i < ARRAY_SIZE(_clock_osc_cnt); i++) + if (cnt >= _clock_osc_cnt[i].min && cnt <= _clock_osc_cnt[i].max) + return _clock_osc_cnt[i].freq; + + return 0; +} + +u32 clock_get_dev_freq(clock_pto_id_t id) +{ + u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (16 - 1); // 16 periods of 32.76KHz window. + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val; + usleep(2); + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST; + usleep(2); + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val; + usleep(2); + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN; + usleep(502); + + while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY) + ; + + u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT; + + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0; + + u32 freq = ((cnt << 8) | 0x3E) / 125; + + return freq; +} + diff --git a/bdk/soc/clock.h b/bdk/soc/clock.h index 2f6de41..67e9b4d 100644 --- a/bdk/soc/clock.h +++ b/bdk/soc/clock.h @@ -35,6 +35,10 @@ #define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 #define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 #define CLK_RST_CONTROLLER_OSC_CTRL 0x50 +#define CLK_RST_CONTROLLER_OSC_FREQ_DET 0x58 +#define CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS 0x5C +#define CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL 0x60 +#define CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS 0x64 #define CLK_RST_CONTROLLER_PLLC_BASE 0x80 #define CLK_RST_CONTROLLER_PLLC_OUT 0x84 #define CLK_RST_CONTROLLER_PLLC_MISC 0x88 @@ -156,11 +160,18 @@ #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710 #define CLK_NO_SOURCE 0x0 +#define CLK_NOT_USED 0x0 /*! PLL control and status bits */ +#define PLLX_BASE_LOCK BIT(27) +#define PLLX_BASE_REF_DIS BIT(29) +#define PLLX_BASE_ENABLE BIT(30) +#define PLLX_BASE_BYPASS BIT(31) + #define PLLCX_BASE_LOCK BIT(27) #define PLLCX_BASE_REF_DIS BIT(29) #define PLLCX_BASE_ENABLE BIT(30) +#define PLLCX_BASE_BYPASS BIT(31) #define PLLA_OUT0_RSTN_CLR BIT(0) #define PLLA_OUT0_CLKEN BIT(1) @@ -178,6 +189,140 @@ #define UTMIPLL_LOCK BIT(31) +/*! PTO_CLK_CNT */ +#define PTO_REF_CLK_WIN_CFG_MASK 0xF +#define PTO_REF_CLK_WIN_CFG_16P 0xF +#define PTO_CNT_EN BIT(9) +#define PTO_CNT_RST BIT(10) +#define PTO_CLK_ENABLE BIT(13) +#define PTO_SRC_SEL_SHIFT 14 +#define PTO_SRC_SEL_MASK 0x1FF +#define PTO_DIV_SEL_MASK (3 << 23) +#define PTO_DIV_SEL_GATED (0 << 23) +#define PTO_DIV_SEL_DIV1 (1 << 23) +#define PTO_DIV_SEL_DIV2_RISING (2 << 23) +#define PTO_DIV_SEL_DIV2_FALLING (3 << 23) +#define PTO_DIV_SEL_CPU_EARLY (0 << 23) +#define PTO_DIV_SEL_CPU_LATE (1 << 23) + +#define PTO_CLK_CNT_BUSY BIT(31) +#define PTO_CLK_CNT 0xFFFFFF + +/*! OSC_FREQ_DET */ +#define OSC_REF_CLK_WIN_CFG_MASK 0xF +#define OSC_FREQ_DET_TRIG BIT(31) + +#define OSC_FREQ_DET_BUSY BIT(31) +#define OSC_FREQ_DET_CNT 0xFFFF + +/*! PLLs omitted as they need PTO enabled in MISC registers. Norm div is 2. */ +typedef enum _clock_pto_id_t +{ + CLK_PTO_PCLK_SYS = 0x06, + CLK_PTO_HCLK_SYS = 0x07, + + CLK_PTO_UTMIP_240 = 0x0C, + + CLK_PTO_CCLK_G = 0x12, + CLK_PTO_CCLK_G_DIV2 = 0x13, + + CLK_PTO_SPI1 = 0x17, + CLK_PTO_SPI2 = 0x18, + CLK_PTO_SPI3 = 0x19, + CLK_PTO_SPI4 = 0x1A, + CLK_PTO_MAUD = 0x1B, + CLK_PTO_SCLK = 0x1C, + + CLK_PTO_SDMMC1 = 0x20, + CLK_PTO_SDMMC2 = 0x21, + CLK_PTO_SDMMC3 = 0x22, + CLK_PTO_SDMMC4 = 0x23, + CLK_PTO_EMC = 0x24, + + CLK_PTO_MSELECT = 0x2F, + + CLK_PTO_VIC = 0x36, + + CLK_PTO_NVDEC = 0x39, + + CLK_PTO_NVENC = 0x3A, + CLK_PTO_NVJPG = 0x3B, + CLK_PTO_TSEC = 0x3C, + CLK_PTO_TSECB = 0x3D, + CLK_PTO_SE = 0x3E, + + CLK_PTO_DSIA_LP = 0x62, + + CLK_PTO_ISP = 0x64, + CLK_PTO_MC = 0x6A, + + CLK_PTO_ACTMON = 0x6B, + CLK_PTO_CSITE = 0x6C, + + CLK_PTO_HOST1X = 0x6F, + + CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE. + CLK_PTO_SOC_THERM = 0x75, + + CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC. + + CLK_PTO_ACLK = 0x7C, + CLK_PTO_QSPI = 0x7D, + + CLK_PTO_I2S1 = 0x80, + CLK_PTO_I2S2 = 0x81, + CLK_PTO_I2S3 = 0x82, + CLK_PTO_I2S4 = 0x83, + CLK_PTO_I2S5 = 0x84, + CLK_PTO_AHUB = 0x85, + CLK_PTO_APE = 0x86, + + CLK_PTO_DVFS_SOC = 0x88, + CLK_PTO_DVFS_REF = 0x89, + + CLK_PTO_SPDIF = 0x8F, + CLK_PTO_SPDIF_IN = 0x90, + CLK_PTO_UART_FST_MIPI_CAL = 0x91, + + CLK_PTO_PWM = 0x93, + CLK_PTO_I2C1 = 0x94, + CLK_PTO_I2C2 = 0x95, + CLK_PTO_I2C3 = 0x96, + CLK_PTO_I2C4 = 0x97, + CLK_PTO_I2C5 = 0x98, + CLK_PTO_I2C6 = 0x99, + CLK_PTO_I2C_SLOW = 0x9A, + CLK_PTO_UARTAPE = 0x9B, + + CLK_PTO_EXTPERIPH1 = 0x9D, + CLK_PTO_EXTPERIPH2 = 0x9E, + + CLK_PTO_ENTROPY = 0xA0, + CLK_PTO_UARTA = 0xA1, + CLK_PTO_UARTB = 0xA2, + CLK_PTO_UARTC = 0xA3, + CLK_PTO_UARTD = 0xA4, + CLK_PTO_OWR = 0xA5, + + CLK_PTO_HDA2CODEC_2X = 0xA7, + CLK_PTO_HDA = 0xA8, + + CLK_PTO_SDMMC_LEGACY_TM = 0xAB, + + CLK_PTO_SOR0 = 0xC0, + CLK_PTO_SOR1 = 0xC1, + + CLK_PTO_DISP2 = 0xC4, + CLK_PTO_DISP1 = 0xC5, + + CLK_PTO_XUSB_FALCON = 0x110, + + CLK_PTO_XUSB_FS = 0x136, + CLK_PTO_XUSB_SS_HOST_DEV = 0x137, + CLK_PTO_XUSB_CORE_HOST = 0x138, + CLK_PTO_XUSB_CORE_DEV = 0x139, +} clock_pto_id_t; + /* * CLOCK Peripherals: * L 0 - 31 @@ -216,7 +361,7 @@ enum CLK_L_DEV CLK_L_USBD = 22, CLK_L_ISP = 23, CLK_L_3D = 24, // HIDDEN. - //CLK_L_ = 25, + CLK_L_IDE = 25, // RESERVED. CLK_L_DISP2 = 26, CLK_L_DISP1 = 27, CLK_L_HOST1X = 28, @@ -244,11 +389,11 @@ enum CLK_H_DEV CLK_H_SPI3 = 14, CLK_H_I2C5 = 15, CLK_H_DSI = 16, - //CLK_H_ = 17, + CLK_H_TVO = 17, // RESERVED. CLK_H_HSI = 18, // HIDDEN. CLK_H_HDMI = 19, // HIDDEN. CLK_H_CSI = 20, - //CLK_H_ = 21, + CLK_H_TVDAC = 21, // RESERVED. CLK_H_I2C2 = 22, CLK_H_UARTC = 23, CLK_H_MIPI_CAL = 24, @@ -263,14 +408,14 @@ enum CLK_H_DEV enum CLK_U_DEV { - //CLK_U_ = 0, + CLK_U_SPEEDO = 0, // RESERVED. CLK_U_UARTD = 1, CLK_U_UARTE = 2, // HIDDEN. CLK_U_I2C3 = 3, CLK_U_SPI4 = 4, CLK_U_SDMMC3 = 5, CLK_U_PCIE = 6, - CLK_U_UNUSED = 7, // RESERVED + CLK_U_OWR = 7, // RESERVED. CLK_U_AFI = 8, CLK_U_CSITE = 9, CLK_U_PCIEXCLK = 10, // Only reset. @@ -444,9 +589,9 @@ enum CLK_Y_DEV /*! Generic clock descriptor. */ typedef struct _clock_t { - u32 reset; - u32 enable; - u32 source; + u16 reset; + u16 enable; + u16 source; u8 index; u8 clk_src; u8 clk_div; @@ -494,4 +639,7 @@ int clock_sdmmc_is_not_reset_and_enabled(u32 id); void clock_sdmmc_enable(u32 id, u32 val); void clock_sdmmc_disable(u32 id); +u32 clock_get_osc_freq(); +u32 clock_get_dev_freq(clock_pto_id_t id); + #endif diff --git a/bdk/soc/fuse.c b/bdk/soc/fuse.c index 62dba31..0a37a4b 100644 --- a/bdk/soc/fuse.c +++ b/bdk/soc/fuse.c @@ -2,7 +2,7 @@ * Copyright (c) 2018 naehrwert * Copyright (c) 2018 shuffle2 * Copyright (c) 2018 balika011 - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 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, @@ -76,6 +76,35 @@ u32 fuse_read_odm_keygen_rev() return 0; } +u32 fuse_read_dramid(bool raw_id) +{ + u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3; + + if (raw_id) + return dramid; + + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + { + if (dramid > 6) + dramid = 0; + } + else + { + if (dramid > 27) + dramid = 8; + } + + return dramid; +} + +u32 fuse_read_hw_state() +{ + if ((fuse_read_odm(4) & 3) != 3) + return FUSE_NX_HW_STATE_PROD; + else + return FUSE_NX_HW_STATE_DEV; +} + u32 fuse_read_hw_type() { if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) @@ -118,6 +147,7 @@ u32 fuse_read(u32 addr) FUSE(FUSE_ADDR) = addr; FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ; fuse_wait_idle(); + return FUSE(FUSE_RDATA); } diff --git a/bdk/soc/fuse.h b/bdk/soc/fuse.h index d7d5c77..810efd6 100644 --- a/bdk/soc/fuse.h +++ b/bdk/soc/fuse.h @@ -2,6 +2,7 @@ * Copyright (c) 2018 naehrwert * Copyright (c) 2018 shuffle2 * Copyright (c) 2018 balika011 + * Copyright (c) 2019-2020 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, @@ -64,9 +65,10 @@ #define FUSE_OPT_X_COORDINATE 0x214 #define FUSE_OPT_Y_COORDINATE 0x218 #define FUSE_GPU_IDDQ_CALIB 0x228 -#define FUSE_RESERVED_ODM28 0x240 #define FUSE_USB_CALIB_EXT 0x350 +#define FUSE_RESERVED_ODM28_T210B01 0x240 + /*! Fuse commands. */ #define FUSE_READ 0x1 #define FUSE_WRITE 0x2 @@ -83,9 +85,17 @@ enum FUSE_NX_HW_TYPE_HOAG }; +enum +{ + FUSE_NX_HW_STATE_PROD, + FUSE_NX_HW_STATE_DEV +}; + void fuse_disable_program(); u32 fuse_read_odm(u32 idx); u32 fuse_read_odm_keygen_rev(); +u32 fuse_read_dramid(bool raw_id); +u32 fuse_read_hw_state(); u32 fuse_read_hw_type(); u8 fuse_count_burnt(u32 val); void fuse_wait_idle(); diff --git a/bdk/soc/hw_init.c b/bdk/soc/hw_init.c index dd79dc6..5c81b1a 100644 --- a/bdk/soc/hw_init.c +++ b/bdk/soc/hw_init.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -285,17 +285,21 @@ static void _config_se_brom() static void _config_regulators(bool tegra_t210) { + // Set RTC/AO domain to POR voltage. + if (tegra_t210) + max7762x_regulator_set_voltage(REGULATOR_LDO4, 1000000); + // Disable low battery shutdown monitor. max77620_low_battery_monitor_config(false); // Disable SDMMC1 IO power. gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW); - max77620_regulator_enable(REGULATOR_LDO2, 0); + max7762x_regulator_enable(REGULATOR_LDO2, false); sd_power_cycle_time_start = get_tmr_ms(); 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, - BIT(6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. + MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. if (tegra_t210) { @@ -313,28 +317,18 @@ static void _config_regulators(bool tegra_t210) (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); + max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000); - // Fix CPU/GPU after a L4T 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); + // Fix CPU/GPU after L4T warmboot. + max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE); + max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE); - 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_DVS_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_DVS_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); + // Set POR configuration. + max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG); + max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG); } else // Tegra X1+ set vdd_core voltage to 1.05V. - max77620_regulator_set_voltage(REGULATOR_SD0, 1050000); + max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000); } void hw_init() @@ -373,7 +367,8 @@ void hw_init() #ifdef DEBUG_UART_PORT clock_enable_uart(DEBUG_UART_PORT); - uart_init(DEBUG_UART_PORT, 115200); + uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE); + uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD); #endif // Enable Dynamic Voltage and Frequency Scaling device clock. @@ -391,17 +386,20 @@ void hw_init() //! TODO: Why? Device is NFC MCU on Lite. if (nx_hoag) - max77620_regulator_set_volt_and_flags(REGULATOR_LDO8, 2800000, MAX77620_POWER_MODE_NORMAL); + { + max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000); + max7762x_regulator_enable(REGULATOR_LDO8, true); + } // Initialize I2C1 for various power related devices. i2c_init(I2C_1); - // Enable charger in case it's disabled. - bq24193_enable_charger(); - // Initialize various regulators based on Erista/Mariko platform. _config_regulators(tegra_t210); + // Enable charger in case it's disabled. + bq24193_enable_charger(); + _config_pmc_scratch(); // Missing from 4.x+ // Set BPMP/SCLK to PLLP_OUT (408MHz). @@ -421,7 +419,7 @@ void hw_init() bpmp_mmu_enable(); } -void hw_reinit_workaround(bool extra_reconfig, u32 magic) +void hw_reinit_workaround(bool coreboot, u32 magic) { // Disable BPMP max clock. bpmp_clk_rate_set(BPMP_CLK_NORMAL); @@ -431,7 +429,7 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic) touch_power_off(); set_fan_duty(0); jc_deinit(); - regulator_disable_5v(REGULATOR_5V_ALL); + regulator_5v_disable(REGULATOR_5V_ALL); clock_disable_uart(UART_B); clock_disable_uart(UART_C); #endif @@ -445,10 +443,10 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic) CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); - if (extra_reconfig) + // Do coreboot mitigations. + if (coreboot) { msleep(10); - PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN; clock_disable_cl_dvfs(); @@ -457,6 +455,9 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic) gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO); + + // Reinstate SD controller power. + PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN); } // Power off display. diff --git a/bdk/soc/hw_init.h b/bdk/soc/hw_init.h index ff9ae4a..8888824 100644 --- a/bdk/soc/hw_init.h +++ b/bdk/soc/hw_init.h @@ -21,7 +21,7 @@ #include void hw_init(); -void hw_reinit_workaround(bool extra_reconfig, u32 magic); +void hw_reinit_workaround(bool coreboot, u32 magic); u32 hw_get_chip_id(); #endif diff --git a/bdk/soc/i2c.c b/bdk/soc/i2c.c index 099a182..0906adc 100644 --- a/bdk/soc/i2c.c +++ b/bdk/soc/i2c.c @@ -136,10 +136,10 @@ static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size) // Initiate transaction on normal mode. base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; - u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms. + u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms. while (base[I2C_STATUS] & I2C_STATUS_BUSY) { - if (get_tmr_ms() > timeout) + if (get_tmr_us() > timeout) return 0; } @@ -168,10 +168,10 @@ static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr) // Initiate transaction on normal mode. base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; - u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms. + u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms. while (base[I2C_STATUS] & I2C_STATUS_BUSY) { - if (get_tmr_ms() > timeout) + if (get_tmr_us() > timeout) return 0; } diff --git a/bdk/soc/irq.c b/bdk/soc/irq.c index 4fb39ca..e2f925c 100644 --- a/bdk/soc/irq.c +++ b/bdk/soc/irq.c @@ -133,6 +133,10 @@ static irq_status_t _irq_handle_source(u32 irq) } } + // Do not re-enable if not handled. + if (status == IRQ_NONE) + return status; + if (irqs[idx].flags & IRQ_FLAG_ONE_OFF) irq_free(irq); else @@ -148,7 +152,9 @@ void irq_handler() if (!irq_init_done) { + _irq_disable_source(irq); _irq_ack_source(irq); + return; } @@ -156,9 +162,10 @@ void irq_handler() int err = _irq_handle_source(irq); - //TODO: disable if unhandhled. if (err == IRQ_NONE) - gfx_printf("Unhandled IRQ: %d\n", irq); + { + DPRINTF("Unhandled IRQ got disabled: %d!\n", irq); + } } static void _irq_init() @@ -170,6 +177,9 @@ static void _irq_init() void irq_end() { + if (!irq_init_done) + return; + _irq_free_all(); irq_disable_cpu_irq_exceptions(); irq_init_done = false; diff --git a/bdk/soc/pmc.c b/bdk/soc/pmc.c index 62caa22..aa86cb7 100644 --- a/bdk/soc/pmc.c +++ b/bdk/soc/pmc.c @@ -14,11 +14,69 @@ * along with this program. If not, see . */ +#include #include #include #include -int pmc_enable_partition(u32 part, int enable) +void pmc_scratch_lock(pmc_sec_lock_t lock_mask) +{ + // Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address. + if (lock_mask & PMC_SEC_LOCK_MISC) + { + PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3. + PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23. + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38. + PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85. + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119. + + // SE2 context. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) + { + PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38) + PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150. + } + } + + if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS) + { + PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20. + PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54. + PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71. + PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87. + PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF; // RW lock: 88-98. + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF; // RW lock: 104-107. + } + + if (lock_mask & PMC_SEC_LOCK_RST_VECTOR) + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xF00000; // RW lock: 34-35. + + if (lock_mask & PMC_SEC_LOCK_CARVEOUTS) + { + PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x30000; // RW lock: 16. + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xC0000000; // RW lock: 39. + PMC(APBDEV_PMC_SEC_DISABLE4) |= 0xC0C00000; // RW lock: 51, 55. + PMC(APBDEV_PMC_SEC_DISABLE6) |= 0x3FF0; // RW lock: 74-78. + PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103. + } + + if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W) + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115. + + if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_R) + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xAA0000; // R lock: 112-115. + + if (lock_mask & PMC_SEC_LOCK_TZ_KEK_W) + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x55; // W lock: 24-27. + + if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R) + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27. + + if (lock_mask & PMC_SEC_LOCK_SE_SRK) + PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7 +} + +int pmc_enable_partition(pmc_power_rail_t part, u32 enable) { u32 part_mask = BIT(part); u32 desired_state = enable << part; diff --git a/bdk/soc/pmc.h b/bdk/soc/pmc.h index c27d937..42bd869 100644 --- a/bdk/soc/pmc.h +++ b/bdk/soc/pmc.h @@ -91,6 +91,8 @@ #define APBDEV_PMC_SEC_DISABLE6 0x5B8 #define APBDEV_PMC_SEC_DISABLE7 0x5BC #define APBDEV_PMC_SEC_DISABLE8 0x5C0 +#define APBDEV_PMC_SEC_DISABLE9 0x5C4 +#define APBDEV_PMC_SEC_DISABLE10 0x5C8 #define APBDEV_PMC_SCRATCH188 0x810 #define APBDEV_PMC_SCRATCH190 0x818 #define APBDEV_PMC_SCRATCH200 0x840 @@ -98,6 +100,54 @@ #define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC #define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0 -int pmc_enable_partition(u32 part, int enable); +typedef enum _pmc_sec_lock_t +{ + PMC_SEC_LOCK_MISC = BIT(0), + PMC_SEC_LOCK_LP0_PARAMS = BIT(1), + PMC_SEC_LOCK_RST_VECTOR = BIT(2), + PMC_SEC_LOCK_CARVEOUTS = BIT(3), + PMC_SEC_LOCK_TZ_CMAC_W = BIT(4), + PMC_SEC_LOCK_TZ_CMAC_R = BIT(5), + PMC_SEC_LOCK_TZ_KEK_W = BIT(6), + PMC_SEC_LOCK_TZ_KEK_R = BIT(7), + PMC_SEC_LOCK_SE_SRK = BIT(8), +} pmc_sec_lock_t; + +typedef enum _pmc_power_rail_t +{ + POWER_RAIL_CRAIL = 0, + POWER_RAIL_3D0 = 1, + POWER_RAIL_VENC = 2, + POWER_RAIL_PCIE = 3, + POWER_RAIL_VDEC = 4, + POWER_RAIL_L2C = 5, + POWER_RAIL_MPE = 6, + POWER_RAIL_HEG = 7, + POWER_RAIL_SATA = 8, + POWER_RAIL_CE1 = 9, + POWER_RAIL_CE2 = 10, + POWER_RAIL_CE3 = 11, + POWER_RAIL_CELP = 12, + POWER_RAIL_3D1 = 13, + POWER_RAIL_CE0 = 14, + POWER_RAIL_C0NC = 15, + POWER_RAIL_C1NC = 16, + POWER_RAIL_SOR = 17, + POWER_RAIL_DIS = 18, + POWER_RAIL_DISB = 19, + POWER_RAIL_XUSBA = 20, + POWER_RAIL_XUSBB = 21, + POWER_RAIL_XUSBC = 22, + POWER_RAIL_VIC = 23, + POWER_RAIL_IRAM = 24, + POWER_RAIL_NVDEC = 25, + POWER_RAIL_NVJPG = 26, + POWER_RAIL_AUD = 27, + POWER_RAIL_DFD = 28, + POWER_RAIL_VE2 = 29 +} pmc_power_rail_t; + +void pmc_scratch_lock(pmc_sec_lock_t lock_mask); +int pmc_enable_partition(pmc_power_rail_t part, u32 enable); #endif diff --git a/bdk/storage/mmc.h b/bdk/storage/mmc.h index efa9e10..976ded4 100644 --- a/bdk/storage/mmc.h +++ b/bdk/storage/mmc.h @@ -142,7 +142,10 @@ c : clear by read #define R1_SWITCH_ERROR (1 << 7) /* sx, c */ #define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ #define R1_APP_CMD (1 << 5) /* sr, c */ +#define R1_SKIP_STATE_CHECK (1 << 4) /* Custom state to skip expected state check */ +#define R1_AKE_SEQ_ERROR (1 << 3) +/* R1_CURRENT_STATE 12:9 */ #define R1_STATE_IDLE 0 #define R1_STATE_READY 1 #define R1_STATE_IDENT 2 diff --git a/bdk/storage/sd.h b/bdk/storage/sd.h index a780ec8..848a679 100644 --- a/bdk/storage/sd.h +++ b/bdk/storage/sd.h @@ -34,14 +34,16 @@ #define SD_APP_SEND_SCR 51 /* adtc R1 */ /* OCR bit definitions */ +#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ +#define SD_OCR_XPC (1 << 28) /* SDXC power control */ #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ -#define SD_OCR_XPC (1 << 28) /* SDXC power control */ -#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ #define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ #define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ #define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ +#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */ + /* * SD_SWITCH argument format: * diff --git a/bdk/storage/sdmmc.c b/bdk/storage/sdmmc.c index 43f837d..58e813e 100644 --- a/bdk/storage/sdmmc.c +++ b/bdk/storage/sdmmc.c @@ -45,7 +45,7 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) * Common functions for SD and MMC. */ -static int _sdmmc_storage_check_result(u32 res) +static int _sdmmc_storage_check_card_status(u32 res) { //Error mask: //TODO: R1_SWITCH_ERROR can be skipped for certain card types. @@ -66,15 +66,15 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re { sdmmc_cmd_t cmdbuf; sdmmc_init_cmd(&cmdbuf, cmd, arg, SDMMC_RSP_TYPE_1, check_busy); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) return 0; sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1); if (mask) *resp &= ~mask; - if (_sdmmc_storage_check_result(*resp)) - if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state) + if (_sdmmc_storage_check_card_status(*resp)) + if (expected_state == R1_SKIP_STATE_CHECK || R1_CURRENT_STATE(*resp) == expected_state) return 1; return 0; @@ -91,34 +91,34 @@ 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); + return sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL); } static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf) { sdmmc_cmd_t cmd; sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL)) return 0; - sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); + sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2); return 1; } static int _sdmmc_storage_select_card(sdmmc_storage_t *storage) { - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, 0x10); + return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK); } static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf) { sdmmc_cmd_t cmdbuf; sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) return 0; - sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); + sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2); return 1; } @@ -306,7 +306,7 @@ static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u } sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL)) return 0; return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3); @@ -340,7 +340,7 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power) static int _mmc_storage_set_relative_addr(sdmmc_storage_t *storage) { - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, 0x10); + return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, R1_SKIP_STATE_CHECK); } static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) @@ -432,19 +432,19 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) reqbuf.is_multi_block = 0; reqbuf.is_auto_cmd12 = 0; - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); _mmc_storage_parse_ext_csd(storage, buf); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg) { - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, 0x10); + return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK); } static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width) @@ -688,53 +688,60 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp static int _sd_storage_send_if_cond(sdmmc_storage_t *storage) { sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, 0x1AA, SDMMC_RSP_TYPE_5, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) + u16 vhd_pattern = SD_VHD_27_36 | 0xAA; + sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0); + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) return 1; // The SD Card is version 1.X + // Card version is >= 2.0, parse results. u32 resp = 0; if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5)) - return 2; + return 2; // Failed. - return (resp & 0xFF) == 0xAA ? 0 : 2; + // Check if VHD was accepted and pattern was properly returned. + if ((resp & 0xFFF) == vhd_pattern) + return 0; + + // Failed. + return 2; } -static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_low_voltage_support) +static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_uhs_support) { sdmmc_cmd_t cmdbuf; // Support for Current > 150mA - u32 arg = (~is_version_1 & 1) ? SD_OCR_XPC : 0; + u32 arg = !is_version_1 ? SD_OCR_XPC : 0; // Support for handling block-addressed SDHC cards - arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0; + arg |= !is_version_1 ? SD_OCR_CCS : 0; // Support for 1.8V - arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0; + arg |= (bus_uhs_support && !is_version_1) ? SD_OCR_S18R : 0; // This is needed for most cards. Do not set bit7 even if 1.8V is supported. arg |= SD_OCR_VDD_32_33; 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)) + if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_version_1 ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL)) return 0; return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); } -static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_low_voltage_support) +static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_uhs_support) { u32 timeout = get_tmr_ms() + 1500; while (1) { u32 cond = 0; - if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_low_voltage_support)) + if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support)) break; if (cond & MMC_CARD_BUSY) { -DPRINTF("[SD] cond: %08X, lv: %d\n", cond, bus_low_voltage_support); +DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); if (cond & SD_OCR_CCS) storage->has_sector_access = 1; // Check if card supports 1.8V signaling. - if (cond & SD_ROCR_S18A && bus_low_voltage_support) + if (cond & SD_ROCR_S18A && bus_uhs_support) { //The low voltage regulator configuration is valid for SDMMC1 only. if (storage->sdmmc->id == SDMMC_1 && @@ -771,7 +778,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage) while (1) { - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) break; u32 resp = 0; @@ -822,7 +829,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf) reqbuf.is_multi_block = 0; reqbuf.is_auto_cmd12 = 0; - if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0)) + if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; @@ -838,7 +845,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf) _sd_storage_parse_scr(storage); //gfx_hexdump(0, storage->raw_scr, 8); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) @@ -854,12 +861,12 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) reqbuf.is_multi_block = 0; reqbuf.is_auto_cmd12 = 0; - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg) @@ -878,12 +885,12 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, reqbuf.is_multi_block = 0; reqbuf.is_auto_cmd12 = 0; - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf) @@ -1057,6 +1064,44 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf) return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25); } +u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage) +{ + u32 au_size = storage->ssr.uhs_au_size; + + if (!au_size) + au_size = storage->ssr.au_size; + + if (au_size <= 10) + { + u32 shift = au_size; + au_size = shift ? 8 : 0; + au_size <<= shift; + } + else + { + switch (au_size) + { + case 11: + au_size = 12288; + break; + case 12: + au_size = 16384; + break; + case 13: + au_size = 24576; + break; + case 14: + au_size = 32768; + break; + case 15: + au_size = 65536; + break; + } + } + + return au_size; +} + static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) { // unstuff_bits supports only 4 u32 so break into 2 x 16byte groups @@ -1106,6 +1151,9 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8); storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4); + + storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4); + storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4); } static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) @@ -1127,7 +1175,7 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n"); return 0; } - if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0)) + if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; @@ -1143,7 +1191,7 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n"); _sd_storage_parse_ssr(storage); //gfx_hexdump(0, storage->raw_ssr, 64); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } static void _sd_storage_parse_cid(sdmmc_storage_t *storage) @@ -1186,7 +1234,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage) } } -static bool _sdmmc_storage_get_low_voltage_support(u32 bus_width, u32 type) +static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type) { switch (type) { @@ -1235,13 +1283,13 @@ DPRINTF("[SD] after init\n"); DPRINTF("[SD] went to idle state\n"); is_version_1 = _sd_storage_send_if_cond(storage); - if (is_version_1 == 2) + if (is_version_1 == 2) // Failed. return 0; DPRINTF("[SD] after send if cond\n"); - bool bus_low_voltage_support = _sdmmc_storage_get_low_voltage_support(bus_width, type); + bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type); - if (!_sd_storage_get_op_cond(storage, is_version_1, bus_low_voltage_support)) + if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support)) return 0; DPRINTF("[SD] got op cond\n"); @@ -1310,6 +1358,7 @@ DPRINTF("[SD] switched to wide bus width\n"); } else { + bus_width = SDMMC_BUS_WIDTH_1; DPRINTF("[SD] SD does not support wide bus width\n"); } @@ -1321,7 +1370,7 @@ DPRINTF("[SD] enabled UHS\n"); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); } - else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0) + else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF)) // Not default speed and not SD Version 1.x { if (!_sd_storage_enable_hs_high_volt(storage, buf)) return 0; @@ -1368,7 +1417,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) reqbuf.is_multi_block = 0; reqbuf.is_auto_cmd12 = 0; - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) { sdmmc_stop_transmission(storage->sdmmc, &resp); return 0; @@ -1376,7 +1425,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1)) return 0; - if (!_sdmmc_storage_check_result(resp)) + if (!_sdmmc_storage_check_card_status(resp)) return 0; return _sdmmc_storage_check_status(storage); } diff --git a/bdk/storage/sdmmc.h b/bdk/storage/sdmmc.h index 68d70f0..481b3a1 100644 --- a/bdk/storage/sdmmc.h +++ b/bdk/storage/sdmmc.h @@ -95,6 +95,8 @@ typedef struct _sd_ssr u8 uhs_grade; u8 video_class; u8 app_class; + u8 au_size; + u8 uhs_au_size; u32 protected_size; } sd_ssr_t; @@ -107,6 +109,7 @@ typedef struct _sdmmc_storage_t u32 sec_cnt; int is_low_voltage; u32 partition; + int initialized; u8 raw_cid[0x10]; u8 raw_csd[0x10]; u8 raw_scr[8]; @@ -116,16 +119,17 @@ typedef struct _sdmmc_storage_t mmc_ext_csd_t ext_csd; sd_scr_t scr; sd_ssr_t ssr; - int initialized; } sdmmc_storage_t; -int sdmmc_storage_end(sdmmc_storage_t *storage); -int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); -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 bus_width, u32 type); -int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); +int sdmmc_storage_end(sdmmc_storage_t *storage); +int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); +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 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 bus_width, u32 type); -int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); +int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); +int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); + +u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage); #endif diff --git a/bdk/storage/sdmmc_driver.c b/bdk/storage/sdmmc_driver.c index 3eaded0..bacb977 100644 --- a/bdk/storage/sdmmc_driver.c +++ b/bdk/storage/sdmmc_driver.c @@ -501,7 +501,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) break; case SDMMC_RSP_TYPE_2: - if (size < 0x10) + if (size < 16) return 0; rsp[0] = sdmmc->rsp[0]; rsp[1] = sdmmc->rsp[1]; @@ -1052,7 +1052,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, if (!result) { #ifdef ERROR_EXTRA_PRINTING - EPRINTFARGS("SDMMC: DMA Update failed (%08X)!", result); + EPRINTF("SDMMC: DMA Update failed!"); #endif } } @@ -1200,8 +1200,8 @@ static int _sdmmc_config_sdmmc1(bool t210b01) usleep(10000); // Enable SD card IO power. - max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); - max77620_regulator_enable(REGULATOR_LDO2, 1); + max7762x_regulator_set_voltage(REGULATOR_LDO2, 3300000); + max7762x_regulator_enable(REGULATOR_LDO2, true); usleep(1000); // Set pad slew codes to get good quality clock. @@ -1332,18 +1332,6 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p void sdmmc1_disable_power() { - // Ensure regulator is into default voltage. - if (PMC(APBDEV_PMC_PWR_DET_VAL) & PMC_PWR_DET_SDMMC1_IO_EN) - { - // Switch to 1.8V and wait for regulator to stabilize. - max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); - usleep(150); - - // Inform IO pads that we switched to 1.8V. - PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN); - (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. - } - // T210B01 WAR: Clear pull down from CLK pad. PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK; @@ -1351,7 +1339,7 @@ void sdmmc1_disable_power() _sdmmc_config_sdmmc1_pads(true); // Disable SD card IO power regulator. - max77620_regulator_enable(REGULATOR_LDO2, 0); + max7762x_regulator_enable(REGULATOR_LDO2, false); usleep(4000); // Disable SD card IO power pin. @@ -1440,7 +1428,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc) _sdmmc_commit_changes(sdmmc); // Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed. - max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); + max7762x_regulator_set_voltage(REGULATOR_LDO2, 1800000); usleep(150); // Inform IO pads that we switched to 1.8V. diff --git a/bdk/thermal/fan.c b/bdk/thermal/fan.c index f39b082..d149b36 100644 --- a/bdk/thermal/fan.c +++ b/bdk/thermal/fan.c @@ -56,7 +56,7 @@ void set_fan_duty(u32 duty) if (inv_duty == 236) { PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%. - regulator_disable_5v(REGULATOR_5V_FAN); + regulator_5v_disable(REGULATOR_5V_FAN); // Disable fan. PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = @@ -65,7 +65,7 @@ void set_fan_duty(u32 duty) else // Set PWM duty. { // Fan power supply. - regulator_enable_5v(REGULATOR_5V_FAN); + regulator_5v_enable(REGULATOR_5V_FAN); PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (inv_duty << 16); // Enable fan. diff --git a/bdk/usb/usb_gadget_hid.c b/bdk/usb/usb_gadget_hid.c index 3437b40..b7c2e24 100644 --- a/bdk/usb/usb_gadget_hid.c +++ b/bdk/usb/usb_gadget_hid.c @@ -309,7 +309,7 @@ static bool _fts_touch_read(touchpad_report_t *rpt) static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len) { - u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED); + u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED_CMD); if (status == USB_ERROR_XFER_ERROR) { usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!"); diff --git a/bdk/usb/usb_gadget_ums.c b/bdk/usb/usb_gadget_ums.c index 97deeb5..6a9831f 100644 --- a/bdk/usb/usb_gadget_ums.c +++ b/bdk/usb/usb_gadget_ums.c @@ -58,7 +58,7 @@ #define UMS_SCSI_TRANSFER_512K (0x80000 >> UMS_DISK_LBA_SHIFT) -#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER >> UMS_DISK_LBA_SHIFT) +#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER) // Length of a SCSI Command Data Block. #define SCSI_MAX_CMD_SZ 16 @@ -121,6 +121,15 @@ enum ums_state { UMS_STATE_TERMINATED }; +enum ums_result { + UMS_RES_OK = 0, + UMS_RES_IO_ERROR = -5, + UMS_RES_TIMEOUT = -3, + UMS_RES_PROT_FATAL = -4, + UMS_RES_INVALID_ARG = -22 +}; + + enum data_direction { DATA_DIR_UNKNOWN = 0, DATA_DIR_FROM_HOST, @@ -283,21 +292,21 @@ static int ums_wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums) { /* usbd_set_ep_wedge(bulk_ctxt->bulk_in); */ - return 0; + return UMS_RES_OK; } static int ums_set_stall(u32 ep) { usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL); - return 0; + return UMS_RES_OK; } static int ums_clear_stall(u32 ep) { usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR); - return 0; + return UMS_RES_OK; } static void ums_flush_endpoint(u32 ep) @@ -306,13 +315,13 @@ static void ums_flush_endpoint(u32 ep) usb_ops.usbd_flush_endpoint(ep); } -static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, bool sync) +static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout) { if (ep == bulk_ctxt->bulk_in) { bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write( bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length, - &bulk_ctxt->bulk_in_length_actual, sync); + &bulk_ctxt->bulk_in_length_actual, sync_timeout); if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR) { @@ -322,14 +331,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED) ums->set_text(ums->label, "#FFDD00 Error:# EP IN Buffer not aligned!"); - if (sync) + if (sync_timeout) bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY; } else { bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read( bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length, - &bulk_ctxt->bulk_out_length_actual, sync); + &bulk_ctxt->bulk_out_length_actual, sync_timeout); if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) { @@ -339,7 +348,7 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED) ums->set_text(ums->label, "#FFDD00 Error:# EP OUT Buffer not aligned!"); - if (sync) + if (sync_timeout) bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; } } @@ -377,7 +386,7 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, else { bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish( - &bulk_ctxt->bulk_out_length_actual, 1000000); + &bulk_ctxt->bulk_out_length_actual); if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) { @@ -446,20 +455,20 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } } if (lba_offset >= ums->lun.num_sectors) { ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } // Check that request data size is not 0. u32 amount_left = ums->data_size_from_cmnd >> UMS_DISK_LBA_SHIFT; if (!amount_left) - return -5; // I/O error. /* No default reply */ + return UMS_RES_IO_ERROR; // No default reply. // Limit IO transfers based on request for faster concurrent reads. u32 max_io_transfer = (amount_left >= UMS_SCSI_TRANSFER_512K) ? @@ -520,7 +529,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) sdmmc_buf += amount << UMS_DISK_LBA_SHIFT; } - return -5; // I/O error no default reply here. /* No default reply */ + return UMS_RES_IO_ERROR; // No default reply. } /* @@ -541,7 +550,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_WRITE_PROTECTED; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } if (ums->cmnd[0] == SC_WRITE_6) @@ -555,7 +564,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } } @@ -564,7 +573,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Carry out the file writes */ @@ -580,7 +589,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { // Limit write to max supported read from EP OUT. - amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER << UMS_DISK_LBA_SHIFT); + amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER); if (usb_lba_offset >= ums->lun.num_sectors) //////////Check if it works with concurrency { @@ -612,7 +621,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) ums->lun.sense_data = SS_COMMUNICATION_FAILURE; ums->lun.sense_data_info = lba_offset; ums->lun.info_valid = 1; - sprintf(txt_buf, "#FFDD00 Error:# Write - Comm failure %d!", bulk_ctxt->bulk_out_status); + s_printf(txt_buf, "#FFDD00 Error:# Write - Comm failure %d!", bulk_ctxt->bulk_out_status); ums->set_text(ums->label, txt_buf); break; } @@ -668,7 +677,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset); } } - return -5; // I/O error. /* No default reply */ + return UMS_RES_IO_ERROR; // No default reply. } static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -679,7 +688,7 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } // We allow DPO but we don't implement it. Check that nothing else is enabled. @@ -687,12 +696,12 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } u32 verification_length = get_array_be_to_le16(&ums->cmnd[7]); if (verification_length == 0) - return -5; // I/O error. /* No default reply */ + return UMS_RES_IO_ERROR; // No default reply. u32 amount; while (verification_length > 0) @@ -724,7 +733,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset); lba_offset += amount; verification_length -= amount; } - return 0; + return UMS_RES_OK; } static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -742,7 +751,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) buf[3] = 20; // Additional length. buf += 4; - sprintf((char *)buf, "%04X%s", + s_printf((char *)buf, "%04X%s", ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC "); switch (ums->lun.partition) @@ -751,13 +760,13 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) strcpy((char *)buf + strlen((char *)buf), "RAW"); break; case EMMC_GPP + 1: - sprintf((char *)buf + strlen((char *)buf), "GPP"); + s_printf((char *)buf + strlen((char *)buf), "GPP"); break; case EMMC_BOOT0 + 1: - sprintf((char *)buf + strlen((char *)buf), "BOOT0"); + s_printf((char *)buf + strlen((char *)buf), "BOOT0"); break; case EMMC_BOOT1 + 1: - sprintf((char *)buf + strlen((char *)buf), "BOOT1"); + s_printf((char *)buf + strlen((char *)buf), "BOOT1"); break; } @@ -784,18 +793,18 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) switch (ums->lun.partition) { case 0: - sprintf((char *)buf, "%s", "SD RAW"); + s_printf((char *)buf, "%s", "SD RAW"); break; case EMMC_GPP + 1: - sprintf((char *)buf, "%s%s", + s_printf((char *)buf, "%s%s", ums->lun.type == MMC_SD ? "SD " : "eMMC ", "GPP"); break; case EMMC_BOOT0 + 1: - sprintf((char *)buf, "%s%s", + s_printf((char *)buf, "%s%s", ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT0"); break; case EMMC_BOOT1 + 1: - sprintf((char *)buf, "%s%s", + s_printf((char *)buf, "%s%s", ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT1"); break; } @@ -843,7 +852,7 @@ static int _scsi_read_capacity(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } put_array_le_to_be32(ums->lun.num_sectors - 1, &buf[0]); // Max logical block. @@ -866,14 +875,14 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } if (pc != 1) // Current cumulative values. { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } memset(buf, 0, 8); @@ -915,7 +924,7 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } put_array_le_to_be16(len - 4, &buf0[2]); @@ -938,14 +947,14 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } if (pc == 3) { ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Write the mode parameter header. Fixed values are: default @@ -995,7 +1004,7 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Store the mode data length */ @@ -1015,14 +1024,14 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums) { ums->lun.sense_data = SS_INVALID_COMMAND; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } else if ((ums->cmnd[1] & ~0x01) != 0 || // Mask away Immed. (ums->cmnd[4] & ~0x03) != 0) // Mask LoEj, Start. { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; + return UMS_RES_INVALID_ARG; } loej = ums->cmnd[4] & 0x02; @@ -1035,10 +1044,10 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums) { ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT; - return -22; + return UMS_RES_INVALID_ARG; } - return 0; + return UMS_RES_OK; } // Check if we are allowed to unload the media. @@ -1047,16 +1056,16 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums) ums->set_text(ums->label, "#C7EA46 Status:# Unload attempt prevented"); ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED; - return -22; + return UMS_RES_INVALID_ARG; } if (!loej) - return 0; + return UMS_RES_OK; // Unmount means we exit UMS because of ejection. ums->lun.unmounted = 1; - return 0; + return UMS_RES_OK; } static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) @@ -1067,7 +1076,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) { ums->lun.sense_data = SS_INVALID_COMMAND; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } prevent = ums->cmnd[4] & 0x01; @@ -1075,7 +1084,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } // Notify for possible unmounting? @@ -1085,7 +1094,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) ums->lun.prevent_medium_removal = prevent; - return 0; + return UMS_RES_OK; } static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1132,7 +1141,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", { ums->phase_error = 1; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } // Cmd length verification. @@ -1146,7 +1155,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", { ums->phase_error = 1; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } } @@ -1167,7 +1176,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", ums->lun.sense_data = ums->lun.unit_attention_data; ums->lun.unit_attention_data = SS_NO_SENSE; - return -22; + return UMS_RES_INVALID_ARG; } // Check that only command bytes listed in the mask are set. @@ -1178,7 +1187,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } } @@ -1187,16 +1196,16 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", { ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT; - return -22; + return UMS_RES_INVALID_ARG; } - return 0; + return UMS_RES_OK; } static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { u32 len; - int reply = -22; // Invalid argument. + int reply = UMS_RES_INVALID_ARG; ums->phase_error = 0; ums->short_packet_received = 0; @@ -1227,7 +1236,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { // We don't support MODE SELECT. ums->lun.sense_data = SS_INVALID_COMMAND; - reply = -22; + reply = UMS_RES_INVALID_ARG; } break; @@ -1238,7 +1247,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { // We don't support MODE SELECT. ums->lun.sense_data = SS_INVALID_COMMAND; - reply = -22; + reply = UMS_RES_INVALID_ARG; } break; @@ -1367,12 +1376,12 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) if (reply == 0) { ums->lun.sense_data = SS_INVALID_COMMAND; - reply = -22; // Invalid argument. + reply = UMS_RES_INVALID_ARG; } break; } - if (reply == -22) // Invalid argument. + if (reply == UMS_RES_INVALID_ARG) reply = 0; // Error reply length. // Set up reply buffer for finish_reply(). Otherwise it's already set. @@ -1384,7 +1393,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) ums->residue -= reply; } - return 0; + return UMS_RES_OK; } static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1398,12 +1407,12 @@ static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) u32 nsend = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep); bulk_ctxt->bulk_in_length = nsend; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA); ums->usb_amount_left -= nsend; current_len_to_keep = 0; } - return 0; + return UMS_RES_OK; } static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1416,10 +1425,10 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) u32 amount = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); bulk_ctxt->bulk_out_length = amount; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_DATA); ums->usb_amount_left -= amount; - return 0; + return UMS_RES_OK; } // Throw away the data in a filled buffer. @@ -1431,15 +1440,15 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) bulk_ctxt->bulk_out_status != USB_RES_OK) { raise_exception(ums, UMS_STATE_ABORT_BULK_OUT); - return -4; // Interrupted system call + return UMS_RES_PROT_FATAL; } } - return 0; + return UMS_RES_OK; } static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { - int rc = 0; + int rc = UMS_RES_OK; switch (ums->data_dir) { case DATA_DIR_NONE: @@ -1463,7 +1472,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) // If there's no residue, simply send the last buffer. if (!ums->residue) { - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA); /* For Bulk-only, if we're allowed to stall then send the * short packet and halt the bulk-in endpoint. If we can't @@ -1471,7 +1480,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) } else if (ums->can_stall) { - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA); rc = ums_set_stall(bulk_ctxt->bulk_in); ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!"); } @@ -1491,7 +1500,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) if (ums->short_packet_received) // Did the host stop sending unexpectedly early? { raise_exception(ums, UMS_STATE_ABORT_BULK_OUT); - rc = -4; // Interrupted system call + rc = UMS_RES_PROT_FATAL; } else // We can't stall. Read in the excess data and throw it away. rc = throw_away_data(ums, bulk_ctxt); @@ -1574,7 +1583,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) } if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore) - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Is the CBW valid? */ @@ -1594,7 +1603,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) // until the next reset. ums_wedge_bulk_in_endpoint(ums); bulk_ctxt->bulk_out_ignore = 1; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Is the CBW meaningful? */ @@ -1613,7 +1622,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) ums->set_text(ums->label, "#FFDD00 Error:# CBW unknown - Stalled both EP!"); } - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Save the command for later */ @@ -1636,12 +1645,12 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) if (!ums->lun.unmounted) ums->timeouts = 0; - return 0; + return UMS_RES_OK; } static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { - int rc = 0; + int rc = UMS_RES_OK; /* Wait for the next buffer to become available */ // while (bulk_ctxt->bulk_out_buf_state != BUF_STATE_EMPTY) @@ -1652,7 +1661,7 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN; /* Queue a request to read a Bulk-only CBW */ - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD); /* We will drain the buffer in software, which means we * can reuse it for the next filling. No need to advance @@ -1698,7 +1707,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) csw->Status = status; bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_CMD); } static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1765,16 +1774,16 @@ static inline void _system_maintainance(usbd_gadget_ums_t *ums) u32 time = get_tmr_ms(); - if (timer_dram < time) - { - minerva_periodic_training(); - timer_dram = get_tmr_ms() + 100; - } - else if (timer_status_bar < time) + if (timer_status_bar < time) { ums->system_maintenance(true); timer_status_bar = get_tmr_ms() + 30000; } + else if (timer_dram < time) + { + minerva_periodic_training(); + timer_dram = get_tmr_ms() + EMC_PERIODIC_TRAIN_MS; + } } int usb_device_gadget_ums(usb_ctxt_t *usbs) diff --git a/bdk/usb/usb_t210.h b/bdk/usb/usb_t210.h index 4d67c69..e677a5f 100644 --- a/bdk/usb/usb_t210.h +++ b/bdk/usb/usb_t210.h @@ -198,6 +198,7 @@ typedef struct _t210_usb2d_t #define XUSB_DEV_XHCI_ST 0x34 #define XHCI_ST_RC BIT(0) #define XHCI_ST_IP BIT(4) +#define XUSB_DEV_XHCI_RT_IMOD 0x38 #define XUSB_DEV_XHCI_PORTSC 0x3C #define XHCI_PORTSC_PR BIT(4) #define XHCI_PORTSC_PLS_MASK (0xF << 5) diff --git a/bdk/usb/usbd.c b/bdk/usb/usbd.c index 8cf37c3..95d1ed5 100644 --- a/bdk/usb/usbd.c +++ b/bdk/usb/usbd.c @@ -724,7 +724,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint) return USB_EP_STATUS_IDLE; } -static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) +static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, u32 sync_timeout) { if (!buf) len = 0; @@ -797,12 +797,12 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) int res = USB_RES_OK; usb_ep_status_t ep_status; - if (sync) + if (sync_timeout) { ep_status = _usbd_get_ep_status(endpoint); if (ep_status == USB_EP_STATUS_ACTIVE) { - u32 retries = 1000000; // Timeout 2s. + u32 retries = sync_timeout; while (retries) { ep_status = _usbd_get_ep_status(endpoint); @@ -834,7 +834,7 @@ out: static int _usbd_ep_ack(usb_ep_t ep) { - return _usbd_ep_operation(ep, NULL, 0, true); + return _usbd_ep_operation(ep, NULL, 0, USB_XFER_SYNCED_ENUM); } static void _usbd_set_ep0_stall() @@ -1275,7 +1275,7 @@ static int _usbd_handle_ep0_control_transfer() if (_wLength < size) size = _wLength; - res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, true); + res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, USB_XFER_SYNCED_ENUM); if (!res) res = _usbd_ep_ack(USB_EP_CTRL_OUT); } @@ -1402,7 +1402,7 @@ static usb_ep_status_t _usbd_get_ep1_status(usb_dir_t dir) return _usbd_get_ep_status(ep); } -int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) +int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_timeout) { if ((u32)buf % USB_EP_BUFFER_ALIGN) return USB2_ERROR_XFER_NOT_ALIGNED; @@ -1410,9 +1410,9 @@ int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; - int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync); + int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync_timeout); - if (sync && bytes_read) + if (sync_timeout && bytes_read) *bytes_read = res ? 0 : len; return res; @@ -1435,7 +1435,7 @@ int usb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) { u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); - res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); + res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA); if (res) return res; @@ -1455,7 +1455,7 @@ static int _usbd_get_ep1_out_bytes_read() return (usbdaemon->ep_bytes_requested[USB_EP_BULK_OUT] - (usbdaemon->qhs[USB_EP_BULK_OUT].token >> 16)); } -int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) +int usb_device_ep1_out_reading_finish(u32 *pending_bytes) { usb_ep_status_t ep_status; do @@ -1480,7 +1480,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) return USB_ERROR_XFER_ERROR; } -int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) +int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_timeout) { if ((u32)buf % USB_EP_BUFFER_ALIGN) return USB2_ERROR_XFER_NOT_ALIGNED; @@ -1488,9 +1488,9 @@ int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; - int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync); + int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync_timeout); - if (sync && bytes_written) + if (sync_timeout && bytes_written) *bytes_written = res ? 0 : len; return res; diff --git a/bdk/usb/usbd.h b/bdk/usb/usbd.h index 6ba2a5a..a0e4a63 100644 --- a/bdk/usb/usbd.h +++ b/bdk/usb/usbd.h @@ -30,8 +30,12 @@ #define USB_EP_BUFFER_MAX_SIZE (USB_EP_BUFFER_4_TD) #define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE) -#define USB_XFER_START false -#define USB_XFER_SYNCED true +#define USB_XFER_START 0 +#define USB_XFER_SYNCED_ENUM 1000000 +#define USB_XFER_SYNCED_CMD 1000000 +#define USB_XFER_SYNCED_DATA 2000000 +#define USB_XFER_SYNCED_CLASS 5000000 +#define USB_XFER_SYNCED -1 typedef enum _usb_hid_type { @@ -169,10 +173,10 @@ typedef struct _usb_ops_t int (*usb_device_class_send_max_lun)(u8); int (*usb_device_class_send_hid_report)(); - int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, bool); + int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32); int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *); - int (*usb_device_ep1_out_reading_finish)(u32 *, int); - int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, bool); + int (*usb_device_ep1_out_reading_finish)(u32 *); + int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, u32); int (*usb_device_ep1_in_writing_finish)(u32 *); bool (*usb_device_get_suspended)(); bool (*usb_device_get_port_in_sleep)(); diff --git a/bdk/usb/xusbd.c b/bdk/usb/xusbd.c index e33ca44..4beefcd 100644 --- a/bdk/usb/xusbd.c +++ b/bdk/usb/xusbd.c @@ -881,7 +881,7 @@ int xusb_device_init() _xusbd_init_device_clocks(); // Enable AHB redirect for access to IRAM for Event/EP ring buffers. - mc_enable_ahb_redirect(); // can be skipped if IRAM is not used///////////////// + mc_enable_ahb_redirect(); // Can be skipped if IRAM is not used. // Enable XUSB device IPFS. XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI; @@ -895,14 +895,11 @@ int xusb_device_init() XUSB_DEV_DEV(XUSB_DEV_INTR_MASK) |= DEV_INTR_MASK_IP_INT_MASK; // AHB USB performance cfg. - //TODO: Doesn't help.. -/* AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE; AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE; AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3; AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) = MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles. -*/ // Initialize context. usbd_xotg = &usbd_xotg_controller_ctxt; @@ -1771,6 +1768,13 @@ int xusb_device_enumerate(usb_gadget_type gadget) usbd_xotg->gadget = gadget; + /* + * Set interrupt moderation to 0us. + * This is important because default value creates a 4.62ms latency. + * Effectively hurting transfers by having 15% to 96% performance loss. + */ + XUSB_DEV_XHCI(XUSB_DEV_XHCI_RT_IMOD) = 0; + // Disable Wake events. XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_0) = 0; XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_1) = 0; @@ -1803,7 +1807,7 @@ int xusb_device_enumerate(usb_gadget_type gadget) u32 timer = get_tmr_ms() + 90000; while (true) { - int res = _xusb_ep_operation(1000000); // 2s timeout. + int res = _xusb_ep_operation(USB_XFER_SYNCED_ENUM); // 2s timeout. if (res && res != USB_ERROR_TIMEOUT) return res; @@ -1826,7 +1830,7 @@ void xusb_end(bool reset_ep, bool only_controller) CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB); CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB); - mc_disable_ahb_redirect();/////////////////// + mc_disable_ahb_redirect(); // Can be skipped if IRAM is not used. } int xusb_handle_ep0_ctrl_setup() @@ -1844,7 +1848,7 @@ int xusb_handle_ep0_ctrl_setup() return USB_RES_OK; } -int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) +int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries) { if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; @@ -1855,10 +1859,10 @@ int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) _xusb_issue_normal_trb(buf, len, USB_DIR_OUT); usbd_xotg->tx_count[USB_DIR_OUT]++; - if (sync) + if (sync_tries) { while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) - res = _xusb_ep_operation(1000000); // 2s timeout. + res = _xusb_ep_operation(sync_tries); if (bytes_read) *bytes_read = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; @@ -1882,7 +1886,7 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) { u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); - int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); + int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA); if (res) return res; @@ -1894,11 +1898,11 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) return USB_RES_OK; } -int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) +int xusb_device_ep1_out_reading_finish(u32 *pending_bytes) { int res = USB_RES_OK; while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) - res = _xusb_ep_operation(tries); + res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries. if (pending_bytes) *pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; @@ -1908,7 +1912,7 @@ int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) return res; } -int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) +int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_tries) { if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; @@ -1921,10 +1925,10 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) _xusb_issue_normal_trb(buf, len, USB_DIR_IN); usbd_xotg->tx_count[USB_DIR_IN]++; - if (sync) + if (sync_tries) { while (!res && usbd_xotg->tx_count[USB_DIR_IN]) - res = _xusb_ep_operation(1000000); // 2s timeout. + res = _xusb_ep_operation(sync_tries); if (bytes_written) *bytes_written = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; @@ -1947,7 +1951,7 @@ int xusb_device_ep1_in_writing_finish(u32 *pending_bytes) { int res = USB_RES_OK; while (!res && usbd_xotg->tx_count[USB_DIR_IN]) - res = _xusb_ep_operation(1000000); // 2s timeout. + res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries. if (pending_bytes) *pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; @@ -1973,7 +1977,7 @@ bool xusb_device_class_send_max_lun(u8 max_lun) // Wait for request and transfer start. while (usbd_xotg->device_state != XUSB_LUN_CONFIGURED) { - _xusb_ep_operation(500000); + _xusb_ep_operation(USB_XFER_SYNCED_CLASS); if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) return true; } @@ -1991,7 +1995,7 @@ bool xusb_device_class_send_hid_report() // Wait for request and transfer start. while (usbd_xotg->device_state != XUSB_HID_CONFIGURED) { - _xusb_ep_operation(500000); + _xusb_ep_operation(USB_XFER_SYNCED_CLASS); if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) return true; } diff --git a/bdk/utils/types.h b/bdk/utils/types.h index 0300425..9fde3ae 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -74,6 +74,9 @@ typedef int bool; #define true 1 #define false 0 +#define DISABLE 0 +#define ENABLE 1 + #define BOOT_CFG_AUTOBOOT_EN BIT(0) #define BOOT_CFG_FROM_LAUNCH BIT(1) #define BOOT_CFG_FROM_ID BIT(2) diff --git a/bdk/utils/util.c b/bdk/utils/util.c index e5cd868..6f535b2 100644 --- a/bdk/utils/util.c +++ b/bdk/utils/util.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (c) 2018 CTCaer +* Copyright (c) 2018-2020 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, @@ -44,7 +44,7 @@ u32 get_tmr_ms() u32 get_tmr_us() { - return TMR(TIMERUS_CNTR_1US); //TIMERUS_CNTR_1US + return TMR(TIMERUS_CNTR_1US); } void msleep(u32 ms) @@ -132,53 +132,58 @@ void panic(u32 val) usleep(1); } -void reboot_normal() +void power_set_state(power_state_t state) { + u8 reg; + + // Unmount and power down sd card. sd_end(); - hw_reinit_workaround(false, 0); - panic(0x21); // Bypass fuse programming in package1. -} - -void reboot_rcm() -{ - sd_end(); - hw_reinit_workaround(false, 0); - - PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; - PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; - - while (true) - bpmp_halt(); -} - -void reboot_full() -{ - sd_end(); - hw_reinit_workaround(false, 0); - - // Enable soft reset wake event. - u8 reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2); - reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg); - - // Do a soft reset. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST); - - while (true) - bpmp_halt(); -} - -void power_off() -{ - sd_end(); + // De-initialize and power down various hardware. hw_reinit_workaround(false, 0); // Stop the alarm, in case we injected and powered off too fast. max77620_rtc_stop_alarm(); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); + // Set power state. + switch (state) + { + case REBOOT_RCM: + PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; // Enable RCM path. + PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; // PMC reset. + break; + + case REBOOT_BYPASS_FUSES: + panic(0x21); // Bypass fuse programming in package1. + break; + + case POWER_OFF: + // Initiate power down sequence and do not generate a reset (regulators retain state). + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); + break; + + case POWER_OFF_RESET: + case POWER_OFF_REBOOT: + default: + // Enable/Disable soft reset wake event. + reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2); + if (state == POWER_OFF_RESET) + reg &= ~MAX77620_ONOFFCNFG2_SFT_RST_WK; // Do not wake up after power off. + else // POWER_OFF_REBOOT. + reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; // Wake up after power off. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg); + + // Initiate power down sequence and generate a reset (regulators' state resets). + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST); + break; + } while (true) bpmp_halt(); } + +void power_set_state_ex(void *param) +{ + power_state_t *state = (power_state_t *)param; + power_set_state(*state); +} diff --git a/bdk/utils/util.h b/bdk/utils/util.h index 20df76f..9a6d00a 100644 --- a/bdk/utils/util.h +++ b/bdk/utils/util.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2020 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, @@ -21,6 +21,18 @@ #include #include +#define NYX_NEW_INFO 0x3058594E + +typedef enum +{ + REBOOT_RCM, // PMC reset. Enter RCM mode. + REBOOT_BYPASS_FUSES, // PMC reset via watchdog. Enter Normal mode. Bypass fuse programming in package1. + + POWER_OFF, // Power off PMIC. Do not reset regulators. + POWER_OFF_RESET, // Power off PMIC. Reset regulators. + POWER_OFF_REBOOT, // Power off PMIC. Reset regulators. Power on. +} power_state_t; + typedef enum { NYX_CFG_BIS = BIT(5), @@ -49,6 +61,10 @@ typedef struct _cfg_op_t typedef struct _nyx_info_t { + u32 magic; + u32 sd_init; + u32 sd_errors[3]; + u8 rsvd[0x1000]; u32 disp_id; u32 errors; } nyx_info_t; @@ -65,17 +81,18 @@ typedef struct _nyx_storage_t emc_table_t mtc_table[10]; } nyx_storage_t; -u32 get_tmr_us(); -u32 get_tmr_ms(); -u32 get_tmr_s(); -void usleep(u32 us); -void msleep(u32 ms); -void panic(u32 val); -void reboot_normal(); -void reboot_rcm(); -void reboot_full(); -void power_off(); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); u32 crc32_calc(u32 crc, const u8 *buf, u32 len); +u32 get_tmr_us(); +u32 get_tmr_ms(); +u32 get_tmr_s(); +void usleep(u32 us); +void msleep(u32 ms); + +void panic(u32 val); +void power_set_state(power_state_t state); +void power_set_state_ex(void *param); + + #endif diff --git a/source/hid/hid.c b/source/hid/hid.c index bc94904..cf9d77c 100644 --- a/source/hid/hid.c +++ b/source/hid/hid.c @@ -6,7 +6,7 @@ #include #include "../utils/utils.h" #include "../tegraexplorer/tools.h" -#include +#include #include "../config.h" static Input_t inputs = {0}; @@ -21,11 +21,6 @@ extern hekate_config h_cfg; Input_t *hidRead(){ jc_gamepad_rpt_t *controller = joycon_poll(); - if (h_cfg.t210b01){ // Disable home and capture buttons on mariko to avoid weird behaviour - controller->home = 0; - controller->cap = 0; - } - if (controller->home) RebootToPayloadOrRcm(); diff --git a/source/hos/sept.c b/source/hos/sept.c index 5e6ef73..24fef6d 100644 --- a/source/hos/sept.c +++ b/source/hos/sept.c @@ -21,7 +21,7 @@ #include "sept.h" #include "../config.h" #include -#include +#include #include #include #include diff --git a/source/keys/keys.c b/source/keys/keys.c index 68efa4c..0380c86 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -1,7 +1,7 @@ #include "keys.h" #include "../config.h" -#include +#include #include #include "../hos/pkg1.h" #include "../hos/pkg2.h" diff --git a/source/main.c b/source/main.c index 0d8f87e..78c8507 100644 --- a/source/main.c +++ b/source/main.c @@ -20,7 +20,7 @@ #include #include "config.h" -#include +#include #include #include #include diff --git a/source/tegraexplorer/mainmenu.c b/source/tegraexplorer/mainmenu.c index 20b4c2c..6c8f030 100644 --- a/source/tegraexplorer/mainmenu.c +++ b/source/tegraexplorer/mainmenu.c @@ -15,6 +15,7 @@ #include #include "../fs/fsutils.h" #include +#include "../utils/utils.h" enum { MainExplore = 0, diff --git a/source/utils/utils.c b/source/utils/utils.c index 41b41bd..c0fc2f8 100644 --- a/source/utils/utils.c +++ b/source/utils/utils.c @@ -12,6 +12,14 @@ extern int launch_payload(char *path); +void ALWAYS_INLINE power_off(){ + power_set_state(POWER_OFF); +} + +void ALWAYS_INLINE reboot_rcm(){ + power_set_state(REBOOT_RCM); +} + void RebootToPayloadOrRcm(){ if (FileExists("sd:/atmosphere/reboot_payload.bin")) launch_payload("sd:/atmosphere/reboot_payload.bin"); diff --git a/source/utils/utils.h b/source/utils/utils.h index 74beb3f..dbf5f58 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -8,4 +8,7 @@ void WaitFor(u32 ms); void RebootToPayloadOrRcm(); #define FREE(x) free(x); x = NULL; -char *ShowKeyboard(const char *toEdit, u8 alwaysRet); \ No newline at end of file +char *ShowKeyboard(const char *toEdit, u8 alwaysRet); + +void power_off(); +void reboot_rcm(); \ No newline at end of file