17c4757c2SRoman Li // SPDX-License-Identifier: MIT 27c4757c2SRoman Li // 37c4757c2SRoman Li // Copyright 2026 Advanced Micro Devices, Inc. 47c4757c2SRoman Li 57c4757c2SRoman Li #include "../dmub_srv.h" 67c4757c2SRoman Li #include "dmub_reg.h" 77c4757c2SRoman Li #include "dmub_dcn35.h" 87c4757c2SRoman Li #include "dmub_dcn401.h" 97c4757c2SRoman Li #include "dmub_dcn42.h" 107c4757c2SRoman Li 117c4757c2SRoman Li #include "dcn/dcn_4_2_0_offset.h" 127c4757c2SRoman Li #include "dcn/dcn_4_2_0_sh_mask.h" 137c4757c2SRoman Li 147c4757c2SRoman Li #define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] 157c4757c2SRoman Li #define CTX dmub 167c4757c2SRoman Li #define REGS dmub->regs_dcn42 177c4757c2SRoman Li #define REG_OFFSET_EXP(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name) 187c4757c2SRoman Li 197c4757c2SRoman Li void dmub_srv_dcn42_regs_init(struct dmub_srv *dmub, struct dc_context *ctx) 207c4757c2SRoman Li { 217c4757c2SRoman Li struct dmub_srv_dcn42_regs *regs = dmub->regs_dcn42; 227c4757c2SRoman Li #define REG_STRUCT regs 237c4757c2SRoman Li 247c4757c2SRoman Li #define DMUB_SR(reg) REG_STRUCT->offset.reg = REG_OFFSET_EXP(reg); 257c4757c2SRoman Li DMUB_DCN42_REGS() 267c4757c2SRoman Li DMCUB_INTERNAL_REGS() 277c4757c2SRoman Li #undef DMUB_SR 287c4757c2SRoman Li 297c4757c2SRoman Li #define DMUB_SF(reg, field) REG_STRUCT->mask.reg##__##field = FD_MASK(reg, field); 307c4757c2SRoman Li DMUB_DCN42_FIELDS() 317c4757c2SRoman Li #undef DMUB_SF 327c4757c2SRoman Li 337c4757c2SRoman Li #define DMUB_SF(reg, field) REG_STRUCT->shift.reg##__##field = FD_SHIFT(reg, field); 347c4757c2SRoman Li DMUB_DCN42_FIELDS() 357c4757c2SRoman Li #undef DMUB_SF 367c4757c2SRoman Li #undef REG_STRUCT 377c4757c2SRoman Li } 387c4757c2SRoman Li 397c4757c2SRoman Li void dmub_dcn42_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params) 407c4757c2SRoman Li { 417c4757c2SRoman Li union dmub_fw_boot_options boot_options = {0}; 427c4757c2SRoman Li 4371488869SMeenakshikumar Somasundaram if (!dmub->dpia_supported) { 44d77ff733SGaghik Khachatrian dmub->dpia_supported = dmub_dcn42_get_fw_boot_option(dmub).bits.enable_dpia != 0; 4571488869SMeenakshikumar Somasundaram } 467c4757c2SRoman Li 477c4757c2SRoman Li boot_options.bits.z10_disable = params->disable_z10; 487c4757c2SRoman Li boot_options.bits.dpia_supported = params->dpia_supported; 4971488869SMeenakshikumar Somasundaram boot_options.bits.enable_dpia = dmub->dpia_supported && !params->disable_dpia; 507c4757c2SRoman Li boot_options.bits.usb4_cm_version = params->usb4_cm_version; 517c4757c2SRoman Li boot_options.bits.dpia_hpd_int_enable_supported = params->dpia_hpd_int_enable_supported; 527c4757c2SRoman Li boot_options.bits.power_optimization = params->power_optimization; 537c4757c2SRoman Li boot_options.bits.disable_clk_ds = params->disallow_dispclk_dppclk_ds; 547c4757c2SRoman Li boot_options.bits.disable_clk_gate = params->disable_clock_gate; 557c4757c2SRoman Li boot_options.bits.ips_disable = params->disable_ips; 567c4757c2SRoman Li boot_options.bits.ips_sequential_ono = params->ips_sequential_ono; 577c4757c2SRoman Li boot_options.bits.disable_sldo_opt = params->disable_sldo_opt; 587c4757c2SRoman Li boot_options.bits.enable_non_transparent_setconfig = params->enable_non_transparent_setconfig; 597c4757c2SRoman Li boot_options.bits.lower_hbr3_phy_ssc = params->lower_hbr3_phy_ssc; 607c4757c2SRoman Li boot_options.bits.skip_phy_access = params->disallow_phy_access; 617c4757c2SRoman Li boot_options.bits.disable_dpia_bw_allocation = params->disable_dpia_bw_allocation; 627c4757c2SRoman Li 637c4757c2SRoman Li REG_WRITE(DMCUB_SCRATCH14, boot_options.all); 647c4757c2SRoman Li } 657c4757c2SRoman Li 667c4757c2SRoman Li static void dmub_dcn42_get_fb_base_offset(struct dmub_srv *dmub, 677c4757c2SRoman Li uint64_t *fb_base, 687c4757c2SRoman Li uint64_t *fb_offset) 697c4757c2SRoman Li { 707c4757c2SRoman Li uint32_t tmp; 717c4757c2SRoman Li 727c4757c2SRoman Li /* 737c4757c2SRoman Li if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) { 747c4757c2SRoman Li *fb_base = dmub->soc_fb_info.fb_base; 757c4757c2SRoman Li *fb_offset = dmub->soc_fb_info.fb_offset; 767c4757c2SRoman Li return; 777c4757c2SRoman Li } 787c4757c2SRoman Li */ 797c4757c2SRoman Li 807c4757c2SRoman Li REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp); 817c4757c2SRoman Li *fb_base = (uint64_t)tmp << 24; 827c4757c2SRoman Li 837c4757c2SRoman Li REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp); 847c4757c2SRoman Li *fb_offset = (uint64_t)tmp << 24; 857c4757c2SRoman Li } 867c4757c2SRoman Li 877c4757c2SRoman Li static inline void dmub_dcn42_translate_addr(const union dmub_addr *addr_in, 887c4757c2SRoman Li uint64_t fb_base, 897c4757c2SRoman Li uint64_t fb_offset, 907c4757c2SRoman Li union dmub_addr *addr_out) 917c4757c2SRoman Li { 927c4757c2SRoman Li addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset; 937c4757c2SRoman Li } 947c4757c2SRoman Li 957c4757c2SRoman Li void dmub_dcn42_reset(struct dmub_srv *dmub) 967c4757c2SRoman Li { 977c4757c2SRoman Li union dmub_gpint_data_register cmd; 987c4757c2SRoman Li const uint32_t timeout = 100000; 997c4757c2SRoman Li uint32_t in_reset, is_enabled, scratch, i, pwait_mode; 1007c4757c2SRoman Li 1017c4757c2SRoman Li REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); 1027c4757c2SRoman Li REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); 1037c4757c2SRoman Li 1047c4757c2SRoman Li if (in_reset == 0 && is_enabled != 0) { 1057c4757c2SRoman Li cmd.bits.status = 1; 1067c4757c2SRoman Li cmd.bits.command_code = DMUB_GPINT__STOP_FW; 1077c4757c2SRoman Li cmd.bits.param = 0; 1087c4757c2SRoman Li 1097c4757c2SRoman Li dmub->hw_funcs.set_gpint(dmub, cmd); 1107c4757c2SRoman Li 1117c4757c2SRoman Li for (i = 0; i < timeout; ++i) { 1127c4757c2SRoman Li if (dmub->hw_funcs.is_gpint_acked(dmub, cmd)) 1137c4757c2SRoman Li break; 1147c4757c2SRoman Li 1157c4757c2SRoman Li udelay(1); 1167c4757c2SRoman Li } 1177c4757c2SRoman Li 1187c4757c2SRoman Li for (i = 0; i < timeout; ++i) { 1197c4757c2SRoman Li scratch = REG_READ(DMCUB_SCRATCH7); 1207c4757c2SRoman Li if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) 1217c4757c2SRoman Li break; 1227c4757c2SRoman Li 1237c4757c2SRoman Li udelay(1); 1247c4757c2SRoman Li } 1257c4757c2SRoman Li 1267c4757c2SRoman Li for (i = 0; i < timeout; ++i) { 1277c4757c2SRoman Li REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode); 1287c4757c2SRoman Li if (pwait_mode & (1 << 0)) 1297c4757c2SRoman Li break; 1307c4757c2SRoman Li 1317c4757c2SRoman Li udelay(1); 1327c4757c2SRoman Li } 1337c4757c2SRoman Li /* Force reset in case we timed out, DMCUB is likely hung. */ 1347c4757c2SRoman Li } 1357c4757c2SRoman Li 1367c4757c2SRoman Li if (is_enabled) { 1377c4757c2SRoman Li REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); 1387c4757c2SRoman Li udelay(1); 1397c4757c2SRoman Li REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); 1407c4757c2SRoman Li } 1417c4757c2SRoman Li 1427c4757c2SRoman Li REG_WRITE(DMCUB_INBOX1_RPTR, 0); 1437c4757c2SRoman Li REG_WRITE(DMCUB_INBOX1_WPTR, 0); 1447c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); 1457c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX1_WPTR, 0); 1467c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX0_RPTR, 0); 1477c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX0_WPTR, 0); 1487c4757c2SRoman Li REG_WRITE(DMCUB_SCRATCH0, 0); 1497c4757c2SRoman Li 1507c4757c2SRoman Li /* Clear the GPINT command manually so we don't send anything during boot. */ 1517c4757c2SRoman Li cmd.all = 0; 1527c4757c2SRoman Li dmub->hw_funcs.set_gpint(dmub, cmd); 1537c4757c2SRoman Li } 1547c4757c2SRoman Li 1557c4757c2SRoman Li void dmub_dcn42_reset_release(struct dmub_srv *dmub) 1567c4757c2SRoman Li { 1577c4757c2SRoman Li REG_WRITE(DMCUB_SCRATCH15, dmub->psp_version & 0x001100FF); 1587c4757c2SRoman Li 1597c4757c2SRoman Li REG_UPDATE_3(DMU_CLK_CNTL, 1607c4757c2SRoman Li LONO_DISPCLK_GATE_DISABLE, 1, 1617c4757c2SRoman Li LONO_SOCCLK_GATE_DISABLE, 1, 1627c4757c2SRoman Li LONO_DMCUBCLK_GATE_DISABLE, 1); 1637c4757c2SRoman Li 1647c4757c2SRoman Li REG_UPDATE_2(DMCUB_CNTL, DMCUB_ENABLE, 1, DMCUB_TRACEPORT_EN, 1); 1657c4757c2SRoman Li REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 0); 1667c4757c2SRoman Li REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 0); 1677c4757c2SRoman Li } 1687c4757c2SRoman Li 1697c4757c2SRoman Li void dmub_dcn42_backdoor_load(struct dmub_srv *dmub, 1707c4757c2SRoman Li const struct dmub_window *cw0, 1717c4757c2SRoman Li const struct dmub_window *cw1) 1727c4757c2SRoman Li { 1737c4757c2SRoman Li union dmub_addr offset; 1747c4757c2SRoman Li uint64_t fb_base, fb_offset; 1757c4757c2SRoman Li 1767c4757c2SRoman Li dmub_dcn42_get_fb_base_offset(dmub, &fb_base, &fb_offset); 1777c4757c2SRoman Li 1787c4757c2SRoman Li dmub_dcn42_translate_addr(&cw0->offset, fb_base, fb_offset, &offset); 1797c4757c2SRoman Li 1807c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part); 1817c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part); 1827c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base); 1837c4757c2SRoman Li REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0, 1847c4757c2SRoman Li DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top, 1857c4757c2SRoman Li DMCUB_REGION3_CW0_ENABLE, 1); 1867c4757c2SRoman Li 1877c4757c2SRoman Li dmub_dcn42_translate_addr(&cw1->offset, fb_base, fb_offset, &offset); 1887c4757c2SRoman Li 1897c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part); 1907c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part); 1917c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base); 1927c4757c2SRoman Li REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0, 1937c4757c2SRoman Li DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, 1947c4757c2SRoman Li DMCUB_REGION3_CW1_ENABLE, 1); 1957c4757c2SRoman Li 1967c4757c2SRoman Li /* TODO: Do we need to set DMCUB_MEM_UNIT_ID? */ 1977c4757c2SRoman Li REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0); 1987c4757c2SRoman Li } 1997c4757c2SRoman Li 2007c4757c2SRoman Li void dmub_dcn42_backdoor_load_zfb_mode(struct dmub_srv *dmub, 2017c4757c2SRoman Li const struct dmub_window *cw0, 2027c4757c2SRoman Li const struct dmub_window *cw1) 2037c4757c2SRoman Li { 2047c4757c2SRoman Li union dmub_addr offset; 2057c4757c2SRoman Li 2067c4757c2SRoman Li REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); 2077c4757c2SRoman Li offset = cw0->offset; 2087c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part); 2097c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part); 2107c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base); 2117c4757c2SRoman Li REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0, 2127c4757c2SRoman Li DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top, 2137c4757c2SRoman Li DMCUB_REGION3_CW0_ENABLE, 1); 2147c4757c2SRoman Li offset = cw1->offset; 2157c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part); 2167c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part); 2177c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base); 2187c4757c2SRoman Li REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0, 2197c4757c2SRoman Li DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, 2207c4757c2SRoman Li DMCUB_REGION3_CW1_ENABLE, 1); 2217c4757c2SRoman Li REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, 2227c4757c2SRoman Li 0x20); 2237c4757c2SRoman Li } 2247c4757c2SRoman Li void dmub_dcn42_setup_windows(struct dmub_srv *dmub, 2257c4757c2SRoman Li const struct dmub_window *cw2, 2267c4757c2SRoman Li const struct dmub_window *cw3, 2277c4757c2SRoman Li const struct dmub_window *cw4, 2287c4757c2SRoman Li const struct dmub_window *cw5, 2297c4757c2SRoman Li const struct dmub_window *cw6, 2307c4757c2SRoman Li const struct dmub_window *region6) 2317c4757c2SRoman Li { 232*c3f327a9SGaghik Khachatrian (void)cw2; 2337c4757c2SRoman Li union dmub_addr offset; 2347c4757c2SRoman Li 2357c4757c2SRoman Li offset = cw3->offset; 2367c4757c2SRoman Li 2377c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part); 2387c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part); 2397c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base); 2407c4757c2SRoman Li REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0, 2417c4757c2SRoman Li DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top, 2427c4757c2SRoman Li DMCUB_REGION3_CW3_ENABLE, 1); 2437c4757c2SRoman Li 2447c4757c2SRoman Li offset = cw4->offset; 2457c4757c2SRoman Li 2467c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part); 2477c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part); 2487c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base); 2497c4757c2SRoman Li REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0, 2507c4757c2SRoman Li DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top, 2517c4757c2SRoman Li DMCUB_REGION3_CW4_ENABLE, 1); 2527c4757c2SRoman Li 2537c4757c2SRoman Li offset = cw5->offset; 2547c4757c2SRoman Li 2557c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part); 2567c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part); 2577c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base); 2587c4757c2SRoman Li REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0, 2597c4757c2SRoman Li DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top, 2607c4757c2SRoman Li DMCUB_REGION3_CW5_ENABLE, 1); 2617c4757c2SRoman Li 2627c4757c2SRoman Li REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part); 2637c4757c2SRoman Li REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part); 2647c4757c2SRoman Li REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0, 2657c4757c2SRoman Li DMCUB_REGION5_TOP_ADDRESS, 2667c4757c2SRoman Li cw5->region.top - cw5->region.base - 1, 2677c4757c2SRoman Li DMCUB_REGION5_ENABLE, 1); 2687c4757c2SRoman Li 2697c4757c2SRoman Li offset = cw6->offset; 2707c4757c2SRoman Li 2717c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part); 2727c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part); 2737c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base); 2747c4757c2SRoman Li REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0, 2757c4757c2SRoman Li DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top, 2767c4757c2SRoman Li DMCUB_REGION3_CW6_ENABLE, 1); 2777c4757c2SRoman Li 2787c4757c2SRoman Li offset = region6->offset; 2797c4757c2SRoman Li 2807c4757c2SRoman Li REG_WRITE(DMCUB_REGION6_OFFSET, offset.u.low_part); 2817c4757c2SRoman Li REG_WRITE(DMCUB_REGION6_OFFSET_HIGH, offset.u.high_part); 2827c4757c2SRoman Li REG_SET_2(DMCUB_REGION6_TOP_ADDRESS, 0, 2837c4757c2SRoman Li DMCUB_REGION6_TOP_ADDRESS, 2847c4757c2SRoman Li region6->region.top - region6->region.base - 1, 2857c4757c2SRoman Li DMCUB_REGION6_ENABLE, 1); 2867c4757c2SRoman Li } 2877c4757c2SRoman Li 2887c4757c2SRoman Li uint32_t dmub_dcn42_get_inbox1_wptr(struct dmub_srv *dmub) 2897c4757c2SRoman Li { 2907c4757c2SRoman Li return REG_READ(DMCUB_INBOX1_WPTR); 2917c4757c2SRoman Li } 2927c4757c2SRoman Li 2937c4757c2SRoman Li uint32_t dmub_dcn42_get_inbox1_rptr(struct dmub_srv *dmub) 2947c4757c2SRoman Li { 2957c4757c2SRoman Li return REG_READ(DMCUB_INBOX1_RPTR); 2967c4757c2SRoman Li } 2977c4757c2SRoman Li 2987c4757c2SRoman Li void dmub_dcn42_setup_out_mailbox(struct dmub_srv *dmub, 2997c4757c2SRoman Li const struct dmub_region *outbox1) 3007c4757c2SRoman Li { 3017c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, outbox1->base); 3027c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX1_SIZE, outbox1->top - outbox1->base); 3037c4757c2SRoman Li } 3047c4757c2SRoman Li 3057c4757c2SRoman Li uint32_t dmub_dcn42_get_outbox1_wptr(struct dmub_srv *dmub) 3067c4757c2SRoman Li { 3077c4757c2SRoman Li /** 3087c4757c2SRoman Li * outbox1 wptr register is accessed without locks (dal & dc) 3097c4757c2SRoman Li * and to be called only by dmub_srv_stat_get_notification() 3107c4757c2SRoman Li */ 3117c4757c2SRoman Li return REG_READ(DMCUB_OUTBOX1_WPTR); 3127c4757c2SRoman Li } 3137c4757c2SRoman Li 3147c4757c2SRoman Li void dmub_dcn42_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset) 3157c4757c2SRoman Li { 3167c4757c2SRoman Li /** 3177c4757c2SRoman Li * outbox1 rptr register is accessed without locks (dal & dc) 3187c4757c2SRoman Li * and to be called only by dmub_srv_stat_get_notification() 3197c4757c2SRoman Li */ 3207c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset); 3217c4757c2SRoman Li } 3227c4757c2SRoman Li 3237c4757c2SRoman Li bool dmub_dcn42_is_supported(struct dmub_srv *dmub) 3247c4757c2SRoman Li { 325e6d5acadSGabe Teeger // DCN without DMUB is not a supported configuration; safe to assume that it is always 326e6d5acadSGabe Teeger // present. 327e6d5acadSGabe Teeger return true; 3287c4757c2SRoman Li } 3297c4757c2SRoman Li 3307c4757c2SRoman Li union dmub_fw_boot_options dmub_dcn42_get_fw_boot_option(struct dmub_srv *dmub) 3317c4757c2SRoman Li { 3327c4757c2SRoman Li union dmub_fw_boot_options option; 3337c4757c2SRoman Li 3347c4757c2SRoman Li option.all = REG_READ(DMCUB_SCRATCH14); 3357c4757c2SRoman Li return option; 3367c4757c2SRoman Li } 3377c4757c2SRoman Li 3387c4757c2SRoman Li void dmub_dcn42_setup_outbox0(struct dmub_srv *dmub, 3397c4757c2SRoman Li const struct dmub_region *outbox0) 3407c4757c2SRoman Li { 3417c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX0_BASE_ADDRESS, outbox0->base); 3427c4757c2SRoman Li 3437c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX0_SIZE, outbox0->top - outbox0->base); 3447c4757c2SRoman Li } 3457c4757c2SRoman Li 3467c4757c2SRoman Li bool dmub_dcn42_should_detect(struct dmub_srv *dmub) 3477c4757c2SRoman Li { 3487c4757c2SRoman Li uint32_t fw_boot_status = REG_READ(DMCUB_SCRATCH0); 3497c4757c2SRoman Li bool should_detect = (fw_boot_status & DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED) != 0; 3507c4757c2SRoman Li return should_detect; 3517c4757c2SRoman Li } 3527c4757c2SRoman Li 3537c4757c2SRoman Li void dmub_dcn42_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data) 3547c4757c2SRoman Li { 3557c4757c2SRoman Li REG_WRITE(DMCUB_INBOX0_WPTR, data.inbox0_cmd_common.all); 3567c4757c2SRoman Li } 3577c4757c2SRoman Li 3587c4757c2SRoman Li uint32_t dmub_dcn42_read_inbox0_ack_register(struct dmub_srv *dmub) 3597c4757c2SRoman Li { 3607c4757c2SRoman Li return REG_READ(DMCUB_SCRATCH17); 3617c4757c2SRoman Li } 3627c4757c2SRoman Li 3637c4757c2SRoman Li bool dmub_dcn42_is_hw_powered_up(struct dmub_srv *dmub) 3647c4757c2SRoman Li { 3657c4757c2SRoman Li union dmub_fw_boot_status status; 3667c4757c2SRoman Li uint32_t is_enable; 3677c4757c2SRoman Li 3687c4757c2SRoman Li REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enable); 3697c4757c2SRoman Li if (is_enable == 0) 3707c4757c2SRoman Li return false; 3717c4757c2SRoman Li 3727c4757c2SRoman Li status.all = REG_READ(DMCUB_SCRATCH0); 3737c4757c2SRoman Li 3747c4757c2SRoman Li return (status.bits.dal_fw && status.bits.hw_power_init_done && status.bits.mailbox_rdy) || 3757c4757c2SRoman Li (!status.bits.dal_fw && status.bits.mailbox_rdy); 3767c4757c2SRoman Li } 3777c4757c2SRoman Li 3787c4757c2SRoman Li void dmub_dcn42_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset) 3797c4757c2SRoman Li { 3807c4757c2SRoman Li REG_WRITE(DMCUB_INBOX1_WPTR, wptr_offset); 3817c4757c2SRoman Li } 3827c4757c2SRoman Li 3837c4757c2SRoman Li bool dmub_dcn42_is_hw_init(struct dmub_srv *dmub) 3847c4757c2SRoman Li { 3857c4757c2SRoman Li union dmub_fw_boot_status status; 3867c4757c2SRoman Li uint32_t is_hw_init; 3877c4757c2SRoman Li 3887c4757c2SRoman Li status.all = REG_READ(DMCUB_SCRATCH0); 3897c4757c2SRoman Li REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init); 3907c4757c2SRoman Li 3917c4757c2SRoman Li return is_hw_init != 0 && status.bits.dal_fw; 3927c4757c2SRoman Li } 3937c4757c2SRoman Li 3947c4757c2SRoman Li union dmub_fw_boot_status dmub_dcn42_get_fw_boot_status(struct dmub_srv *dmub) 3957c4757c2SRoman Li { 3967c4757c2SRoman Li union dmub_fw_boot_status status; 3977c4757c2SRoman Li 3987c4757c2SRoman Li status.all = REG_READ(DMCUB_SCRATCH0); 3997c4757c2SRoman Li return status; 4007c4757c2SRoman Li } 4017c4757c2SRoman Li 4027c4757c2SRoman Li void dmub_dcn42_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip) 4037c4757c2SRoman Li { 4047c4757c2SRoman Li union dmub_fw_boot_options boot_options; 4057c4757c2SRoman Li boot_options.all = REG_READ(DMCUB_SCRATCH14); 4067c4757c2SRoman Li boot_options.bits.skip_phy_init_panel_sequence = skip; 4077c4757c2SRoman Li REG_WRITE(DMCUB_SCRATCH14, boot_options.all); 4087c4757c2SRoman Li } 4097c4757c2SRoman Li 4107c4757c2SRoman Li void dmub_dcn42_configure_dmub_in_system_memory(struct dmub_srv *dmub) 4117c4757c2SRoman Li { 4127c4757c2SRoman Li /* DMCUB_REGION3_TMR_AXI_SPACE values: 4137c4757c2SRoman Li * 0b011 (0x3) - FB physical address 4147c4757c2SRoman Li * 0b100 (0x4) - GPU virtual address 4157c4757c2SRoman Li * 4167c4757c2SRoman Li * Default value is 0x3 (FB Physical address for TMR). When programming 4177c4757c2SRoman Li * DMUB to be in system memory, change to 0x4. The system memory allocated 4187c4757c2SRoman Li * is accessible by both GPU and CPU, so we use GPU virtual address. 4197c4757c2SRoman Li */ 4207c4757c2SRoman Li REG_WRITE(DMCUB_REGION3_TMR_AXI_SPACE, 0x4); 4217c4757c2SRoman Li } 4227c4757c2SRoman Li 4237c4757c2SRoman Li void dmub_dcn42_clear_inbox0_ack_register(struct dmub_srv *dmub) 4247c4757c2SRoman Li { 4257c4757c2SRoman Li REG_WRITE(DMCUB_SCRATCH17, 0); 4267c4757c2SRoman Li } 4277c4757c2SRoman Li 4287c4757c2SRoman Li void dmub_dcn42_send_reg_inbox0_cmd_msg(struct dmub_srv *dmub, 4297c4757c2SRoman Li union dmub_rb_cmd *cmd) 4307c4757c2SRoman Li { 4317c4757c2SRoman Li uint32_t *dwords = (uint32_t *)cmd; 4327c4757c2SRoman Li int32_t payload_size_bytes = cmd->cmd_common.header.payload_bytes; 4337c4757c2SRoman Li uint32_t msg_index; 4347c4757c2SRoman Li static_assert(sizeof(*cmd) == 64, "DMUB command size mismatch"); 4357c4757c2SRoman Li 4367c4757c2SRoman Li /* read remaining data based on payload size */ 4377c4757c2SRoman Li for (msg_index = 0; msg_index < 15; msg_index++) { 4387c4757c2SRoman Li if (payload_size_bytes <= msg_index * 4) { 4397c4757c2SRoman Li break; 4407c4757c2SRoman Li } 4417c4757c2SRoman Li 4427c4757c2SRoman Li switch (msg_index) { 4437c4757c2SRoman Li case 0: 4447c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG0, dwords[msg_index + 1]); 4457c4757c2SRoman Li break; 4467c4757c2SRoman Li case 1: 4477c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG1, dwords[msg_index + 1]); 4487c4757c2SRoman Li break; 4497c4757c2SRoman Li case 2: 4507c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG2, dwords[msg_index + 1]); 4517c4757c2SRoman Li break; 4527c4757c2SRoman Li case 3: 4537c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG3, dwords[msg_index + 1]); 4547c4757c2SRoman Li break; 4557c4757c2SRoman Li case 4: 4567c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG4, dwords[msg_index + 1]); 4577c4757c2SRoman Li break; 4587c4757c2SRoman Li case 5: 4597c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG5, dwords[msg_index + 1]); 4607c4757c2SRoman Li break; 4617c4757c2SRoman Li case 6: 4627c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG6, dwords[msg_index + 1]); 4637c4757c2SRoman Li break; 4647c4757c2SRoman Li case 7: 4657c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG7, dwords[msg_index + 1]); 4667c4757c2SRoman Li break; 4677c4757c2SRoman Li case 8: 4687c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG8, dwords[msg_index + 1]); 4697c4757c2SRoman Li break; 4707c4757c2SRoman Li case 9: 4717c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG9, dwords[msg_index + 1]); 4727c4757c2SRoman Li break; 4737c4757c2SRoman Li case 10: 4747c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG10, dwords[msg_index + 1]); 4757c4757c2SRoman Li break; 4767c4757c2SRoman Li case 11: 4777c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG11, dwords[msg_index + 1]); 4787c4757c2SRoman Li break; 4797c4757c2SRoman Li case 12: 4807c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG12, dwords[msg_index + 1]); 4817c4757c2SRoman Li break; 4827c4757c2SRoman Li case 13: 4837c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG13, dwords[msg_index + 1]); 4847c4757c2SRoman Li break; 4857c4757c2SRoman Li case 14: 4867c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_MSG14, dwords[msg_index + 1]); 4877c4757c2SRoman Li break; 4887c4757c2SRoman Li } 4897c4757c2SRoman Li } 4907c4757c2SRoman Li 4917c4757c2SRoman Li /* writing to INBOX RDY register will trigger DMUB REG INBOX0 RDY 4927c4757c2SRoman Li * interrupt. 4937c4757c2SRoman Li */ 4947c4757c2SRoman Li REG_WRITE(DMCUB_REG_INBOX0_RDY, dwords[0]); 4957c4757c2SRoman Li } 4967c4757c2SRoman Li 4977c4757c2SRoman Li uint32_t dmub_dcn42_read_reg_inbox0_rsp_int_status(struct dmub_srv *dmub) 4987c4757c2SRoman Li { 4997c4757c2SRoman Li uint32_t status; 5007c4757c2SRoman Li 5017c4757c2SRoman Li REG_GET(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_STAT, &status); 5027c4757c2SRoman Li return status; 5037c4757c2SRoman Li } 5047c4757c2SRoman Li 5057c4757c2SRoman Li void dmub_dcn42_read_reg_inbox0_cmd_rsp(struct dmub_srv *dmub, 5067c4757c2SRoman Li union dmub_rb_cmd *cmd) 5077c4757c2SRoman Li { 5087c4757c2SRoman Li uint32_t *dwords = (uint32_t *)cmd; 5097c4757c2SRoman Li 5107c4757c2SRoman Li static_assert(sizeof(*cmd) == 64, "DMUB command size mismatch"); 5117c4757c2SRoman Li 5127c4757c2SRoman Li dwords[0] = REG_READ(DMCUB_REG_INBOX0_RSP); 5137c4757c2SRoman Li dwords[1] = REG_READ(DMCUB_REG_INBOX0_MSG0); 5147c4757c2SRoman Li dwords[2] = REG_READ(DMCUB_REG_INBOX0_MSG1); 5157c4757c2SRoman Li dwords[3] = REG_READ(DMCUB_REG_INBOX0_MSG2); 5167c4757c2SRoman Li dwords[4] = REG_READ(DMCUB_REG_INBOX0_MSG3); 5177c4757c2SRoman Li dwords[5] = REG_READ(DMCUB_REG_INBOX0_MSG4); 5187c4757c2SRoman Li dwords[6] = REG_READ(DMCUB_REG_INBOX0_MSG5); 5197c4757c2SRoman Li dwords[7] = REG_READ(DMCUB_REG_INBOX0_MSG6); 5207c4757c2SRoman Li dwords[8] = REG_READ(DMCUB_REG_INBOX0_MSG7); 5217c4757c2SRoman Li dwords[9] = REG_READ(DMCUB_REG_INBOX0_MSG8); 5227c4757c2SRoman Li dwords[10] = REG_READ(DMCUB_REG_INBOX0_MSG9); 5237c4757c2SRoman Li dwords[11] = REG_READ(DMCUB_REG_INBOX0_MSG10); 5247c4757c2SRoman Li dwords[12] = REG_READ(DMCUB_REG_INBOX0_MSG11); 5257c4757c2SRoman Li dwords[13] = REG_READ(DMCUB_REG_INBOX0_MSG12); 5267c4757c2SRoman Li dwords[14] = REG_READ(DMCUB_REG_INBOX0_MSG13); 5277c4757c2SRoman Li dwords[15] = REG_READ(DMCUB_REG_INBOX0_MSG14); 5287c4757c2SRoman Li } 5297c4757c2SRoman Li 5307c4757c2SRoman Li void dmub_dcn42_write_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub) 5317c4757c2SRoman Li { 5327c4757c2SRoman Li REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK, 1); 5337c4757c2SRoman Li } 5347c4757c2SRoman Li 5357c4757c2SRoman Li void dmub_dcn42_clear_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub) 5367c4757c2SRoman Li { 5377c4757c2SRoman Li REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK, 0); 5387c4757c2SRoman Li } 5397c4757c2SRoman Li 5407c4757c2SRoman Li void dmub_dcn42_enable_reg_inbox0_rsp_int(struct dmub_srv *dmub, bool enable) 5417c4757c2SRoman Li { 5427c4757c2SRoman Li REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN, enable ? 1:0); 5437c4757c2SRoman Li } 5447c4757c2SRoman Li 5457c4757c2SRoman Li void dmub_dcn42_write_reg_outbox0_rdy_int_ack(struct dmub_srv *dmub) 5467c4757c2SRoman Li { 5477c4757c2SRoman Li REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK, 1); 5487c4757c2SRoman Li REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK, 0); 5497c4757c2SRoman Li } 5507c4757c2SRoman Li 5517c4757c2SRoman Li void dmub_dcn42_read_reg_outbox0_msg(struct dmub_srv *dmub, uint32_t *msg) 5527c4757c2SRoman Li { 5537c4757c2SRoman Li *msg = REG_READ(DMCUB_REG_OUTBOX0_MSG0); 5547c4757c2SRoman Li } 5557c4757c2SRoman Li 5567c4757c2SRoman Li 5577c4757c2SRoman Li void dmub_dcn42_enable_reg_outbox0_rdy_int(struct dmub_srv *dmub, bool enable) 5587c4757c2SRoman Li { 5597c4757c2SRoman Li REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN, enable ? 1:0); 5607c4757c2SRoman Li } 5617c4757c2SRoman Li 5627c4757c2SRoman Li uint32_t dmub_dcn42_read_reg_outbox0_rdy_int_status(struct dmub_srv *dmub) 5637c4757c2SRoman Li { 5647c4757c2SRoman Li uint32_t status; 5657c4757c2SRoman Li 5667c4757c2SRoman Li REG_GET(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT, &status); 5677c4757c2SRoman Li return status; 5687c4757c2SRoman Li } 5697c4757c2SRoman Li 5707c4757c2SRoman Li void dmub_dcn42_setup_mailbox(struct dmub_srv *dmub, 5717c4757c2SRoman Li const struct dmub_region *inbox1) 5727c4757c2SRoman Li { 5737c4757c2SRoman Li REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, inbox1->base); 5747c4757c2SRoman Li REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base); 5757c4757c2SRoman Li } 5767c4757c2SRoman Li 5777c4757c2SRoman Li void dmub_dcn42_set_gpint(struct dmub_srv *dmub, 5787c4757c2SRoman Li union dmub_gpint_data_register reg) 5797c4757c2SRoman Li { 5807c4757c2SRoman Li REG_WRITE(DMCUB_GPINT_DATAIN1, reg.all); 5817c4757c2SRoman Li } 5827c4757c2SRoman Li 5837c4757c2SRoman Li bool dmub_dcn42_is_gpint_acked(struct dmub_srv *dmub, 5847c4757c2SRoman Li union dmub_gpint_data_register reg) 5857c4757c2SRoman Li { 5867c4757c2SRoman Li union dmub_gpint_data_register test; 5877c4757c2SRoman Li 5887c4757c2SRoman Li reg.bits.status = 0; 5897c4757c2SRoman Li test.all = REG_READ(DMCUB_GPINT_DATAIN1); 5907c4757c2SRoman Li 5917c4757c2SRoman Li return test.all == reg.all; 5927c4757c2SRoman Li } 5937c4757c2SRoman Li 5947c4757c2SRoman Li uint32_t dmub_dcn42_get_gpint_response(struct dmub_srv *dmub) 5957c4757c2SRoman Li { 5967c4757c2SRoman Li return REG_READ(DMCUB_SCRATCH7); 5977c4757c2SRoman Li } 5987c4757c2SRoman Li 5997c4757c2SRoman Li uint32_t dmub_dcn42_get_gpint_dataout(struct dmub_srv *dmub) 6007c4757c2SRoman Li { 6017c4757c2SRoman Li uint32_t dataout = REG_READ(DMCUB_GPINT_DATAOUT); 6027c4757c2SRoman Li 6037c4757c2SRoman Li REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 0); 6047c4757c2SRoman Li 6057c4757c2SRoman Li REG_WRITE(DMCUB_GPINT_DATAOUT, 0); 6067c4757c2SRoman Li REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 1); 6077c4757c2SRoman Li REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 0); 6087c4757c2SRoman Li 6097c4757c2SRoman Li REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 1); 6107c4757c2SRoman Li 6117c4757c2SRoman Li return dataout; 6127c4757c2SRoman Li } 6137c4757c2SRoman Li 6147c4757c2SRoman Li uint32_t dmub_dcn42_get_outbox0_wptr(struct dmub_srv *dmub) 6157c4757c2SRoman Li { 6167c4757c2SRoman Li return REG_READ(DMCUB_OUTBOX0_WPTR); 6177c4757c2SRoman Li } 6187c4757c2SRoman Li 6197c4757c2SRoman Li void dmub_dcn42_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset) 6207c4757c2SRoman Li { 6217c4757c2SRoman Li REG_WRITE(DMCUB_OUTBOX0_RPTR, rptr_offset); 6227c4757c2SRoman Li } 6237c4757c2SRoman Li 6247c4757c2SRoman Li uint32_t dmub_dcn42_get_current_time(struct dmub_srv *dmub) 6257c4757c2SRoman Li { 6267c4757c2SRoman Li return REG_READ(DMCUB_TIMER_CURRENT); 6277c4757c2SRoman Li } 6287c4757c2SRoman Li 6297c4757c2SRoman Li void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub) 6307c4757c2SRoman Li { 6317c4757c2SRoman Li uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset, is_pwait; 6327c4757c2SRoman Li uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; 6337c4757c2SRoman Li struct dmub_timeout_info timeout = {0}; 6347c4757c2SRoman Li 6357c4757c2SRoman Li if (!dmub) 6367c4757c2SRoman Li return; 6377c4757c2SRoman Li 6387c4757c2SRoman Li /* timeout data filled externally, cache before resetting memory */ 6397c4757c2SRoman Li timeout = dmub->debug.timeout_info; 6407c4757c2SRoman Li memset(&dmub->debug, 0, sizeof(dmub->debug)); 6417c4757c2SRoman Li dmub->debug.timeout_info = timeout; 6427c4757c2SRoman Li 6437c4757c2SRoman Li dmub->debug.dmcub_version = dmub->fw_version; 6447c4757c2SRoman Li 6457c4757c2SRoman Li dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); 6467c4757c2SRoman Li dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); 6477c4757c2SRoman Li dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); 6487c4757c2SRoman Li dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); 6497c4757c2SRoman Li dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); 6507c4757c2SRoman Li dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); 6517c4757c2SRoman Li dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); 6527c4757c2SRoman Li dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); 6537c4757c2SRoman Li dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); 6547c4757c2SRoman Li dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); 6557c4757c2SRoman Li dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); 6567c4757c2SRoman Li dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); 6577c4757c2SRoman Li dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); 6587c4757c2SRoman Li dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); 6597c4757c2SRoman Li dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); 6607c4757c2SRoman Li dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); 6617c4757c2SRoman Li dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16); 6627c4757c2SRoman Li 6637c4757c2SRoman Li dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); 6647c4757c2SRoman Li dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); 6657c4757c2SRoman Li dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); 6667c4757c2SRoman Li 6677c4757c2SRoman Li dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); 6687c4757c2SRoman Li dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); 6697c4757c2SRoman Li dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); 6707c4757c2SRoman Li 6717c4757c2SRoman Li dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); 6727c4757c2SRoman Li dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); 6737c4757c2SRoman Li dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); 6747c4757c2SRoman Li 6757c4757c2SRoman Li dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); 6767c4757c2SRoman Li dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); 6777c4757c2SRoman Li dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); 6787c4757c2SRoman Li 6797c4757c2SRoman Li REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); 680d77ff733SGaghik Khachatrian ASSERT(is_dmub_enabled <= 0xFF); 681d77ff733SGaghik Khachatrian dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; 6827c4757c2SRoman Li 6837c4757c2SRoman Li REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); 684d77ff733SGaghik Khachatrian ASSERT(is_pwait <= 0xFF); 685d77ff733SGaghik Khachatrian dmub->debug.is_pwait = (uint8_t)is_pwait; 6867c4757c2SRoman Li 6877c4757c2SRoman Li REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); 688d77ff733SGaghik Khachatrian ASSERT(is_soft_reset <= 0xFF); 689d77ff733SGaghik Khachatrian dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; 6907c4757c2SRoman Li 6917c4757c2SRoman Li REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); 692d77ff733SGaghik Khachatrian ASSERT(is_sec_reset <= 0xFF); 693d77ff733SGaghik Khachatrian dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; 6947c4757c2SRoman Li 6957c4757c2SRoman Li REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); 696d77ff733SGaghik Khachatrian ASSERT(is_traceport_enabled <= 0xFF); 697d77ff733SGaghik Khachatrian dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; 6987c4757c2SRoman Li 6997c4757c2SRoman Li REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); 700d77ff733SGaghik Khachatrian ASSERT(is_cw0_enabled <= 0xFF); 701d77ff733SGaghik Khachatrian dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; 7027c4757c2SRoman Li 7037c4757c2SRoman Li REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); 704d77ff733SGaghik Khachatrian ASSERT(is_cw6_enabled <= 0xFF); 705d77ff733SGaghik Khachatrian dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; 7067c4757c2SRoman Li 7077c4757c2SRoman Li dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); 7087c4757c2SRoman Li } 7097c4757c2SRoman Li 7107c4757c2SRoman Li bool dmub_dcn42_get_preos_fw_info(struct dmub_srv *dmub) 7117c4757c2SRoman Li { 7127c4757c2SRoman Li uint64_t region3_cw5_offset; 7137c4757c2SRoman Li uint32_t top_addr, top_addr_enable, offset_low; 7147c4757c2SRoman Li uint32_t offset_high, base_addr, fw_version; 7157c4757c2SRoman Li bool is_vbios_fw = false; 7167c4757c2SRoman Li 7177c4757c2SRoman Li memset(&dmub->preos_info, 0, sizeof(dmub->preos_info)); 7187c4757c2SRoman Li 7197c4757c2SRoman Li fw_version = REG_READ(DMCUB_SCRATCH1); 7207c4757c2SRoman Li is_vbios_fw = ((fw_version >> 6) & 0x01) ? true : false; 7217c4757c2SRoman Li if (!is_vbios_fw) 7227c4757c2SRoman Li return false; 7237c4757c2SRoman Li 7247c4757c2SRoman Li dmub->preos_info.boot_status = REG_READ(DMCUB_SCRATCH0); 7257c4757c2SRoman Li dmub->preos_info.fw_version = REG_READ(DMCUB_SCRATCH1); 7267c4757c2SRoman Li dmub->preos_info.boot_options = REG_READ(DMCUB_SCRATCH14); 7277c4757c2SRoman Li REG_GET(DMCUB_REGION3_CW5_TOP_ADDRESS, 7287c4757c2SRoman Li DMCUB_REGION3_CW5_ENABLE, &top_addr_enable); 7297c4757c2SRoman Li if (top_addr_enable) { 7307c4757c2SRoman Li dmub_dcn42_get_fb_base_offset(dmub, 7317c4757c2SRoman Li &dmub->preos_info.fb_base, &dmub->preos_info.fb_offset); 7327c4757c2SRoman Li offset_low = REG_READ(DMCUB_REGION3_CW5_OFFSET); 7337c4757c2SRoman Li offset_high = REG_READ(DMCUB_REGION3_CW5_OFFSET_HIGH); 7347c4757c2SRoman Li region3_cw5_offset = ((uint64_t)offset_high << 32) | offset_low; 7357c4757c2SRoman Li dmub->preos_info.trace_buffer_phy_addr = region3_cw5_offset 7367c4757c2SRoman Li - dmub->preos_info.fb_base + dmub->preos_info.fb_offset; 7377c4757c2SRoman Li 7387c4757c2SRoman Li REG_GET(DMCUB_REGION3_CW5_TOP_ADDRESS, 7397c4757c2SRoman Li DMCUB_REGION3_CW5_TOP_ADDRESS, &top_addr); 7407c4757c2SRoman Li base_addr = REG_READ(DMCUB_REGION3_CW5_BASE_ADDRESS) & 0x1FFFFFFF; 7417c4757c2SRoman Li dmub->preos_info.trace_buffer_size = 7427c4757c2SRoman Li (top_addr > base_addr) ? (top_addr - base_addr + 1) : 0; 7437c4757c2SRoman Li } 7447c4757c2SRoman Li 7457c4757c2SRoman Li return true; 7467c4757c2SRoman Li } 7477c4757c2SRoman Li 7487c4757c2SRoman Li void dmub_dcn42_write_reg_outbox0_rsp(struct dmub_srv *dmub, uint32_t *rsp) 7497c4757c2SRoman Li { 7507c4757c2SRoman Li REG_WRITE(DMCUB_REG_OUTBOX0_RSP, *rsp); 7517c4757c2SRoman Li } 7527c4757c2SRoman Li 7537c4757c2SRoman Li uint32_t dmub_dcn42_read_reg_outbox0_rsp_int_status(struct dmub_srv *dmub) 7547c4757c2SRoman Li { 7557c4757c2SRoman Li uint32_t status; 7567c4757c2SRoman Li 7577c4757c2SRoman Li REG_GET(DMCUB_INTERRUPT_STATUS, DMCUB_REG_OUTBOX0_RSP_INT_STAT, &status); 7587c4757c2SRoman Li return status; 7597c4757c2SRoman Li } 760