summaryrefslogtreecommitdiff
path: root/include/fdt_decode.h
blob: 45072df9bc7ed769828af9a2b876955317819dbd (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
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
/*
 * Copyright (c) 2011 The Chromium OS Authors.
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */


/*
 * This file contains convenience functions for decoding useful and
 * enlightening information from FDTs. It is intended to be used by device
 * drivers and board-specific code within U-Boot. It aims to reduce the
 * amount of FDT munging required within U-Boot itself, so that driver code
 * changes to support FDT are minimized.
 */

#include <ns16550.h>
#include <asm/arch/clock.h>

/* A typedef for a physical address. We should move it to a generic place */
#ifdef CONFIG_PHYS_64BIT
typedef u64 addr_t;
#define ADDR_T_NONE (-1ULL)
#define addr_to_cpu(reg) be64_to_cpu(reg)
#else
typedef u32 addr_t;
#define ADDR_T_NONE (-1U)
#define addr_to_cpu(reg) be32_to_cpu(reg)
#endif

/**
 * Compat types that we know about and for which we might have drivers.
 * Each is named COMPAT_<dir>_<filename> where <dir> is the directory
 * within drivers.
 */
enum fdt_compat_id {
	COMPAT_UNKNOWN,
	COMPAT_NVIDIA_SPI_UART_SWITCH,	/* SPI / UART switch */
	COMPAT_SERIAL_NS16550,		/* NS16550 UART */
	COMPAT_NVIDIA_TEGRA250_USB,	/* Tegra 250 USB port */
	COMPAT_NVIDIA_TEGRA250_SDMMC,	/* Tegra 250 SDMMC port */
	COMPAT_NVIDIA_TEGRA250_KBC,	/* Tegra 250 Keyboard */
	COMPAT_NVIDIA_TEGRA250_I2C,	/* Tegra 250 i2c */

	COMPAT_COUNT,
};

/* Information obtained about a UART from the FDT */
struct fdt_uart {
	addr_t reg;	/* address of registers in physical memory */
	int id;		/* id or port number (numbered from 0, default -1) */
	int reg_shift;	/* each register is (1 << reg_shift) apart */
	int baudrate;	/* baud rate, will be gd->baudrate if not defined */
	int clock_freq;	/* clock frequency, -1 if not provided */
	int multiplier;	/* divisor multiplier, default 16 */
	int divisor;	/* baud rate divisor, default calculated */
	int enabled;	/* 1 to enable, 0 to disable */
	int interrupt;	/* interrupt line */
	int silent;	/* 1 for silent UART (supresses output by default) */
	enum fdt_compat_id compat; /* our selected driver */
};

/* Information about the spi/uart switch */
struct fdt_spi_uart {
	int gpio;			/* GPIO to control switch */
	NS16550_t regs;			/* Address of UART affected */
	u32 port;			/* Port number of UART affected */
};

enum {
	FDT_GPIO_NONE = 255,	/* an invalid GPIO used to end our list */
	FDT_GPIO_MAX  = 224,	/* maximum value GPIO number on Tegra2 */

	FDT_GPIO_OUTPUT	= 1 << 0,	/* set as output (else input) */
	FDT_GPIO_HIGH	= 1 << 1,	/* set output as high (else low) */
};

/* This is the state of a GPIO pin. For now it only handles output pins */
struct fdt_gpio_state {
	u8 gpio;		/* GPIO number, or FDT_GPIO_NONE if none */
	u8 flags;		/* FDT_GPIO_... flags */
};

/* This tells us whether a fdt_gpio_state record is valid or not */
#define fdt_gpio_isvalid(gpio) ((gpio)->gpio != FDT_GPIO_NONE)

#define FDT_LCD_GPIOS	5

enum {
	FDT_LCD_TIMING_REF_TO_SYNC,
	FDT_LCD_TIMING_SYNC_WIDTH,
	FDT_LCD_TIMING_BACK_PORCH,
	FDT_LCD_TIMING_FRONT_PORCH,

	FDT_LCD_TIMING_COUNT,
};

enum lcd_cache_t {
	FDT_LCD_CACHE_OFF		= 0,
	FDT_LCD_CACHE_WRITE_THROUGH	= 1 << 0,
	FDT_LCD_CACHE_WRITE_BACK	= 1 << 1,
	FDT_LCD_CACHE_FLUSH		= 1 << 2,
	FDT_LCD_CACHE_WRITE_BACK_FLUSH	= FDT_LCD_CACHE_WRITE_BACK |
						FDT_LCD_CACHE_FLUSH,
};

/* Information about the LCD */
struct fdt_lcd {
	addr_t reg;		/* address of registers in physical memory */
	int width;		/* width in pixels */
	int height;		/* height in pixels */
	int bpp;		/* number of bits per pixel */

	/*
	 * log2 of number of bpp, in general, unless it bpp is 24 in which
	 * case this field holds 24 also! This is a U-Boot thing.
	 */
	int log2_bpp;
	struct fdt_gpio_state gpios[FDT_LCD_GPIOS]; /* state of output GPIOS */
	struct pwfm_ctlr *pwfm;	/* PWM to use for backlight */
	struct disp_ctlr *disp;	/* Display controller to use */
	addr_t frame_buffer;	/* Address of frame buffer */
	unsigned pixel_clock;	/* Pixel clock in Hz */
	int horiz_timing[FDT_LCD_TIMING_COUNT];	/* Horizontal timing */
	int vert_timing[FDT_LCD_TIMING_COUNT];	/* Vertical timing */
	enum lcd_cache_t cache_type;
};

/* Parameters we need for USB */
enum {
	PARAM_DIVN,			/* PLL FEEDBACK DIVIDer */
	PARAM_DIVM,			/* PLL INPUT DIVIDER */
	PARAM_DIVP,			/* POST DIVIDER (2^N) */
	PARAM_CPCON,			/* BASE PLLC CHARGE Pump setup ctrl */
	PARAM_LFCON,			/* BASE PLLC LOOP FILter setup ctrl */
	PARAM_ENABLE_DELAY_COUNT,	/* PLL-U Enable Delay Count */
	PARAM_STABLE_COUNT,		/* PLL-U STABLE count */
	PARAM_ACTIVE_DELAY_COUNT,	/* PLL-U Active delay count */
	PARAM_XTAL_FREQ_COUNT,		/* PLL-U XTAL frequency count */
	PARAM_DEBOUNCE_A_TIME,		/* 10MS DELAY for BIAS_DEBOUNCE_A */
	PARAM_BIAS_TIME,		/* 20US DELAY AFter bias cell op */

	PARAM_COUNT
};

/* Information about USB */
struct fdt_usb {
	struct usb_ctlr *reg;	/* address of registers in physical memory */
	int params[PARAM_COUNT]; /* timing parameters */
	int host_mode;		/* 1 if port has host mode, else 0 */
	int utmi;		/* 1 if port has external tranceiver, else 0 */
	int enabled;		/* 1 to enable, 0 to disable */
	enum periph_id periph_id;/* peripheral id */
};

/* Information about an SDMMC port */
struct fdt_sdmmc {
	struct tegra2_mmc *reg;	/* address of registers in physical memory */
	int width;		/* port width in bits (normally 4) */
	int removable;		/* 1 for removable device, 0 for fixed */
	int enabled;		/* 1 to enable, 0 to disable */
	struct fdt_gpio_state cd_gpio;		/* card detect GPIO */
	struct fdt_gpio_state wp_gpio;		/* write protect GPIO */
	struct fdt_gpio_state power_gpio;	/* power GPIO */
	enum periph_id periph_id; 		/* peripheral id */
};

enum {
	FDT_KBC_KEY_COUNT	= 128,	/* number of keys in each map */
};

/* Information about keycode mappings */
struct fdt_kbc {
	u8 plain_keycode[FDT_KBC_KEY_COUNT];
	u8 shift_keycode[FDT_KBC_KEY_COUNT];
	u8 fn_keycode[FDT_KBC_KEY_COUNT];
	u8 ctrl_keycode[FDT_KBC_KEY_COUNT];
};

/* Information about i2c controller */
struct fdt_i2c {
	struct i2c_ctlr *reg;
	int pinmux;
	u32 speed;
	enum periph_id periph_id;
};

/**
 * Return information from the FDT about the console UART. This looks for
 * an alias node called 'console' which must point to a UART. It then reads
 * out the following attributes:
 *
 *	reg
 *	port
 *	clock-frequency
 *	reg-shift (default 2)
 *	baudrate (default 115200)
 *	multiplier (default 16)
 *	divisor (calculated by default)
 *	enabled (default 1)
 *	interrupts (returns first in interrupt list, -1 if none)
 *	silent (default 0)
 *	cache-type (default FDT_LCD_CACHE_WRITE_BACK_FLUSH)
 *
 * The divisor calculation is performed by calling
 * fdt_decode_uart_calc_divisor() automatically once the information is
 * available. Therefore callers should be able to simply use the ->divisor
 * field as their baud rate divisor.
 *
 * @param blob	FDT blob to use
 * @param uart	struct to use to return information
 * @param default_baudrate  Baud rate to use if none defined in FDT
 * @return 0 on success, -ve on error, in which case uart is unchanged
 */
int fdt_decode_uart_console(const void *blob, struct fdt_uart *uart,
		int default_baudrate);

/**
 * Calculate the divisor to use for the uart. This is done based on the
 * formula (uart clock / (baudrate * multiplier). The divisor is updated
 * in the uart structure ready for use.
 *
 * @param uart	uart structure to examine and update
 */
void fdt_decode_uart_calc_divisor(struct fdt_uart *uart);

/**
 * Find the compat id for a node. This looks at the 'compat' property of
 * the node and looks up the corresponding ftp_compat_id. This is used for
 * determining which driver will implement the decide described by the node.
 */
enum fdt_compat_id fdt_decode_lookup(const void *blob, int node);

/**
 * Find the next node which is compatible with the given id. Pass in a node
 * of 0 the first time.
 *
 * @param blob		FDT blob to use
 * @param node		Node offset to start search after
 * @param id		Compatible ID to look for
 * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more
 */
int fdt_decode_next_compatible(const void *blob, int node,
		enum fdt_compat_id id);

/**
 * Find the next numbered alias for a peripheral. This is used to enumerate
 * all the peripherals of a certain type.
 *
 * Do the first call with *upto = 0. Assuming /aliases/<name>0 exists then
 * this function will return a pointer to the node the alias points to, and
 * then update *upto to 1. Next time you call this function, the next node
 * will be returned.
 *
 * All nodes returned will match the compatible ID, as it is assumed that
 * all peripherals use the same driver.
 *
 * @param blob		FDT blob to use
 * @param name		Root name of alias to search for
 * @param id		Compatible ID to look for
 * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more
 */
int fdt_decode_next_alias(const void *blob, const char *name,
		enum fdt_compat_id id, int *upto);

/**
 * Returns information from the FDT about the SPI / UART switch on tegra
 * platforms.
 *
 * @param blob		FDT blob to use
 * @param config	structure to use to return information
 * @returns 0 on success, -ve on error, in which case config is unchanged
 */
int fdt_decode_get_spi_switch(const void *blob, struct fdt_spi_uart *config);

/**
 * Set up a GPIO pin according to the provided gpio. This sets it to either
 * input or output. If an output, then the defined value is assigned.
 *
 * @param gpio		GPIO to set up
 */
void fdt_setup_gpio(struct fdt_gpio_state *gpio);

/**
 * Set up GPIO pins according to the list provided.
 *
 * @param gpio_list	List of GPIOs to set up
 */
void fdt_setup_gpios(struct fdt_gpio_state *gpio_list);

/**
 * Converts an FDT GPIO record into a number and returns it.
 *
 * @param gpio		GPIO to check
 * @return gpio number, or -1 if none or not valid
 */
int fdt_get_gpio_num(struct fdt_gpio_state *gpio);

/**
 * Returns information from the FDT about the LCD display. This function reads
 * out the following attributes:
 *
 *	reg		physical address of display peripheral
 *	width		width in pixels
 *	height		height in pixels
 *	bits_per_pixel	put in bpp
 *	log2_bpp	log2 of bpp (so bpp = 2 ^ log2_bpp)
 *	pwfm		PWFM to use
 *	display		Display to use (SOC peripheral)
 *	frame-buffer	Frame buffer address (can be omitted since U-Boot will
 *			normally set this)
 *	pixel_clock	Pixel clock in Hz
 *	horiz_timing	ref_to_sync, sync_width. back_porch, front_porch
 *	vert_timing	ref_to_sync, sync_width. back_porch, front_porch
 *	gpios		list of GPIOs to make as outputs, along with 0/1 value
 *
 * @param blob		FDT blob to use
 * @param config	structure to use to return information
 * @returns 0 on success, -ve on error, in which case config may or may not be
 *			unchanged. If the node is present but expected data is
 *			missing then this will generally return
 *			-FDT_ERR_MISSING.
 */
int fdt_decode_lcd(const void *blob, struct fdt_lcd *config);

/**
 * Returns information from the FDT about the USB port. This function reads
 * out the following attributes:
 *
 *	reg
 *	params
 *	host-mode
 *	utmi
 *	periph-id
 *	enabled
 *
 * The params are read out according to the supplied clock frequency. This is
 * done by looking for a compatible 'nvidia,tegra250-usbparams' node with
 * osc-frequency set to the given value.
 *
 * @param blob		FDT blob to use
 * @param node		Node to read from
 * @param osc_frequency_mhz	Current oscillator frequency
 * @param config	structure to use to return information
 * @returns 0 on success, -ve on error, in which case config may or may not be
 *			unchanged. If the node is present but expected data is
 *			missing then this will generally return
 *			-FDT_ERR_MISSING.
 */
int fdt_decode_usb(const void *blob, int node, unsigned osc_frequency_mhz,
		struct fdt_usb *config);

/**
 * Returns information from the FDT about an SDMMC port. This function reads
 * out the following attributes:
 *
 *	reg
 *	width
 *	periph-id
 *	enabled
 *
 * @param blob		FDT blob to use
 * @param node		Node to read from
 * @param config	structure to use to return information
 * @returns 0 on success, -ve on error, in which case config may or may not be
 *			unchanged. If the node is present but expected data is
 *			missing then this will generally return
 *			-FDT_ERR_MISSING.
 */
int fdt_decode_sdmmc(const void *blob, int node, struct fdt_sdmmc *config);

/**
 * Look in the FDT for a config item with the given name and return its value
 * as a string.
 *
 * @param blob		FDT blob
 * @param prop_name	property name to look up
 * @returns property string, NULL on error.
 */
char *fdt_decode_get_config_string(const void *blob, const char *prop_name);

/**
 * Look in the FDT for a config item with the given name and return its value
 * as a 32-bit integer. The property must have at least 4 bytes of data. The
 * value of the first cell is returned.
 *
 * @param blob		FDT blob
 * @param prop_name	property name to look up
 * @param default_val	default value to return if the property is not found
 * @return integer value, if found, or default_val if not
 */
int fdt_decode_get_config_int(const void *blob, const char *prop_name,
		int default_val);

/**
 * Returns information from the FDT about an i2c controler. This function reads
 * out the following attributes:
 *
 *	reg
 *	pinmux
 *	speed
 *	periph-id
 *
 * @param blob		FDT blob to use
 * @param node		Node to read from
 * @param config	structure to use to return information
 * @returns 0 on success, -ve on error, in which case config may or may not be
 *			unchanged. If the node is present but expected data is
 *			missing then this will generally return
 *			-FDT_ERR_MISSING.
 */
int fdt_decode_i2c(const void *blob, int node, struct fdt_i2c *config);

/**
 * Returns information from the FDT about the keboard controler. This function
 * reads out the following attributes:
 *
 *	reg
 *	keycode-plain
 *	keycode-shift
 *	keycode-fn
 *	keycode-ctrl
 *
 * @param blob		FDT blob to use
 * @param node		Node to read from
 * @param config	structure to use to return information
 * @returns 0 on success, -ve on error, in which case config may or may not be
 *			unchanged. If the node is present but expected data is
 *			missing then this will generally return
 *			-FDT_ERR_MISSING.
 */
int fdt_decode_kbc(const void *blob, int node, struct fdt_kbc *config);

/**
 * Returns the model name of the device. This returns the /model property
 * from the fdt.
 *
 * \return model name, or "<not defined>" if unknown
 */
const char *fdt_decode_get_model(const void *blob);

/**
 * Returns the machine architecture ID of the device. This is used by Linux
 * to specify the machine that it is running on. We put it in the fdt so that
 * it can easily be controlled from there.
 *
 * \return architecture number or -1 if not found
 */
int fdt_decode_get_machine_arch_id(const void *blob);