347 lines · c
1/*2 * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20 * DEALINGS IN THE SOFTWARE.21 */22#include "gf100.h"23#include "ctxgf100.h"24 25#include <core/firmware.h>26#include <subdev/timer.h>27 28#include <nvif/class.h>29 30struct gk20a_fw_av31{32 u32 addr;33 u32 data;34};35 36int37gk20a_gr_av_to_init_(struct nvkm_blob *blob, u8 count, u32 pitch, struct gf100_gr_pack **ppack)38{39 struct gf100_gr_init *init;40 struct gf100_gr_pack *pack;41 int nent;42 int i;43 44 nent = (blob->size / sizeof(struct gk20a_fw_av));45 pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1)));46 if (!pack)47 return -ENOMEM;48 49 init = (void *)(pack + 2);50 pack[0].init = init;51 52 for (i = 0; i < nent; i++) {53 struct gf100_gr_init *ent = &init[i];54 struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob->data)[i];55 56 ent->addr = av->addr;57 ent->data = av->data;58 ent->count = ((ent->addr & 0xffff) != 0xe100) ? count : 1;59 ent->pitch = pitch;60 }61 62 *ppack = pack;63 return 0;64}65 66int67gk20a_gr_av_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)68{69 return gk20a_gr_av_to_init_(blob, 1, 1, ppack);70}71 72struct gk20a_fw_aiv73{74 u32 addr;75 u32 index;76 u32 data;77};78 79int80gk20a_gr_aiv_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)81{82 struct gf100_gr_init *init;83 struct gf100_gr_pack *pack;84 int nent;85 int i;86 87 nent = (blob->size / sizeof(struct gk20a_fw_aiv));88 pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1)));89 if (!pack)90 return -ENOMEM;91 92 init = (void *)(pack + 2);93 pack[0].init = init;94 95 for (i = 0; i < nent; i++) {96 struct gf100_gr_init *ent = &init[i];97 struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)blob->data)[i];98 99 ent->addr = av->addr;100 ent->data = av->data;101 ent->count = 1;102 ent->pitch = 1;103 }104 105 *ppack = pack;106 return 0;107}108 109int110gk20a_gr_av_to_method(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)111{112 struct gf100_gr_init *init;113 struct gf100_gr_pack *pack;114 /* We don't suppose we will initialize more than 16 classes here... */115 static const unsigned int max_classes = 16;116 u32 classidx = 0, prevclass = 0;117 int nent;118 int i;119 120 nent = (blob->size / sizeof(struct gk20a_fw_av));121 pack = vzalloc((sizeof(*pack) * (max_classes + 1)) +122 (sizeof(*init) * (nent + max_classes + 1)));123 if (!pack)124 return -ENOMEM;125 126 init = (void *)(pack + max_classes + 1);127 128 for (i = 0; i < nent; i++, init++) {129 struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob->data)[i];130 u32 class = av->addr & 0xffff;131 u32 addr = (av->addr & 0xffff0000) >> 14;132 133 if (prevclass != class) {134 if (prevclass) /* Add terminator to the method list. */135 init++;136 pack[classidx].init = init;137 pack[classidx].type = class;138 prevclass = class;139 if (++classidx >= max_classes) {140 vfree(pack);141 return -ENOSPC;142 }143 }144 145 init->addr = addr;146 init->data = av->data;147 init->count = 1;148 init->pitch = 1;149 }150 151 *ppack = pack;152 return 0;153}154 155static int156gk20a_gr_wait_mem_scrubbing(struct gf100_gr *gr)157{158 struct nvkm_subdev *subdev = &gr->base.engine.subdev;159 struct nvkm_device *device = subdev->device;160 161 if (nvkm_msec(device, 2000,162 if (!(nvkm_rd32(device, 0x40910c) & 0x00000006))163 break;164 ) < 0) {165 nvkm_error(subdev, "FECS mem scrubbing timeout\n");166 return -ETIMEDOUT;167 }168 169 if (nvkm_msec(device, 2000,170 if (!(nvkm_rd32(device, 0x41a10c) & 0x00000006))171 break;172 ) < 0) {173 nvkm_error(subdev, "GPCCS mem scrubbing timeout\n");174 return -ETIMEDOUT;175 }176 177 return 0;178}179 180static void181gk20a_gr_set_hww_esr_report_mask(struct gf100_gr *gr)182{183 struct nvkm_device *device = gr->base.engine.subdev.device;184 nvkm_wr32(device, 0x419e44, 0x1ffffe);185 nvkm_wr32(device, 0x419e4c, 0x7f);186}187 188int189gk20a_gr_init(struct gf100_gr *gr)190{191 struct nvkm_device *device = gr->base.engine.subdev.device;192 int ret;193 194 /* Clear SCC RAM */195 nvkm_wr32(device, 0x40802c, 0x1);196 197 gf100_gr_mmio(gr, gr->sw_nonctx);198 199 ret = gk20a_gr_wait_mem_scrubbing(gr);200 if (ret)201 return ret;202 203 ret = gf100_gr_wait_idle(gr);204 if (ret)205 return ret;206 207 /* MMU debug buffer */208 if (gr->func->init_gpc_mmu)209 gr->func->init_gpc_mmu(gr);210 211 /* Set the PE as stream master */212 nvkm_mask(device, 0x503018, 0x1, 0x1);213 214 /* Zcull init */215 gr->func->init_zcull(gr);216 217 gr->func->init_rop_active_fbps(gr);218 219 /* Enable FIFO access */220 nvkm_wr32(device, 0x400500, 0x00010001);221 222 /* Enable interrupts */223 nvkm_wr32(device, 0x400100, 0xffffffff);224 nvkm_wr32(device, 0x40013c, 0xffffffff);225 226 /* Enable FECS error interrupts */227 nvkm_wr32(device, 0x409c24, 0x000f0000);228 229 /* Enable hardware warning exceptions */230 nvkm_wr32(device, 0x404000, 0xc0000000);231 nvkm_wr32(device, 0x404600, 0xc0000000);232 233 if (gr->func->set_hww_esr_report_mask)234 gr->func->set_hww_esr_report_mask(gr);235 236 /* Enable TPC exceptions per GPC */237 nvkm_wr32(device, 0x419d0c, 0x2);238 nvkm_wr32(device, 0x41ac94, (((1 << gr->tpc_total) - 1) & 0xff) << 16);239 240 /* Reset and enable all exceptions */241 nvkm_wr32(device, 0x400108, 0xffffffff);242 nvkm_wr32(device, 0x400138, 0xffffffff);243 nvkm_wr32(device, 0x400118, 0xffffffff);244 nvkm_wr32(device, 0x400130, 0xffffffff);245 nvkm_wr32(device, 0x40011c, 0xffffffff);246 nvkm_wr32(device, 0x400134, 0xffffffff);247 248 gf100_gr_zbc_init(gr);249 250 return gf100_gr_init_ctxctl(gr);251}252 253static const struct gf100_gr_func254gk20a_gr = {255 .oneinit_tiles = gf100_gr_oneinit_tiles,256 .oneinit_sm_id = gf100_gr_oneinit_sm_id,257 .init = gk20a_gr_init,258 .init_zcull = gf117_gr_init_zcull,259 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps,260 .trap_mp = gf100_gr_trap_mp,261 .set_hww_esr_report_mask = gk20a_gr_set_hww_esr_report_mask,262 .fecs.reset = gf100_gr_fecs_reset,263 .rops = gf100_gr_rops,264 .ppc_nr = 1,265 .grctx = &gk20a_grctx,266 .zbc = &gf100_gr_zbc,267 .sclass = {268 { -1, -1, FERMI_TWOD_A },269 { -1, -1, KEPLER_INLINE_TO_MEMORY_A },270 { -1, -1, KEPLER_C, &gf100_fermi },271 { -1, -1, KEPLER_COMPUTE_A },272 {}273 }274};275 276int277gk20a_gr_load_net(struct gf100_gr *gr, const char *path, const char *name, int ver,278 int (*load)(struct nvkm_blob *, struct gf100_gr_pack **),279 struct gf100_gr_pack **ppack)280{281 struct nvkm_blob blob;282 int ret;283 284 ret = nvkm_firmware_load_blob(&gr->base.engine.subdev, path, name, ver, &blob);285 if (ret)286 return ret;287 288 ret = load(&blob, ppack);289 nvkm_blob_dtor(&blob);290 return 0;291}292 293int294gk20a_gr_load_sw(struct gf100_gr *gr, const char *path, int ver)295{296 if (gk20a_gr_load_net(gr, path, "sw_nonctx", ver, gk20a_gr_av_to_init, &gr->sw_nonctx) ||297 gk20a_gr_load_net(gr, path, "sw_ctx", ver, gk20a_gr_aiv_to_init, &gr->sw_ctx) ||298 gk20a_gr_load_net(gr, path, "sw_bundle_init", ver, gk20a_gr_av_to_init, &gr->bundle) ||299 gk20a_gr_load_net(gr, path, "sw_method_init", ver, gk20a_gr_av_to_method, &gr->method))300 return -ENOENT;301 302 return 0;303}304 305#if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) || IS_ENABLED(CONFIG_ARCH_TEGRA_132_SOC)306MODULE_FIRMWARE("nvidia/gk20a/fecs_data.bin");307MODULE_FIRMWARE("nvidia/gk20a/fecs_inst.bin");308MODULE_FIRMWARE("nvidia/gk20a/gpccs_data.bin");309MODULE_FIRMWARE("nvidia/gk20a/gpccs_inst.bin");310MODULE_FIRMWARE("nvidia/gk20a/sw_bundle_init.bin");311MODULE_FIRMWARE("nvidia/gk20a/sw_ctx.bin");312MODULE_FIRMWARE("nvidia/gk20a/sw_method_init.bin");313MODULE_FIRMWARE("nvidia/gk20a/sw_nonctx.bin");314#endif315 316static int317gk20a_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif)318{319 struct nvkm_subdev *subdev = &gr->base.engine.subdev;320 321 if (nvkm_firmware_load_blob(subdev, "", "fecs_inst", ver,322 &gr->fecs.inst) ||323 nvkm_firmware_load_blob(subdev, "", "fecs_data", ver,324 &gr->fecs.data) ||325 nvkm_firmware_load_blob(subdev, "", "gpccs_inst", ver,326 &gr->gpccs.inst) ||327 nvkm_firmware_load_blob(subdev, "", "gpccs_data", ver,328 &gr->gpccs.data))329 return -ENOENT;330 331 gr->firmware = true;332 333 return gk20a_gr_load_sw(gr, "", ver);334}335 336static const struct gf100_gr_fwif337gk20a_gr_fwif[] = {338 { 0, gk20a_gr_load, &gk20a_gr },339 {}340};341 342int343gk20a_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)344{345 return gf100_gr_new_(gk20a_gr_fwif, device, type, inst, pgr);346}347