root/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
#ifndef __NVKM_FALCON_H__
#define __NVKM_FALCON_H__
#include <core/firmware.h>
#include <engine/falcon.h>

enum nvkm_falcon_mem {
        IMEM,
        DMEM,
        EMEM,
};

static inline const char *
nvkm_falcon_mem(enum nvkm_falcon_mem mem)
{
        switch (mem) {
        case IMEM: return "imem";
        case DMEM: return "dmem";
        case EMEM: return "emem";
        default:
                WARN_ON(1);
                return "?mem";
        }
}

struct nvkm_falcon_func_pio {
        int min;
        int max;
        void (*wr_init)(struct nvkm_falcon *, u8 port, bool sec, u32 mem_base);
        void (*wr)(struct nvkm_falcon *, u8 port, const u8 *img, int len, u16 tag);
        void (*rd_init)(struct nvkm_falcon *, u8 port, u32 mem_base);
        void (*rd)(struct nvkm_falcon *, u8 port, const u8 *img, int len);
};

struct nvkm_falcon_func_dma {
        int (*init)(struct nvkm_falcon *, u64 dma_addr, int xfer_len,
                    enum nvkm_falcon_mem, bool sec, u32 *cmd);
        void (*xfer)(struct nvkm_falcon *, u32 mem_base, u32 dma_base, u32 cmd);
        bool (*done)(struct nvkm_falcon *);
};

int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner,
                     const char *name, u32 addr, struct nvkm_falcon *);
void nvkm_falcon_dtor(struct nvkm_falcon *);
int nvkm_falcon_reset(struct nvkm_falcon *);
int nvkm_falcon_pio_wr(struct nvkm_falcon *, const u8 *img, u32 img_base, u8 port,
                       enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec);
int nvkm_falcon_pio_rd(struct nvkm_falcon *, u8 port, enum nvkm_falcon_mem type, u32 mem_base,
                       const u8 *img, u32 img_base, int len);
int nvkm_falcon_dma_wr(struct nvkm_falcon *, const u8 *img, u64 dma_addr, u32 dma_base,
                       enum nvkm_falcon_mem mem_type, u32 mem_base, int len, bool sec);
bool nvkm_falcon_riscv_active(struct nvkm_falcon *);
void nvkm_falcon_intr_retrigger(struct nvkm_falcon *);

int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
int gm200_flcn_disable(struct nvkm_falcon *);
int gm200_flcn_enable(struct nvkm_falcon *);
void gm200_flcn_bind_inst(struct nvkm_falcon *, int, u64);
int gm200_flcn_bind_stat(struct nvkm_falcon *, bool);
extern const struct nvkm_falcon_func_pio gm200_flcn_imem_pio;
extern const struct nvkm_falcon_func_pio gm200_flcn_dmem_pio;
void gm200_flcn_tracepc(struct nvkm_falcon *);

int gp102_flcn_reset_eng(struct nvkm_falcon *);
extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio;

bool tu102_flcn_riscv_active(struct nvkm_falcon *);

void ga100_flcn_intr_retrigger(struct nvkm_falcon *);

int ga102_flcn_select(struct nvkm_falcon *);
int ga102_flcn_reset_prep(struct nvkm_falcon *);
int ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
extern const struct nvkm_falcon_func_dma ga102_flcn_dma;
bool ga102_flcn_riscv_active(struct nvkm_falcon *);

void nvkm_falcon_v1_load_imem(struct nvkm_falcon *,
                              void *, u32, u32, u16, u8, bool);
void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8);
void nvkm_falcon_v1_start(struct nvkm_falcon *);

