summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
blob: d8fd2cbd2872c20943051c691f0ce720f678e024 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#ifndef __NVKM_FALCON_H__
#define __NVKM_FALCON_H__
#include <core/firmware.h>
#include <engine/falcon.h>

enum nvkm_falcon_mem {
	IMEM,
	DMEM,
};

static inline const char *
nvkm_falcon_mem(enum nvkm_falcon_mem mem)
{
	switch (mem) {
	case IMEM: return "imem";
	case DMEM: return "dmem";
	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);
};

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 gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
int gm200_flcn_disable(struct nvkm_falcon *);
int gm200_flcn_enable(struct nvkm_falcon *);
extern const struct nvkm_falcon_func_pio gm200_flcn_imem_pio;
extern const struct nvkm_falcon_func_pio gm200_flcn_dmem_pio;

int gp102_flcn_reset_eng(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_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *);
void nvkm_falcon_v1_bind_context(struct nvkm_falcon *, struct nvkm_memory *);
int nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *, u32);
int nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *, u32);
void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *, u32 start_addr);
void nvkm_falcon_v1_start(struct nvkm_falcon *);

void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *);

#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 (*load)(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 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;

	u32 boot_addr;

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

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_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);

#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