summaryrefslogtreecommitdiff
path: root/include/dm/acpi.h
blob: 3adfe21767899018adb6f77c0ed9f2c83eb98a37 (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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Core ACPI (Advanced Configuration and Power Interface) support
 *
 * Copyright 2019 Google LLC
 * Written by Simon Glass <sjg@chromium.org>
 */

#ifndef __DM_ACPI_H__
#define __DM_ACPI_H__

/* Allow operations to be optional for ACPI */
#if CONFIG_IS_ENABLED(ACPIGEN)
#define ACPI_OPS_PTR(_ptr)	.acpi_ops	= _ptr,
#else
#define ACPI_OPS_PTR(_ptr)
#endif

/* Length of an ACPI name string, excluding null terminator */
#define ACPI_NAME_LEN	4

/* Length of an ACPI name string including nul terminator */
#define ACPI_NAME_MAX	(ACPI_NAME_LEN + 1)

/* Number of nested objects supported */
#define ACPIGEN_LENSTACK_SIZE 10

#if !defined(__ACPI__)

#include <linker_lists.h>

struct nhlt;
struct udevice;

/** enum acpi_dump_option - selects what ACPI information to dump */
enum acpi_dump_option {
	ACPI_DUMP_LIST,		/* Just the list of items */
	ACPI_DUMP_CONTENTS,	/* Include the binary contents also */
};

/**
 * struct acpi_ctx - Context used for writing ACPI tables
 *
 * This contains a few useful pieces of information used when writing
 *
 * @base: Base address of ACPI tables
 * @current: Current address for writing
 * @tab_start: Address of start of the table being written. This is set up
 * before the writer or driver method is called. It must not be changed by the
 * method
 * @rsdp: Pointer to the Root System Description Pointer, typically used when
 *	adding a new table. The RSDP holds pointers to the RSDT and XSDT.
 * @rsdt: Pointer to the Root System Description Table
 * @xsdt: Pointer to the Extended System Description Table
 * @facs: Pointer to the Firmware ACPI Control Structure
 * @dsdt: Pointer to the Differentiated System Description Table
 * @nhlt: Intel Non-High-Definition-Audio Link Table (NHLT) pointer, used to
 *	build up information that audio codecs need to provide in the NHLT ACPI
 *	table
 * @len_stack: Stack of 'length' words to fix up later
 * @ltop: Points to current top of stack (0 = empty)
 */
struct acpi_ctx {
	void *base;
	void *current;
	void *tab_start;
	struct acpi_rsdp *rsdp;
	struct acpi_rsdt *rsdt;
	struct acpi_xsdt *xsdt;
	struct acpi_facs *facs;
	struct acpi_table_header *dsdt;
	struct nhlt *nhlt;
	char *len_stack[ACPIGEN_LENSTACK_SIZE];
	int ltop;
};

/**
 * enum acpi_writer_flags_t - flags to use for the ACPI writers
 *
 * ACPIWF_ALIGN64 - align to 64 bytes after writing this one (default is 16)
 */
enum acpi_writer_flags_t {
	ACPIWF_ALIGN64	= 1 << 0,
};

struct acpi_writer;

/**
 * acpi_writer_func() - Function that can write an ACPI table
 *
 * @ctx: ACPI context to use for writing
 * @entry: Linker-list entry for this writer
 * @return 0 if OK, -ve on error
 */
typedef int (*acpi_writer_func)(struct acpi_ctx *ctx,
				const struct acpi_writer *entry);

/**
 * struct acpi_writer - an ACPI table that can be written
 *
 * @name: Name of the writer
 * @table: Table name that is generated (e.g. "DSDT")
 * @h_write: Writer function
 */
struct acpi_writer {
	const char *name;
	const char *table;
	acpi_writer_func h_write;
	int flags;
};

/* Declare a new ACPI-table writer */
#define ACPI_WRITER(_name, _table, _write, _flags)					\
	ll_entry_declare(struct acpi_writer, _name, acpi_writer) = {	\
		.name = #_name,						\
		.table = _table,					\
		.h_write = _write,					\
		.flags = _flags,					\
	}

/* Get a pointer to a given ACPI-table writer */
#define ACPI_WRITER_GET(_name)						\
	ll_entry_get(struct acpi_writer, _name, acpi_writer)

/**
 * struct acpi_ops - ACPI operations supported by driver model
 */
struct acpi_ops {
	/**
	 * get_name() - Obtain the ACPI name of a device
	 *
	 * @dev: Device to check
	 * @out_name: Place to put the name, must hold at least ACPI_NAME_MAX
	 *	bytes
	 * @return 0 if OK, -ENOENT if no name is available, other -ve value on
	 *	other error
	 */
	int (*get_name)(const struct udevice *dev, char *out_name);

	/**
	 * write_tables() - Write out any tables required by this device
	 *
	 * @dev: Device to write
	 * @ctx: ACPI context to use
	 * @return 0 if OK, -ve on error
	 */
	int (*write_tables)(const struct udevice *dev, struct acpi_ctx *ctx);

	/**
	 * fill_ssdt() - Generate SSDT code for a device
	 *
	 * This is called to create the SSDT code. The method should write out
	 * whatever ACPI code is needed by this device. It will end up in the
	 * SSDT table.
	 *
	 * Note that this is called 'fill' because the entire contents of the
	 * SSDT is build by calling this method on all devices.
	 *
	 * @dev: Device to write
	 * @ctx: ACPI context to use
	 * @return 0 if OK, -ve on error
	 */
	int (*fill_ssdt)(const struct udevice *dev, struct acpi_ctx *ctx);

	/**
	 * inject_dsdt() - Generate DSDT code for a device
	 *
	 * This is called to create the DSDT code. The method should write out
	 * whatever ACPI code is needed by this device. It will end up in the
	 * DSDT table.
	 *
	 * Note that this is called 'inject' because the output of calling this
	 * method on all devices is injected into the DSDT, the bulk of which
	 * is written in .asl files for the board.
	 *
	 * @dev: Device to write
	 * @ctx: ACPI context to use
	 * @return 0 if OK, -ve on error
	 */
	int (*inject_dsdt)(const struct udevice *dev, struct acpi_ctx *ctx);

	/**
	 * setup_nhlt() - Set up audio information for this device
	 *
	 * The method can add information to ctx->nhlt if it likes
	 *
	 * @return 0 if OK, -ENODATA if nothing to add, -ve on error
	 */
	int (*setup_nhlt)(const struct udevice *dev, struct acpi_ctx *ctx);
};

#define device_get_acpi_ops(dev)	((dev)->driver->acpi_ops)

/**
 * acpi_get_name() - Obtain the ACPI name of a device
 *
 * @dev: Device to check
 * @out_name: Place to put the name, must hold at least ACPI_NAME_MAX
 *	bytes
 * Return: 0 if OK, -ENOENT if no name is available, other -ve value on
 *	other error
 */
int acpi_get_name(const struct udevice *dev, char *out_name);

/**
 * acpi_copy_name() - Copy an ACPI name to an output buffer
 *
 * This convenience function can be used to return a literal string as a name
 * in functions that implement the get_name() method.
 *
 * For example:
 *
 *	static int mydev_get_name(const struct udevice *dev, char *out_name)
 *	{
 *		return acpi_copy_name(out_name, "WIBB");
 *	}
 *
 * @out_name: Place to put the name
 * @name: Name to copy
 * Return: 0 (always)
 */
int acpi_copy_name(char *out_name, const char *name);

/**
 * acpi_write_dev_tables() - Write ACPI tables required by devices
 *
 * This scans through all devices and tells them to write any tables they want
 * to write.
 *
 * Return: 0 if OK, -ve if any device returned an error
 */
int acpi_write_dev_tables(struct acpi_ctx *ctx);

/**
 * acpi_fill_ssdt() - Generate ACPI tables for SSDT
 *
 * This is called to create the SSDT code for all devices.
 *
 * @ctx: ACPI context to use
 * Return: 0 if OK, -ve on error
 */
int acpi_fill_ssdt(struct acpi_ctx *ctx);

/**
 * acpi_inject_dsdt() - Generate ACPI tables for DSDT
 *
 * This is called to create the DSDT code for all devices.
 *
 * @ctx: ACPI context to use
 * Return: 0 if OK, -ve on error
 */
int acpi_inject_dsdt(struct acpi_ctx *ctx);

/**
 * acpi_setup_nhlt() - Set up audio information
 *
 * This is called to set up the nhlt information for all devices.
 *
 * @ctx: ACPI context to use
 * @nhlt: Pointer to nhlt information to add to
 * Return: 0 if OK, -ve on error
 */
int acpi_setup_nhlt(struct acpi_ctx *ctx, struct nhlt *nhlt);

/**
 * acpi_add_other_item() - Add a new table to the list of ACPI tables
 *
 * This adds an entry of type ACPIT_TYPE_OTHER
 *
 * @ctx: ACPI context
 * @writer: Writer entry that generated the data
 * @type: Table type it refers to
 * @start: The start of the data (the end is obtained from ctx->current)
 * @return 0 if OK, -ENOSPC if too many items, -ENOMEM if out of memory
 */
int acpi_add_other_item(struct acpi_ctx *ctx, const struct acpi_writer *writer,
			void *start);

/**
 * acpi_dump_items() - Dump out the collected ACPI items
 *
 * This lists the ACPI DSDT and SSDT items generated by the various U-Boot
 * drivers.
 *
 * @option: Sets what should be dumpyed
 */
void acpi_dump_items(enum acpi_dump_option option);

/**
 * acpi_get_path() - Get the full ACPI path for a device
 *
 * This checks for any override in the device tree and calls acpi_device_path()
 * if not
 *
 * @dev: Device to check
 * @out_path: Buffer to place the path in (should be ACPI_PATH_MAX long)
 * @maxlen: Size of buffer (typically ACPI_PATH_MAX)
 * Return: 0 if OK, -ve on error
 */
int acpi_get_path(const struct udevice *dev, char *out_path, int maxlen);

/**
 * acpi_reset_items() - Reset the list of ACPI items to empty
 *
 * This list keeps track of DSDT and SSDT items that are generated
 * programmatically. The 'acpi items' command shows the list. Use this function
 * to empty the list, before writing new items.
 */
void acpi_reset_items(void);

/**
 * acpi_write_one() - Call a single ACPI writer entry
 *
 * This handles aligning the context afterwards, if the entry flags indicate
 * that.
 *
 * @ctx: ACPI context to use
 * @entry: Entry to call
 * @return 0 if OK, -ENOENT if this writer produced an empty entry, other -ve
 * value on error
 */
int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry);

/**
 * acpi_setup_ctx() - Set up a new ACPI context
 *
 * This zeros the context and sets up the base and current pointers, ensuring
 * that they are aligned. Then it writes the acpi_start and acpi_ctx values in
 * global_data
 *
 * @ctx: ACPI context to set up
 * @start: Start address for ACPI table
 */
void acpi_setup_ctx(struct acpi_ctx *ctx, ulong start);

/**
 * acpi_write_one() - Call a single ACPI writer entry
 *
 * This handles aligning the context afterwards, if the entry flags indicate
 * that.
 *
 * @ctx: ACPI context to use
 * @entry: Entry to call
 * @return 0 if OK, -ENOENT if this writer produced an empty entry, other -ve
 * value on error
 */
int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry);

#endif /* __ACPI__ */

#endif