1/* $NetBSD: nouveau_nvkm_engine_gr_g84.c,v 1.3 2021/12/18 23:45:36 riastradh Exp $ */ 2 3/* 4 * Copyright 2012 Red Hat Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: Ben Skeggs 25 */ 26#include <sys/cdefs.h> 27__KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_engine_gr_g84.c,v 1.3 2021/12/18 23:45:36 riastradh Exp $"); 28 29#include "nv50.h" 30 31#include <subdev/timer.h> 32 33#include <nvif/class.h> 34 35static const struct nvkm_bitfield nv50_gr_status[] = { 36 { 0x00000001, "BUSY" }, /* set when any bit is set */ 37 { 0x00000002, "DISPATCH" }, 38 { 0x00000004, "UNK2" }, 39 { 0x00000008, "UNK3" }, 40 { 0x00000010, "UNK4" }, 41 { 0x00000020, "UNK5" }, 42 { 0x00000040, "M2MF" }, 43 { 0x00000080, "UNK7" }, 44 { 0x00000100, "CTXPROG" }, 45 { 0x00000200, "VFETCH" }, 46 { 0x00000400, "CCACHE_PREGEOM" }, 47 { 0x00000800, "STRMOUT_VATTR_POSTGEOM" }, 48 { 0x00001000, "VCLIP" }, 49 { 0x00002000, "RATTR_APLANE" }, 50 { 0x00004000, "TRAST" }, 51 { 0x00008000, "CLIPID" }, 52 { 0x00010000, "ZCULL" }, 53 { 0x00020000, "ENG2D" }, 54 { 0x00040000, "RMASK" }, 55 { 0x00080000, "TPC_RAST" }, 56 { 0x00100000, "TPC_PROP" }, 57 { 0x00200000, "TPC_TEX" }, 58 { 0x00400000, "TPC_GEOM" }, 59 { 0x00800000, "TPC_MP" }, 60 { 0x01000000, "ROP" }, 61 {} 62}; 63 64static const struct nvkm_bitfield 65nv50_gr_vstatus_0[] = { 66 { 0x01, "VFETCH" }, 67 { 0x02, "CCACHE" }, 68 { 0x04, "PREGEOM" }, 69 { 0x08, "POSTGEOM" }, 70 { 0x10, "VATTR" }, 71 { 0x20, "STRMOUT" }, 72 { 0x40, "VCLIP" }, 73 {} 74}; 75 76static const struct nvkm_bitfield 77nv50_gr_vstatus_1[] = { 78 { 0x01, "TPC_RAST" }, 79 { 0x02, "TPC_PROP" }, 80 { 0x04, "TPC_TEX" }, 81 { 0x08, "TPC_GEOM" }, 82 { 0x10, "TPC_MP" }, 83 {} 84}; 85 86static const struct nvkm_bitfield 87nv50_gr_vstatus_2[] = { 88 { 0x01, "RATTR" }, 89 { 0x02, "APLANE" }, 90 { 0x04, "TRAST" }, 91 { 0x08, "CLIPID" }, 92 { 0x10, "ZCULL" }, 93 { 0x20, "ENG2D" }, 94 { 0x40, "RMASK" }, 95 { 0x80, "ROP" }, 96 {} 97}; 98 99static void 100nvkm_gr_vstatus_print(struct nv50_gr *gr, int r, 101 const struct nvkm_bitfield *units, u32 status) 102{ 103 struct nvkm_subdev *subdev = &gr->base.engine.subdev; 104 u32 stat = status; 105 u8 mask = 0x00; 106 char msg[64]; 107 int i; 108 109 for (i = 0; units[i].name && status; i++) { 110 if ((status & 7) == 1) 111 mask |= (1 << i); 112 status >>= 3; 113 } 114 115 nvkm_snprintbf(msg, sizeof(msg), units, mask); 116 nvkm_error(subdev, "PGRAPH_VSTATUS%d: %08x [%s]\n", r, stat, msg); 117} 118 119int 120g84_gr_tlb_flush(struct nvkm_gr *base) 121{ 122 struct nv50_gr *gr = nv50_gr(base); 123 struct nvkm_subdev *subdev = &gr->base.engine.subdev; 124 struct nvkm_device *device = subdev->device; 125 struct nvkm_timer *tmr = device->timer; 126 bool idle, timeout = false; 127 unsigned long flags; 128 char status[128]; 129 u64 start; 130 u32 tmp; 131 132 spin_lock_irqsave(&gr->lock, flags); 133 nvkm_mask(device, 0x400500, 0x00000001, 0x00000000); 134 135 start = nvkm_timer_read(tmr); 136 do { 137 idle = true; 138 139 for (tmp = nvkm_rd32(device, 0x400380); tmp && idle; tmp >>= 3) { 140 if ((tmp & 7) == 1) 141 idle = false; 142 } 143 144 for (tmp = nvkm_rd32(device, 0x400384); tmp && idle; tmp >>= 3) { 145 if ((tmp & 7) == 1) 146 idle = false; 147 } 148 149 for (tmp = nvkm_rd32(device, 0x400388); tmp && idle; tmp >>= 3) { 150 if ((tmp & 7) == 1) 151 idle = false; 152 } 153 } while (!idle && 154 !(timeout = nvkm_timer_read(tmr) - start > 2000000000)); 155 156 if (timeout) { 157 nvkm_error(subdev, "PGRAPH TLB flush idle timeout fail\n"); 158 159 tmp = nvkm_rd32(device, 0x400700); 160 nvkm_snprintbf(status, sizeof(status), nv50_gr_status, tmp); 161 nvkm_error(subdev, "PGRAPH_STATUS %08x [%s]\n", tmp, status); 162 163 nvkm_gr_vstatus_print(gr, 0, nv50_gr_vstatus_0, 164 nvkm_rd32(device, 0x400380)); 165 nvkm_gr_vstatus_print(gr, 1, nv50_gr_vstatus_1, 166 nvkm_rd32(device, 0x400384)); 167 nvkm_gr_vstatus_print(gr, 2, nv50_gr_vstatus_2, 168 nvkm_rd32(device, 0x400388)); 169 } 170 171 172 nvkm_wr32(device, 0x100c80, 0x00000001); 173 nvkm_msec(device, 2000, 174 if (!(nvkm_rd32(device, 0x100c80) & 0x00000001)) 175 break; 176 ); 177 nvkm_mask(device, 0x400500, 0x00000001, 0x00000001); 178 spin_unlock_irqrestore(&gr->lock, flags); 179 return timeout ? -EBUSY : 0; 180} 181 182static const struct nvkm_gr_func 183g84_gr = { 184 .init = nv50_gr_init, 185 .intr = nv50_gr_intr, 186 .chan_new = nv50_gr_chan_new, 187 .tlb_flush = g84_gr_tlb_flush, 188 .units = nv50_gr_units, 189 .sclass = { 190 { -1, -1, NV_NULL_CLASS, &nv50_gr_object }, 191 { -1, -1, NV50_TWOD, &nv50_gr_object }, 192 { -1, -1, NV50_MEMORY_TO_MEMORY_FORMAT, &nv50_gr_object }, 193 { -1, -1, NV50_COMPUTE, &nv50_gr_object }, 194 { -1, -1, G82_TESLA, &nv50_gr_object }, 195 {} 196 } 197}; 198 199int 200g84_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) 201{ 202 return nv50_gr_new_(&g84_gr, device, index, pgr); 203} 204