Line data Source code
1 : /*
2 : * Copyright 2020 Advanced Micro Devices, Inc.
3 : *
4 : * Permission is hereby granted, free of charge, to any person obtaining a
5 : * copy of this software and associated documentation files (the "Software"),
6 : * to deal in the Software without restriction, including without limitation
7 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : * and/or sell copies of the Software, and to permit persons to whom the
9 : * Software is furnished to do so, subject to the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included in
12 : * all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 : * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 : * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 : * OTHER DEALINGS IN THE SOFTWARE.
21 : *
22 : * Authors: AMD
23 : *
24 : */
25 :
26 : #include "../dmub_srv.h"
27 : #include "dmub_reg.h"
28 : #include "dmub_dcn20.h"
29 : #include "dmub_dcn30.h"
30 :
31 : #include "sienna_cichlid_ip_offset.h"
32 : #include "dcn/dcn_3_0_0_offset.h"
33 : #include "dcn/dcn_3_0_0_sh_mask.h"
34 :
35 : #define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg
36 : #define CTX dmub
37 : #define REGS dmub->regs
38 :
39 : /* Registers. */
40 :
41 : const struct dmub_srv_common_regs dmub_srv_dcn30_regs = {
42 : #define DMUB_SR(reg) REG_OFFSET(reg),
43 : {
44 : DMUB_COMMON_REGS()
45 : DMCUB_INTERNAL_REGS()
46 : },
47 : #undef DMUB_SR
48 :
49 : #define DMUB_SF(reg, field) FD_MASK(reg, field),
50 : { DMUB_COMMON_FIELDS() },
51 : #undef DMUB_SF
52 :
53 : #define DMUB_SF(reg, field) FD_SHIFT(reg, field),
54 : { DMUB_COMMON_FIELDS() },
55 : #undef DMUB_SF
56 : };
57 :
58 : /* Shared functions. */
59 :
60 0 : static void dmub_dcn30_get_fb_base_offset(struct dmub_srv *dmub,
61 : uint64_t *fb_base,
62 : uint64_t *fb_offset)
63 : {
64 : uint32_t tmp;
65 :
66 0 : if (dmub->fb_base || dmub->fb_offset) {
67 0 : *fb_base = dmub->fb_base;
68 0 : *fb_offset = dmub->fb_offset;
69 0 : return;
70 : }
71 :
72 0 : REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp);
73 0 : *fb_base = (uint64_t)tmp << 24;
74 :
75 0 : REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp);
76 0 : *fb_offset = (uint64_t)tmp << 24;
77 : }
78 :
79 : static inline void dmub_dcn30_translate_addr(const union dmub_addr *addr_in,
80 : uint64_t fb_base,
81 : uint64_t fb_offset,
82 : union dmub_addr *addr_out)
83 : {
84 0 : addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
85 : }
86 :
87 0 : void dmub_dcn30_backdoor_load(struct dmub_srv *dmub,
88 : const struct dmub_window *cw0,
89 : const struct dmub_window *cw1)
90 : {
91 : union dmub_addr offset;
92 : uint64_t fb_base, fb_offset;
93 :
94 0 : dmub_dcn30_get_fb_base_offset(dmub, &fb_base, &fb_offset);
95 :
96 0 : REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
97 :
98 : /* MEM_CTNL read/write space doesn't exist. */
99 :
100 0 : dmub_dcn30_translate_addr(&cw0->offset, fb_base, fb_offset, &offset);
101 :
102 0 : REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
103 0 : REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
104 0 : REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
105 0 : REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
106 : DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
107 : DMCUB_REGION3_CW0_ENABLE, 1);
108 :
109 0 : dmub_dcn30_translate_addr(&cw1->offset, fb_base, fb_offset, &offset);
110 :
111 0 : REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
112 0 : REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
113 0 : REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
114 0 : REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
115 : DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
116 : DMCUB_REGION3_CW1_ENABLE, 1);
117 :
118 0 : REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
119 : 0x20);
120 0 : }
121 :
122 0 : void dmub_dcn30_setup_windows(struct dmub_srv *dmub,
123 : const struct dmub_window *cw2,
124 : const struct dmub_window *cw3,
125 : const struct dmub_window *cw4,
126 : const struct dmub_window *cw5,
127 : const struct dmub_window *cw6)
128 : {
129 : union dmub_addr offset;
130 :
131 : /* sienna_cichlid has hardwired virtual addressing for CW2-CW7 */
132 :
133 0 : offset = cw2->offset;
134 :
135 0 : if (cw2->region.base != cw2->region.top) {
136 0 : REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part);
137 0 : REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part);
138 0 : REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base);
139 0 : REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0,
140 : DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top,
141 : DMCUB_REGION3_CW2_ENABLE, 1);
142 : } else {
143 0 : REG_WRITE(DMCUB_REGION3_CW2_OFFSET, 0);
144 0 : REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, 0);
145 0 : REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, 0);
146 0 : REG_WRITE(DMCUB_REGION3_CW2_TOP_ADDRESS, 0);
147 : }
148 :
149 0 : offset = cw3->offset;
150 :
151 0 : REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part);
152 0 : REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part);
153 0 : REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base);
154 0 : REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0,
155 : DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top,
156 : DMCUB_REGION3_CW3_ENABLE, 1);
157 :
158 0 : offset = cw4->offset;
159 :
160 : /* New firmware can support CW4. */
161 0 : if (dmub_dcn20_use_cached_inbox(dmub)) {
162 0 : REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
163 0 : REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
164 0 : REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
165 0 : REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0,
166 : DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top,
167 : DMCUB_REGION3_CW4_ENABLE, 1);
168 : } else {
169 0 : REG_WRITE(DMCUB_REGION4_OFFSET, offset.u.low_part);
170 0 : REG_WRITE(DMCUB_REGION4_OFFSET_HIGH, offset.u.high_part);
171 0 : REG_SET_2(DMCUB_REGION4_TOP_ADDRESS, 0,
172 : DMCUB_REGION4_TOP_ADDRESS,
173 : cw4->region.top - cw4->region.base - 1,
174 : DMCUB_REGION4_ENABLE, 1);
175 : }
176 :
177 0 : offset = cw5->offset;
178 :
179 0 : REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part);
180 0 : REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part);
181 0 : REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base);
182 0 : REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0,
183 : DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
184 : DMCUB_REGION3_CW5_ENABLE, 1);
185 :
186 0 : REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
187 0 : REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
188 0 : REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
189 : DMCUB_REGION5_TOP_ADDRESS,
190 : cw5->region.top - cw5->region.base - 1,
191 : DMCUB_REGION5_ENABLE, 1);
192 :
193 0 : offset = cw6->offset;
194 :
195 0 : REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
196 0 : REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part);
197 0 : REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base);
198 0 : REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0,
199 : DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top,
200 : DMCUB_REGION3_CW6_ENABLE, 1);
201 0 : }
|