/* SPDX-License-Identifier: MIT * * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. */ #include void nvif_chan506f_gpfifo_kick(struct nvif_chan *chan) { wmb(); nvif_wr32(&chan->userd, 0x8c, chan->gpfifo.cur); } void nvif_chan506f_gpfifo_push(struct nvif_chan *chan, bool main, u64 addr, u32 size, bool no_prefetch) { u32 gpptr = chan->gpfifo.cur << 3; if (WARN_ON(!chan->gpfifo.free)) return; nvif_wr32(&chan->gpfifo, gpptr + 0, lower_32_bits(addr)); nvif_wr32(&chan->gpfifo, gpptr + 4, upper_32_bits(addr) | (main ? 0 : BIT(9)) | (size >> 2) << 10 | (no_prefetch ? BIT(31) : 0)); chan->gpfifo.cur = (chan->gpfifo.cur + 1) & chan->gpfifo.max; chan->gpfifo.free--; if (!chan->gpfifo.free) chan->push.end = chan->push.cur; } static u32 nvif_chan506f_gpfifo_read_get(struct nvif_chan *chan) { return nvif_rd32(&chan->userd, 0x88); } static u32 nvif_chan506f_read_get(struct nvif_chan *chan) { u32 tlgetlo = nvif_rd32(&chan->userd, 0x58); u32 tlgethi = nvif_rd32(&chan->userd, 0x5c); struct nvif_push *push = &chan->push; /* Update cached GET pointer if TOP_LEVEL_GET is valid. */ if (tlgethi & BIT(31)) { u64 tlget = ((u64)(tlgethi & 0xff) << 32) | tlgetlo; push->hw.get = (tlget - push->addr) >> 2; } return push->hw.get; } static const struct nvif_chan_func nvif_chan506f = { .push.read_get = nvif_chan506f_read_get, .gpfifo.read_get = nvif_chan506f_gpfifo_read_get, .gpfifo.push = nvif_chan506f_gpfifo_push, .gpfifo.kick = nvif_chan506f_gpfifo_kick, }; int nvif_chan506f_ctor(struct nvif_chan *chan, void *userd, void *gpfifo, u32 gpfifo_size, void *push, u64 push_addr, u32 push_size) { nvif_chan_gpfifo_ctor(&nvif_chan506f, userd, gpfifo, gpfifo_size, push, push_addr, push_size, chan); return 0; }