1d1fb887aSBen Skeggs /* SPDX-License-Identifier: MIT 2d1fb887aSBen Skeggs * 3d1fb887aSBen Skeggs * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. 4d1fb887aSBen Skeggs */ 5d1fb887aSBen Skeggs #include <nvif/chan.h> 6d1fb887aSBen Skeggs 7*862450a8SBen Skeggs void 8d1fb887aSBen Skeggs nvif_chan506f_gpfifo_kick(struct nvif_chan *chan) 9d1fb887aSBen Skeggs { 10d1fb887aSBen Skeggs wmb(); 11d1fb887aSBen Skeggs nvif_wr32(&chan->userd, 0x8c, chan->gpfifo.cur); 12d1fb887aSBen Skeggs } 13d1fb887aSBen Skeggs 14d1fb887aSBen Skeggs void 15d1fb887aSBen Skeggs nvif_chan506f_gpfifo_push(struct nvif_chan *chan, bool main, u64 addr, u32 size, bool no_prefetch) 16d1fb887aSBen Skeggs { 17d1fb887aSBen Skeggs u32 gpptr = chan->gpfifo.cur << 3; 18d1fb887aSBen Skeggs 19d1fb887aSBen Skeggs if (WARN_ON(!chan->gpfifo.free)) 20d1fb887aSBen Skeggs return; 21d1fb887aSBen Skeggs 22d1fb887aSBen Skeggs nvif_wr32(&chan->gpfifo, gpptr + 0, lower_32_bits(addr)); 23d1fb887aSBen Skeggs nvif_wr32(&chan->gpfifo, gpptr + 4, upper_32_bits(addr) | 24d1fb887aSBen Skeggs (main ? 0 : BIT(9)) | 25d1fb887aSBen Skeggs (size >> 2) << 10 | 26d1fb887aSBen Skeggs (no_prefetch ? BIT(31) : 0)); 27d1fb887aSBen Skeggs 28d1fb887aSBen Skeggs chan->gpfifo.cur = (chan->gpfifo.cur + 1) & chan->gpfifo.max; 29d1fb887aSBen Skeggs chan->gpfifo.free--; 30d1fb887aSBen Skeggs if (!chan->gpfifo.free) 31d1fb887aSBen Skeggs chan->push.end = chan->push.cur; 32d1fb887aSBen Skeggs } 33d1fb887aSBen Skeggs 34*862450a8SBen Skeggs static u32 35d1fb887aSBen Skeggs nvif_chan506f_gpfifo_read_get(struct nvif_chan *chan) 36d1fb887aSBen Skeggs { 37d1fb887aSBen Skeggs return nvif_rd32(&chan->userd, 0x88); 38d1fb887aSBen Skeggs } 39d1fb887aSBen Skeggs 40*862450a8SBen Skeggs static u32 41d1fb887aSBen Skeggs nvif_chan506f_read_get(struct nvif_chan *chan) 42d1fb887aSBen Skeggs { 43d1fb887aSBen Skeggs u32 tlgetlo = nvif_rd32(&chan->userd, 0x58); 44d1fb887aSBen Skeggs u32 tlgethi = nvif_rd32(&chan->userd, 0x5c); 45d1fb887aSBen Skeggs struct nvif_push *push = &chan->push; 46d1fb887aSBen Skeggs 47d1fb887aSBen Skeggs /* Update cached GET pointer if TOP_LEVEL_GET is valid. */ 48d1fb887aSBen Skeggs if (tlgethi & BIT(31)) { 49d1fb887aSBen Skeggs u64 tlget = ((u64)(tlgethi & 0xff) << 32) | tlgetlo; 50d1fb887aSBen Skeggs 51d1fb887aSBen Skeggs push->hw.get = (tlget - push->addr) >> 2; 52d1fb887aSBen Skeggs } 53d1fb887aSBen Skeggs 54d1fb887aSBen Skeggs return push->hw.get; 55d1fb887aSBen Skeggs } 56d1fb887aSBen Skeggs 57d1fb887aSBen Skeggs static const struct nvif_chan_func 58d1fb887aSBen Skeggs nvif_chan506f = { 59d1fb887aSBen Skeggs .push.read_get = nvif_chan506f_read_get, 60d1fb887aSBen Skeggs .gpfifo.read_get = nvif_chan506f_gpfifo_read_get, 61d1fb887aSBen Skeggs .gpfifo.push = nvif_chan506f_gpfifo_push, 62d1fb887aSBen Skeggs .gpfifo.kick = nvif_chan506f_gpfifo_kick, 63d1fb887aSBen Skeggs }; 64d1fb887aSBen Skeggs 65d1fb887aSBen Skeggs int 66d1fb887aSBen Skeggs nvif_chan506f_ctor(struct nvif_chan *chan, void *userd, void *gpfifo, u32 gpfifo_size, 67d1fb887aSBen Skeggs void *push, u64 push_addr, u32 push_size) 68d1fb887aSBen Skeggs { 69d1fb887aSBen Skeggs nvif_chan_gpfifo_ctor(&nvif_chan506f, userd, gpfifo, gpfifo_size, 70d1fb887aSBen Skeggs push, push_addr, push_size, chan); 71d1fb887aSBen Skeggs return 0; 72d1fb887aSBen Skeggs } 73