summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h')
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h438
1 files changed, 438 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
index 72619d7df..6f5d376d8 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
@@ -3,14 +3,452 @@
#define nvkm_gsp(p) container_of((p), struct nvkm_gsp, subdev)
#include <core/subdev.h>
#include <core/falcon.h>
+#include <core/firmware.h>
+
+#define GSP_PAGE_SHIFT 12
+#define GSP_PAGE_SIZE BIT(GSP_PAGE_SHIFT)
+
+struct nvkm_gsp_mem {
+ size_t size;
+ void *data;
+ dma_addr_t addr;
+};
+
+struct nvkm_gsp_radix3 {
+ struct nvkm_gsp_mem mem[3];
+};
+
+int nvkm_gsp_sg(struct nvkm_device *, u64 size, struct sg_table *);
+void nvkm_gsp_sg_free(struct nvkm_device *, struct sg_table *);
+
+typedef int (*nvkm_gsp_msg_ntfy_func)(void *priv, u32 fn, void *repv, u32 repc);
+
+struct nvkm_gsp_event;
+typedef void (*nvkm_gsp_event_func)(struct nvkm_gsp_event *, void *repv, u32 repc);
struct nvkm_gsp {
const struct nvkm_gsp_func *func;
struct nvkm_subdev subdev;
struct nvkm_falcon falcon;
+
+ struct {
+ struct {
+ const struct firmware *load;
+ const struct firmware *unload;
+ } booter;
+ const struct firmware *bl;
+ const struct firmware *rm;
+ } fws;
+
+ struct nvkm_firmware fw;
+ struct nvkm_gsp_mem sig;
+ struct nvkm_gsp_radix3 radix3;
+
+ struct {
+ struct {
+ struct {
+ u64 addr;
+ u64 size;
+ } vga_workspace;
+ u64 addr;
+ u64 size;
+ } bios;
+ struct {
+ struct {
+ u64 addr;
+ u64 size;
+ } frts, boot, elf, heap;
+ u64 addr;
+ u64 size;
+ } wpr2;
+ struct {
+ u64 addr;
+ u64 size;
+ } heap;
+ u64 addr;
+ u64 size;
+
+ struct {
+ u64 addr;
+ u64 size;
+ } region[16];
+ int region_nr;
+ u32 rsvd_size;
+ } fb;
+
+ struct {
+ struct nvkm_falcon_fw load;
+ struct nvkm_falcon_fw unload;
+ } booter;
+
+ struct {
+ struct nvkm_gsp_mem fw;
+ u32 code_offset;
+ u32 data_offset;
+ u32 manifest_offset;
+ u32 app_version;
+ } boot;
+
+ struct nvkm_gsp_mem libos;
+ struct nvkm_gsp_mem loginit;
+ struct nvkm_gsp_mem logintr;
+ struct nvkm_gsp_mem logrm;
+ struct nvkm_gsp_mem rmargs;
+
+ struct nvkm_gsp_mem wpr_meta;
+
+ struct {
+ struct sg_table sgt;
+ struct nvkm_gsp_radix3 radix3;
+ struct nvkm_gsp_mem meta;
+ } sr;
+
+ struct {
+ struct nvkm_gsp_mem mem;
+
+ struct {
+ int nr;
+ u32 size;
+ u64 *ptr;
+ } ptes;
+
+ struct {
+ u32 size;
+ void *ptr;
+ } cmdq, msgq;
+ } shm;
+
+ struct nvkm_gsp_cmdq {
+ struct mutex mutex;
+ u32 cnt;
+ u32 seq;
+ u32 *wptr;
+ u32 *rptr;
+ } cmdq;
+
+ struct nvkm_gsp_msgq {
+ struct mutex mutex;
+ u32 cnt;
+ u32 *wptr;
+ u32 *rptr;
+ struct nvkm_gsp_msgq_ntfy {
+ u32 fn;
+ nvkm_gsp_msg_ntfy_func func;
+ void *priv;
+ } ntfy[16];
+ int ntfy_nr;
+ struct work_struct work;
+ } msgq;
+
+ bool running;
+
+ /* Internal GSP-RM control handles. */
+ struct {
+ struct nvkm_gsp_client {
+ struct nvkm_gsp_object {
+ struct nvkm_gsp_client *client;
+ struct nvkm_gsp_object *parent;
+ u32 handle;
+ } object;
+
+ struct nvkm_gsp *gsp;
+
+ struct list_head events;
+ } client;
+
+ struct nvkm_gsp_device {
+ struct nvkm_gsp_object object;
+ struct nvkm_gsp_object subdevice;
+ } device;
+ } internal;
+
+ struct {
+ enum nvkm_subdev_type type;
+ int inst;
+ u32 stall;
+ u32 nonstall;
+ } intr[32];
+ int intr_nr;
+
+ struct {
+ u64 rm_bar1_pdb;
+ u64 rm_bar2_pdb;
+ } bar;
+
+ struct {
+ u8 gpcs;
+ u8 tpcs;
+ } gr;
+
+ const struct nvkm_gsp_rm {
+ void *(*rpc_get)(struct nvkm_gsp *, u32 fn, u32 argc);
+ void *(*rpc_push)(struct nvkm_gsp *, void *argv, bool wait, u32 repc);
+ void (*rpc_done)(struct nvkm_gsp *gsp, void *repv);
+
+ void *(*rm_ctrl_get)(struct nvkm_gsp_object *, u32 cmd, u32 argc);
+ int (*rm_ctrl_push)(struct nvkm_gsp_object *, void **argv, u32 repc);
+ void (*rm_ctrl_done)(struct nvkm_gsp_object *, void *repv);
+
+ void *(*rm_alloc_get)(struct nvkm_gsp_object *, u32 oclass, u32 argc);
+ void *(*rm_alloc_push)(struct nvkm_gsp_object *, void *argv, u32 repc);
+ void (*rm_alloc_done)(struct nvkm_gsp_object *, void *repv);
+
+ int (*rm_free)(struct nvkm_gsp_object *);
+
+ int (*client_ctor)(struct nvkm_gsp *, struct nvkm_gsp_client *);
+ void (*client_dtor)(struct nvkm_gsp_client *);
+
+ int (*device_ctor)(struct nvkm_gsp_client *, struct nvkm_gsp_device *);
+ void (*device_dtor)(struct nvkm_gsp_device *);
+
+ int (*event_ctor)(struct nvkm_gsp_device *, u32 handle, u32 id,
+ nvkm_gsp_event_func, struct nvkm_gsp_event *);
+ void (*event_dtor)(struct nvkm_gsp_event *);
+ } *rm;
+
+ struct {
+ struct mutex mutex;;
+ struct idr idr;
+ } client_id;
+};
+
+static inline bool
+nvkm_gsp_rm(struct nvkm_gsp *gsp)
+{
+ return gsp && (gsp->fws.rm || gsp->fw.img);
+}
+
+static inline void *
+nvkm_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 argc)
+{
+ return gsp->rm->rpc_get(gsp, fn, argc);
+}
+
+static inline void *
+nvkm_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, u32 repc)
+{
+ return gsp->rm->rpc_push(gsp, argv, wait, repc);
+}
+
+static inline void *
+nvkm_gsp_rpc_rd(struct nvkm_gsp *gsp, u32 fn, u32 argc)
+{
+ void *argv = nvkm_gsp_rpc_get(gsp, fn, argc);
+
+ if (IS_ERR_OR_NULL(argv))
+ return argv;
+
+ return nvkm_gsp_rpc_push(gsp, argv, true, argc);
+}
+
+static inline int
+nvkm_gsp_rpc_wr(struct nvkm_gsp *gsp, void *argv, bool wait)
+{
+ void *repv = nvkm_gsp_rpc_push(gsp, argv, wait, 0);
+
+ if (IS_ERR(repv))
+ return PTR_ERR(repv);
+
+ return 0;
+}
+
+static inline void
+nvkm_gsp_rpc_done(struct nvkm_gsp *gsp, void *repv)
+{
+ gsp->rm->rpc_done(gsp, repv);
+}
+
+static inline void *
+nvkm_gsp_rm_ctrl_get(struct nvkm_gsp_object *object, u32 cmd, u32 argc)
+{
+ return object->client->gsp->rm->rm_ctrl_get(object, cmd, argc);
+}
+
+static inline int
+nvkm_gsp_rm_ctrl_push(struct nvkm_gsp_object *object, void *argv, u32 repc)
+{
+ return object->client->gsp->rm->rm_ctrl_push(object, argv, repc);
+}
+
+static inline void *
+nvkm_gsp_rm_ctrl_rd(struct nvkm_gsp_object *object, u32 cmd, u32 repc)
+{
+ void *argv = nvkm_gsp_rm_ctrl_get(object, cmd, repc);
+ int ret;
+
+ if (IS_ERR(argv))
+ return argv;
+
+ ret = nvkm_gsp_rm_ctrl_push(object, &argv, repc);
+ if (ret)
+ return ERR_PTR(ret);
+ return argv;
+}
+
+static inline int
+nvkm_gsp_rm_ctrl_wr(struct nvkm_gsp_object *object, void *argv)
+{
+ int ret = nvkm_gsp_rm_ctrl_push(object, &argv, 0);
+
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static inline void
+nvkm_gsp_rm_ctrl_done(struct nvkm_gsp_object *object, void *repv)
+{
+ object->client->gsp->rm->rm_ctrl_done(object, repv);
+}
+
+static inline void *
+nvkm_gsp_rm_alloc_get(struct nvkm_gsp_object *parent, u32 handle, u32 oclass, u32 argc,
+ struct nvkm_gsp_object *object)
+{
+ struct nvkm_gsp_client *client = parent->client;
+ struct nvkm_gsp *gsp = client->gsp;
+ void *argv;
+
+ object->client = parent->client;
+ object->parent = parent;
+ object->handle = handle;
+
+ argv = gsp->rm->rm_alloc_get(object, oclass, argc);
+ if (IS_ERR_OR_NULL(argv)) {
+ object->client = NULL;
+ return argv;
+ }
+
+ return argv;
+}
+
+static inline void *
+nvkm_gsp_rm_alloc_push(struct nvkm_gsp_object *object, void *argv, u32 repc)
+{
+ void *repv = object->client->gsp->rm->rm_alloc_push(object, argv, repc);
+
+ if (IS_ERR(repv))
+ object->client = NULL;
+
+ return repv;
+}
+
+static inline int
+nvkm_gsp_rm_alloc_wr(struct nvkm_gsp_object *object, void *argv)
+{
+ void *repv = nvkm_gsp_rm_alloc_push(object, argv, 0);
+
+ if (IS_ERR(repv))
+ return PTR_ERR(repv);
+
+ return 0;
+}
+
+static inline void
+nvkm_gsp_rm_alloc_done(struct nvkm_gsp_object *object, void *repv)
+{
+ object->client->gsp->rm->rm_alloc_done(object, repv);
+}
+
+static inline int
+nvkm_gsp_rm_alloc(struct nvkm_gsp_object *parent, u32 handle, u32 oclass, u32 argc,
+ struct nvkm_gsp_object *object)
+{
+ void *argv = nvkm_gsp_rm_alloc_get(parent, handle, oclass, argc, object);
+
+ if (IS_ERR_OR_NULL(argv))
+ return argv ? PTR_ERR(argv) : -EIO;
+
+ return nvkm_gsp_rm_alloc_wr(object, argv);
+}
+
+static inline int
+nvkm_gsp_rm_free(struct nvkm_gsp_object *object)
+{
+ if (object->client)
+ return object->client->gsp->rm->rm_free(object);
+
+ return 0;
+}
+
+static inline int
+nvkm_gsp_client_ctor(struct nvkm_gsp *gsp, struct nvkm_gsp_client *client)
+{
+ if (WARN_ON(!gsp->rm))
+ return -ENOSYS;
+
+ return gsp->rm->client_ctor(gsp, client);
+}
+
+static inline void
+nvkm_gsp_client_dtor(struct nvkm_gsp_client *client)
+{
+ if (client->gsp)
+ client->gsp->rm->client_dtor(client);
+}
+
+static inline int
+nvkm_gsp_device_ctor(struct nvkm_gsp_client *client, struct nvkm_gsp_device *device)
+{
+ return client->gsp->rm->device_ctor(client, device);
+}
+
+static inline void
+nvkm_gsp_device_dtor(struct nvkm_gsp_device *device)
+{
+ if (device->object.client)
+ device->object.client->gsp->rm->device_dtor(device);
+}
+
+static inline int
+nvkm_gsp_client_device_ctor(struct nvkm_gsp *gsp,
+ struct nvkm_gsp_client *client, struct nvkm_gsp_device *device)
+{
+ int ret = nvkm_gsp_client_ctor(gsp, client);
+
+ if (ret == 0) {
+ ret = nvkm_gsp_device_ctor(client, device);
+ if (ret)
+ nvkm_gsp_client_dtor(client);
+ }
+
+ return ret;
+}
+
+struct nvkm_gsp_event {
+ struct nvkm_gsp_device *device;
+ u32 id;
+ nvkm_gsp_event_func func;
+
+ struct nvkm_gsp_object object;
+
+ struct list_head head;
};
+static inline int
+nvkm_gsp_device_event_ctor(struct nvkm_gsp_device *device, u32 handle, u32 id,
+ nvkm_gsp_event_func func, struct nvkm_gsp_event *event)
+{
+ return device->object.client->gsp->rm->event_ctor(device, handle, id, func, event);
+}
+
+static inline void
+nvkm_gsp_event_dtor(struct nvkm_gsp_event *event)
+{
+ struct nvkm_gsp_device *device = event->device;
+
+ if (device)
+ device->object.client->gsp->rm->event_dtor(event);
+}
+
+int nvkm_gsp_intr_stall(struct nvkm_gsp *, enum nvkm_subdev_type, int);
+int nvkm_gsp_intr_nonstall(struct nvkm_gsp *, enum nvkm_subdev_type, int);
+
int gv100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
+int tu102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
+int tu116_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
+int ga100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
int ga102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
+int ad102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
#endif