#define FLCN_PRINTK(f,l,p,fmt,a...) ({                                                          \
        if ((f)->owner->name != (f)->name)                                                      \
                nvkm_printk___((f)->owner, (f)->user, NV_DBG_##l, p, "%s:"fmt, (f)->name, ##a); \
        else                                                                                    \
                nvkm_printk___((f)->owner, (f)->user, NV_DBG_##l, p, fmt, ##a);                 \
})
#define FLCN_DBG(f,fmt,a...) FLCN_PRINTK((f), DEBUG, info, " "fmt"\n", ##a)
#define FLCN_ERR(f,fmt,a...) FLCN_PRINTK((f), ERROR, err, " "fmt"\n", ##a)
#define FLCN_ERRON(f,c,fmt,a...) \
        ({ bool _cond = (c); _cond ? FLCN_ERR(f, fmt, ##a) : FLCN_DBG(f, fmt, ##a); _cond; })


struct nvkm_falcon_fw {
        const struct nvkm_falcon_fw_func {
                int (*signature)(struct nvkm_falcon_fw *, u32 *sig_base_src);
                int (*reset)(struct nvkm_falcon_fw *);
                int (*setup)(struct nvkm_falcon_fw *);
                int (*load)(struct nvkm_falcon_fw *);
                int (*load_bld)(struct nvkm_falcon_fw *);
                int (*boot)(struct nvkm_falcon_fw *,
                            u32 *mbox0, u32 *mbox1, u32 mbox0_ok, u32 irqsclr);
        } *func;
        struct nvkm_firmware fw;

        u32 sig_base_prd;
        u32 sig_base_dbg;
        u32 sig_base_img;
        u32 sig_size;
        int sig_nr;
        u8 *sigs;
        u32 fuse_ver;
        u32 engine_id;
        u32 ucode_id;

        u32 nmem_base_img;
        u32 nmem_base;
        u32 nmem_size;

        u32 imem_base_img;
        u32 imem_base;
        u32 imem_size;

        u32 dmem_base_img;
        u32 dmem_base;
        u32 dmem_size;
        u32 dmem_sign;

        u8 *boot;
        u32 boot_size;
        u32 boot_addr;

        struct nvkm_falcon *falcon;
        struct nvkm_memory *inst;
        struct nvkm_vmm *vmm;
        struct nvkm_vma *vma;
};

int nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *, const char *name, struct nvkm_device *,
                        bool bl, const void *src, u32 len, struct nvkm_falcon *,
                        struct nvkm_falcon_fw *);
int nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *, const char *name,
                           struct nvkm_subdev *, const char *bl, const char *img, int ver,
                           struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw);
int nvkm_falcon_fw_ctor_hs_v2(const struct nvkm_falcon_fw_func *, const char *name,
                              struct nvkm_subdev *, const char *img, int ver, struct nvkm_falcon *,
                              struct nvkm_falcon_fw *);
int nvkm_falcon_fw_sign(struct nvkm_falcon_fw *, u32 sig_base_img, u32 sig_size, const u8 *sigs,
                        int sig_nr_prd, u32 sig_base_prd, int sig_nr_dbg, u32 sig_base_dbg);
int nvkm_falcon_fw_patch(struct nvkm_falcon_fw *);
void nvkm_falcon_fw_dtor(struct nvkm_falcon_fw *);
int nvkm_falcon_fw_oneinit(struct nvkm_falcon_fw *, struct nvkm_falcon *, struct nvkm_vmm *,
                           struct nvkm_memory *inst);
int nvkm_falcon_fw_boot(struct nvkm_falcon_fw *, struct nvkm_subdev *user,
                        bool release, u32 *pmbox0, u32 *pmbox1, u32 mbox0_ok, u32 irqsclr);

extern const struct nvkm_falcon_fw_func gm200_flcn_fw;
int gm200_flcn_fw_signature(struct nvkm_falcon_fw *, u32 *);
int gm200_flcn_fw_reset(struct nvkm_falcon_fw *);
int gm200_flcn_fw_load(struct nvkm_falcon_fw *);
int gm200_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32);

int ga100_flcn_fw_signature(struct nvkm_falcon_fw *, u32 *);

extern const struct nvkm_falcon_fw_func ga102_flcn_fw;
int ga102_flcn_fw_load(struct nvkm_falcon_fw *);
int ga102_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32);

#define FLCNFW_PRINTK(f,l,p,fmt,a...) FLCN_PRINTK((f)->falcon, l, p, "%s: "fmt, (f)->fw.name, ##a)
#define FLCNFW_DBG(f,fmt,a...) FLCNFW_PRINTK((f), DEBUG, info, fmt"\n", ##a)
#define FLCNFW_ERR(f,fmt,a...) FLCNFW_PRINTK((f), ERROR, err, fmt"\n", ##a)

/**
 * struct nvfw_falcon_msg - header for all messages
 *
 * @unit_id:    id of firmware process that sent the message
 * @size:       total size of message
 * @ctrl_flags: control flags
 * @seq_id:     used to match a message from its corresponding command
 */
struct nvfw_falcon_msg {
        u8 unit_id;
        u8 size;
        u8 ctrl_flags;
        u8 seq_id;
};

#define nvfw_falcon_cmd nvfw_falcon_msg
#define NV_FALCON_CMD_UNIT_ID_REWIND                                       0x00

struct nvkm_falcon_qmgr;
int nvkm_falcon_qmgr_new(struct nvkm_falcon *, struct nvkm_falcon_qmgr **);
void nvkm_falcon_qmgr_del(struct nvkm_falcon_qmgr **);

typedef int
(*nvkm_falcon_qmgr_callback)(void *priv, struct nvfw_falcon_msg *);

struct nvkm_falcon_cmdq;
int nvkm_falcon_cmdq_new(struct nvkm_falcon_qmgr *, const char *name,
                         struct nvkm_falcon_cmdq **);
void nvkm_falcon_cmdq_del(struct nvkm_falcon_cmdq **);
void nvkm_falcon_cmdq_init(struct nvkm_falcon_cmdq *,
                           u32 index, u32 offset, u32 size);
void nvkm_falcon_cmdq_fini(struct nvkm_falcon_cmdq *);
int nvkm_falcon_cmdq_send(struct nvkm_falcon_cmdq *, struct nvfw_falcon_cmd *,
                          nvkm_falcon_qmgr_callback, void *priv,
                          unsigned long timeout_jiffies);

struct nvkm_falcon_msgq;
int nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *, const char *name,
                         struct nvkm_falcon_msgq **);
void nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **);
void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *,
                           u32 index, u32 offset, u32 size);
bool nvkm_falcon_msgq_empty(struct nvkm_falcon_msgq *);
int nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *, void *, u32 size);
void nvkm_falcon_msgq_recv(struct nvkm_falcon_msgq *);
#endif