brintos

brintos / linux-shallow public Read only

0
0
Text · 8.8 KiB · 035ea21 Raw
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