aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/remoteproc.h
blob: 2dc9ec1f0a9e5e49f01ae31573598dabcac1b8a2 (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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
 * Remote Processor Framework
 *
 * Copyright(c) 2011 Texas Instruments. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 * * Neither the name Texas Instruments nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef REMOTEPROC_H
#define REMOTEPROC_H

#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/notifier.h>

/**
 * The following enums and structures define the binary format of the images
 * we load and run the remote processors with.
 *
 * The binary format is as follows:
 *
 * struct {
 *     char magic[4] = { 'R', 'P', 'R', 'C' };
 *     u32 version;
 *     u32 header_len;
 *     char header[...] = { header_len bytes of unformatted, textual header };
 *     struct section {
 *         u32 type;
 *         u64 da;
 *         u32 len;
 *         u8 content[...] = { len bytes of binary data };
 *     } [ no limit on number of sections ];
 * } __packed;
 */
struct fw_header {
	char magic[4];
	u32 version;
	u32 header_len;
	char header[0];
} __packed;

struct fw_section {
	u32 type;
	u64 da;
	u32 len;
	char content[0];
} __packed;

enum fw_section_type {
	FW_RESOURCE	= 0,
	FW_TEXT		= 1,
	FW_DATA		= 2,
};

struct fw_resource {
	u32 type;
	u64 da;
	u32 len;
	u32 reserved;
	u8 name[48];
} __packed;

enum fw_resource_type {
	RSC_MEMORY	= 0,
	RSC_DEVICE	= 1,
	RSC_IRQ		= 2,
	RSC_SERVICE	= 3,
	RSC_TRACE	= 4,
	RSC_BOOTADDR	= 5,
	RSC_END		= 6,
};

/**
 * struct rproc_mem_entry - descriptor of a remote memory region
 *
 * @da:		virtual address as seen by the device (aka device address)
 * @pa:		physical address
 * @size:	size of this memory region
 */
struct rproc_mem_entry {
	u64 da;
	phys_addr_t pa;
	u32 size;
};

struct rproc;

struct rproc_ops {
	int (*start)(struct rproc *rproc, u64 bootaddr);
	int (*stop)(struct rproc *rproc);
	int (*suspend)(struct rproc *rproc, bool force);
	int (*resume)(struct rproc *rproc);
	int (*iommu_init)(struct rproc *, int (*)(struct rproc *, u64, u32));
	int (*iommu_exit)(struct rproc *);
};

/*
 * enum rproc_state - remote processor states
 *
 * @RPROC_OFFLINE: needs firmware load and init to exit this state.
 *
 * @RPROC_SUSPENDED: needs to be woken up to receive a message.
 *
 * @RPROC_RUNNING: up and running.
 *
 * @RPROC_LOADING: asynchronous firmware loading has started
 *
 * @RPROC_CRASHED: needs to be logged, connections torn down, resources
 * released, and returned to OFFLINE.
 */
enum rproc_state {
	RPROC_OFFLINE,
	RPROC_SUSPENDED,
	RPROC_RUNNING,
	RPROC_LOADING,
	RPROC_CRASHED,
};

/*
 * enum rproc_event - remote processor events
 *
 * @RPROC_ERROR: Fatal error has happened on the remote processor.
 *
 * @RPROC_PRE_SUSPEND: users can register for that event in order to cancel
 *		       autosuspend, they just need to return an error in the
 *		       callback function.
 *
 * @RPROC_POS_SUSPEND: users can register for that event in order to release
 *		       resources not needed when the remote processor is
 *		       sleeping or if they need to save some context.
 *
 * @RPROC_RESUME: users should use this event to revert what was done in the
 *		  POS_SUSPEND event.
 */
enum rproc_event {
	RPROC_ERROR,
	RPROC_PRE_SUSPEND,
	RPROC_POS_SUSPEND,
	RPROC_RESUME,
};

#define RPROC_MAX_NAME	100

/*
 * struct rproc - a physical remote processor device
 *
 * @next: next rproc entry in the list
 * @name: human readable name of the rproc, cannot exceed RPROC_MAN_NAME bytes
 * @memory_maps: table of da-to-pa memory maps (relevant if device is behind
 *               an iommu)
 * @firmware: name of firmware file to be loaded
 * @owner: reference to the platform-specific rproc module
 * @priv: private data which belongs to the platform-specific rproc module
 * @ops: platform-specific start/stop rproc handlers
 * @dev: reference to the platform-specific rproc dev
 * @count: usage refcount
 * @state: rproc_state enum value representing the state of the device
 * @lock: lock which protects concurrent manipulations of the rproc
 * @dbg_dir: debugfs directory of this rproc device
 * @trace_buf0: main trace buffer of the remote processor
 * @trace_buf1: second, optional, trace buffer of the remote processor
 * @trace_len0: length of main trace buffer of the remote processor
 * @trace_len1: length of the second (and optional) trace buffer
 * @firmware_loading_complete: flags e/o asynchronous firmware loading
 * @mmufault_work: work in charge of notifing mmufault
 * @nb_error: notify block for fatal errors
 */
struct rproc {
	struct list_head next;
	const char *name;
	const struct rproc_mem_entry *memory_maps;
	const char *firmware;
	struct module *owner;
	void *priv;
	const struct rproc_ops *ops;
	struct device *dev;
	int count;
	int state;
	struct mutex lock;
	struct dentry *dbg_dir;
	char *trace_buf0, *trace_buf1;
	int trace_len0, trace_len1;
	struct completion firmware_loading_complete;
	struct work_struct mmufault_work;
	struct blocking_notifier_head nb_error;
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
	unsigned sus_timeout;
	bool force_suspend;
	bool need_resume;
	struct blocking_notifier_head nb_presus;
	struct blocking_notifier_head nb_possus;
	struct blocking_notifier_head nb_resume;
	struct mutex pm_lock;
#endif
};

struct rproc *rproc_get(const char *);
void rproc_put(struct rproc *);
int rproc_event_register(struct rproc *, struct notifier_block *, int);
int rproc_event_unregister(struct rproc *, struct notifier_block *, int);
int rproc_register(struct device *, const char *, const struct rproc_ops *,
		const char *, const struct rproc_mem_entry *, struct module *,
		unsigned int timeout);
int rproc_unregister(const char *);
void rproc_last_busy(struct rproc *);
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
extern const struct dev_pm_ops rproc_gen_pm_ops;
#define GENERIC_RPROC_PM_OPS	(&rproc_gen_pm_ops)
#else
#define GENERIC_RPROC_PM_OPS	NULL
#endif

#endif /* REMOTEPROC_H */