Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2020 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
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 /* Registers. */
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 /* Shared functions. */
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     /* MEM_CTNL read/write space doesn't exist. */
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     /* sienna_cichlid  has hardwired virtual addressing for CW2-CW7 */
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     /* New firmware can support CW4. */
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 }