0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "../dmub_srv.h"
0027 #include "dmub_reg.h"
0028 #include "dmub_dcn20.h"
0029 #include "dmub_dcn30.h"
0030
0031 #include "sienna_cichlid_ip_offset.h"
0032 #include "dcn/dcn_3_0_0_offset.h"
0033 #include "dcn/dcn_3_0_0_sh_mask.h"
0034
0035 #define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg
0036 #define CTX dmub
0037 #define REGS dmub->regs
0038
0039
0040
0041 const struct dmub_srv_common_regs dmub_srv_dcn30_regs = {
0042 #define DMUB_SR(reg) REG_OFFSET(reg),
0043 {
0044 DMUB_COMMON_REGS()
0045 DMCUB_INTERNAL_REGS()
0046 },
0047 #undef DMUB_SR
0048
0049 #define DMUB_SF(reg, field) FD_MASK(reg, field),
0050 { DMUB_COMMON_FIELDS() },
0051 #undef DMUB_SF
0052
0053 #define DMUB_SF(reg, field) FD_SHIFT(reg, field),
0054 { DMUB_COMMON_FIELDS() },
0055 #undef DMUB_SF
0056 };
0057
0058
0059
0060 static void dmub_dcn30_get_fb_base_offset(struct dmub_srv *dmub,
0061 uint64_t *fb_base,
0062 uint64_t *fb_offset)
0063 {
0064 uint32_t tmp;
0065
0066 if (dmub->fb_base || dmub->fb_offset) {
0067 *fb_base = dmub->fb_base;
0068 *fb_offset = dmub->fb_offset;
0069 return;
0070 }
0071
0072 REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp);
0073 *fb_base = (uint64_t)tmp << 24;
0074
0075 REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp);
0076 *fb_offset = (uint64_t)tmp << 24;
0077 }
0078
0079 static inline void dmub_dcn30_translate_addr(const union dmub_addr *addr_in,
0080 uint64_t fb_base,
0081 uint64_t fb_offset,
0082 union dmub_addr *addr_out)
0083 {
0084 addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
0085 }
0086
0087 void dmub_dcn30_backdoor_load(struct dmub_srv *dmub,
0088 const struct dmub_window *cw0,
0089 const struct dmub_window *cw1)
0090 {
0091 union dmub_addr offset;
0092 uint64_t fb_base, fb_offset;
0093
0094 dmub_dcn30_get_fb_base_offset(dmub, &fb_base, &fb_offset);
0095
0096 REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
0097
0098
0099
0100 dmub_dcn30_translate_addr(&cw0->offset, fb_base, fb_offset, &offset);
0101
0102 REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
0103 REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
0104 REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
0105 REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
0106 DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
0107 DMCUB_REGION3_CW0_ENABLE, 1);
0108
0109 dmub_dcn30_translate_addr(&cw1->offset, fb_base, fb_offset, &offset);
0110
0111 REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
0112 REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
0113 REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
0114 REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
0115 DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
0116 DMCUB_REGION3_CW1_ENABLE, 1);
0117
0118 REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
0119 0x20);
0120 }
0121
0122 void dmub_dcn30_setup_windows(struct dmub_srv *dmub,
0123 const struct dmub_window *cw2,
0124 const struct dmub_window *cw3,
0125 const struct dmub_window *cw4,
0126 const struct dmub_window *cw5,
0127 const struct dmub_window *cw6)
0128 {
0129 union dmub_addr offset;
0130
0131
0132
0133 offset = cw2->offset;
0134
0135 if (cw2->region.base != cw2->region.top) {
0136 REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part);
0137 REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part);
0138 REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base);
0139 REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0,
0140 DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top,
0141 DMCUB_REGION3_CW2_ENABLE, 1);
0142 } else {
0143 REG_WRITE(DMCUB_REGION3_CW2_OFFSET, 0);
0144 REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, 0);
0145 REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, 0);
0146 REG_WRITE(DMCUB_REGION3_CW2_TOP_ADDRESS, 0);
0147 }
0148
0149 offset = cw3->offset;
0150
0151 REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part);
0152 REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part);
0153 REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base);
0154 REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0,
0155 DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top,
0156 DMCUB_REGION3_CW3_ENABLE, 1);
0157
0158 offset = cw4->offset;
0159
0160
0161 if (dmub_dcn20_use_cached_inbox(dmub)) {
0162 REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
0163 REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
0164 REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
0165 REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0,
0166 DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top,
0167 DMCUB_REGION3_CW4_ENABLE, 1);
0168 } else {
0169 REG_WRITE(DMCUB_REGION4_OFFSET, offset.u.low_part);
0170 REG_WRITE(DMCUB_REGION4_OFFSET_HIGH, offset.u.high_part);
0171 REG_SET_2(DMCUB_REGION4_TOP_ADDRESS, 0,
0172 DMCUB_REGION4_TOP_ADDRESS,
0173 cw4->region.top - cw4->region.base - 1,
0174 DMCUB_REGION4_ENABLE, 1);
0175 }
0176
0177 offset = cw5->offset;
0178
0179 REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part);
0180 REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part);
0181 REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base);
0182 REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0,
0183 DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
0184 DMCUB_REGION3_CW5_ENABLE, 1);
0185
0186 REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
0187 REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
0188 REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
0189 DMCUB_REGION5_TOP_ADDRESS,
0190 cw5->region.top - cw5->region.base - 1,
0191 DMCUB_REGION5_ENABLE, 1);
0192
0193 offset = cw6->offset;
0194
0195 REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
0196 REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part);
0197 REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base);
0198 REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0,
0199 DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top,
0200 DMCUB_REGION3_CW6_ENABLE, 1);
0201 }