Commit | Line | Data |
---|---|---|
93fac324 MM |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | ||
19 | */ | |
20 | ||
21 | ||
22 | #ifndef _DEVICE_TREE_H_ | |
23 | #define _DEVICE_TREE_H_ | |
24 | ||
25 | #ifndef INLINE_DEVICE | |
26 | #define INLINE_DEVICE | |
27 | #endif | |
28 | ||
29 | ||
30 | ||
31 | /* declared in basics.h, this object is used everywhere */ | |
32 | /* typedef struct _device device; */ | |
33 | ||
34 | ||
35 | ||
36 | \f | |
37 | /* Device Tree: | |
38 | ||
39 | All the devices in this model live in a tree. The following allow | |
40 | the location/manipulation of this tree */ | |
41 | ||
979c3c25 | 42 | INLINE_DEVICE(device *) device_parent |
93fac324 MM |
43 | (device *me); |
44 | ||
979c3c25 | 45 | INLINE_DEVICE(device *) device_sibling |
93fac324 MM |
46 | (device *me); |
47 | ||
979c3c25 MM |
48 | INLINE_DEVICE(device *) device_child |
49 | (device *me); | |
50 | ||
51 | INLINE_DEVICE(const char *) device_name | |
52 | (device *me); | |
53 | ||
54 | INLINE_DEVICE(void *) device_data | |
93fac324 MM |
55 | (device *me); |
56 | ||
57 | ||
58 | /* Grow the device tree adding either a specific device or | |
59 | alternativly a device found in the device table */ | |
60 | ||
979c3c25 | 61 | INLINE_DEVICE(device *)device_tree_add_device |
93fac324 MM |
62 | (device *root, |
63 | const char *prefix, | |
64 | device *new_sub_tree); | |
65 | ||
979c3c25 | 66 | INLINE_DEVICE(device *) device_tree_add_found |
93fac324 MM |
67 | (device *root, |
68 | const char *prefix, | |
69 | const char *name); | |
70 | ||
979c3c25 | 71 | INLINE_DEVICE(device *) device_tree_add_found_c |
93fac324 MM |
72 | (device *root, |
73 | const char *prefix, | |
74 | const char *name, | |
75 | const char *c1); | |
76 | ||
979c3c25 | 77 | INLINE_DEVICE(device *) device_tree_add_found_c_uw |
93fac324 MM |
78 | (device *root, |
79 | const char *prefix, | |
80 | const char *name, | |
81 | const char *c1, | |
82 | unsigned_word uw2); | |
83 | ||
979c3c25 | 84 | INLINE_DEVICE(device *) device_tree_add_found_uw_u |
93fac324 MM |
85 | (device *root, |
86 | const char *prefix, | |
87 | const char *name, | |
88 | unsigned_word uw1, | |
89 | unsigned u2); | |
90 | ||
979c3c25 | 91 | INLINE_DEVICE(device *) device_tree_add_found_uw_u_u |
93fac324 MM |
92 | (device *root, |
93 | const char *prefix, | |
94 | const char *name, | |
95 | unsigned_word uw1, | |
96 | unsigned u2, | |
97 | unsigned u3); | |
98 | ||
979c3c25 | 99 | INLINE_DEVICE(device *) device_tree_add_found_uw_u_u_c |
93fac324 MM |
100 | (device *root, |
101 | const char *prefix, | |
102 | const char *name, | |
103 | unsigned_word uw1, | |
104 | unsigned u2, | |
105 | unsigned u3, | |
106 | const char *c4); | |
107 | ||
979c3c25 | 108 | INLINE_DEVICE(device *) device_tree_add_found_uw_uw_u_u_c |
93fac324 MM |
109 | (device *root, |
110 | const char *prefix, | |
111 | const char *name, | |
112 | unsigned_word uw1, | |
113 | unsigned_word uw2, | |
114 | unsigned u3, | |
115 | unsigned u4, | |
116 | const char *c5); | |
117 | ||
979c3c25 | 118 | INLINE_DEVICE(device *) device_tree_add_found_uw_uw_u_u_u |
93fac324 MM |
119 | (device *root, |
120 | const char *prefix, | |
121 | const char *name, | |
122 | unsigned_word uw1, | |
123 | unsigned_word uw2, | |
124 | unsigned u3, | |
125 | unsigned u4, | |
126 | unsigned u5); | |
127 | ||
128 | ||
129 | /* Query the device tree, null is returned if the specified device is | |
130 | not found */ | |
131 | ||
979c3c25 | 132 | INLINE_DEVICE(device *) device_tree_find_device |
93fac324 MM |
133 | (device *root, |
134 | const char *path); | |
135 | ||
136 | ||
137 | /* traverse the device tree visiting all notes (either pre or post | |
138 | fix) */ | |
139 | ||
140 | typedef void (device_tree_traverse_function) | |
141 | (device *device, | |
142 | void *data); | |
143 | ||
979c3c25 | 144 | INLINE_DEVICE(void) device_tree_traverse |
93fac324 MM |
145 | (device *root, |
146 | device_tree_traverse_function *prefix, | |
147 | device_tree_traverse_function *postfix, | |
148 | void *data); | |
149 | ||
150 | ||
151 | /* dump a node, this can be passed to the device_tree_traverse() | |
152 | function to dump out the entire device tree */ | |
153 | ||
979c3c25 | 154 | INLINE_DEVICE(void) device_tree_dump |
93fac324 MM |
155 | (device *device, |
156 | void *ignore_data_argument); | |
157 | ||
158 | ||
159 | ||
160 | \f | |
161 | /* Device Properties: | |
162 | ||
163 | Attached to a device (typically by open boot firmware) are | |
164 | properties that profile the devices features. The below allow the | |
165 | manipulation of device properties */ | |
166 | ||
167 | /* Each device can have associated properties. Internal to | |
168 | psim those properties are strictly typed. Within the simulation, | |
169 | no such control exists */ | |
170 | ||
171 | typedef enum { | |
172 | integer_property, | |
173 | boolean_property, | |
174 | string_property, | |
175 | array_property, | |
176 | null_property, | |
177 | } device_property_type; | |
178 | ||
179 | typedef struct _device_property device_property; | |
180 | struct _device_property { | |
181 | device *owner; | |
182 | device_property_type type; | |
183 | unsigned sizeof_array; | |
184 | const void *array; | |
185 | }; | |
186 | ||
187 | ||
188 | /* Basic operations used by software */ | |
189 | ||
979c3c25 | 190 | INLINE_DEVICE(const char *) device_find_next_property |
93fac324 MM |
191 | (device *me, |
192 | const char *previous); | |
193 | ||
93fac324 MM |
194 | /* INLINE_DEVICE void device_add_property |
195 | No such external function, all properties, when added are explictly | |
196 | typed */ | |
197 | ||
979c3c25 | 198 | INLINE_DEVICE(void) device_add_array_property |
93fac324 MM |
199 | (device *me, |
200 | const char *property, | |
201 | const void *array, | |
202 | int sizeof_array); | |
203 | ||
979c3c25 | 204 | INLINE_DEVICE(void) device_add_integer_property |
93fac324 MM |
205 | (device *me, |
206 | const char *property, | |
207 | signed_word integer); | |
208 | ||
979c3c25 | 209 | INLINE_DEVICE(void) device_add_boolean_property |
93fac324 MM |
210 | (device *me, |
211 | const char *property, | |
212 | int bool); | |
213 | ||
979c3c25 | 214 | INLINE_DEVICE(void) device_add_null_property |
93fac324 MM |
215 | (device *me, |
216 | const char *property); | |
217 | ||
979c3c25 | 218 | INLINE_DEVICE(void) device_add_string_property |
93fac324 MM |
219 | (device *me, |
220 | const char *property, | |
221 | const char *string); | |
222 | ||
223 | ||
224 | /* Locate a property returning its description. Return NULL if the | |
225 | named property is not found */ | |
226 | ||
979c3c25 | 227 | INLINE_DEVICE(const device_property *) device_find_property |
93fac324 MM |
228 | (device *me, |
229 | const char *property); | |
230 | ||
231 | ||
232 | /* Process all properties attached to the named device */ | |
233 | ||
234 | typedef void (device_traverse_property_function) | |
235 | (device *me, | |
236 | const char *name, | |
237 | void *data); | |
238 | ||
979c3c25 | 239 | INLINE_DEVICE(void) device_traverse_properties |
93fac324 MM |
240 | (device *me, |
241 | device_traverse_property_function *traverse, | |
242 | void *data); | |
243 | ||
244 | ||
245 | /* Similar to above except that the property *must* be in the device | |
246 | tree and *must* be of the specified type. */ | |
247 | ||
979c3c25 | 248 | INLINE_DEVICE(const device_property *) device_find_array_property |
93fac324 MM |
249 | (device *me, |
250 | const char *property); | |
251 | ||
979c3c25 | 252 | INLINE_DEVICE(signed_word) device_find_integer_property |
93fac324 MM |
253 | (device *me, |
254 | const char *property); | |
255 | ||
979c3c25 | 256 | INLINE_DEVICE(const char *) device_find_string_property |
93fac324 MM |
257 | (device *me, |
258 | const char *property); | |
259 | ||
979c3c25 | 260 | INLINE_DEVICE(int) device_find_boolean_property |
93fac324 MM |
261 | (device *me, |
262 | const char *property); | |
263 | ||
264 | ||
265 | \f | |
266 | /* Device Hardware: | |
267 | ||
268 | A device principaly is modeling real hardware that a processor can | |
269 | directly interact with via load/stores dma's and interrupts. The | |
270 | interface below is used by the hardware side of the device | |
271 | model. */ | |
272 | ||
273 | /* Address access attributes that can be attached to a devices address | |
274 | range */ | |
275 | typedef enum _access_type { | |
276 | access_invalid = 0, | |
277 | access_read = 1, | |
278 | access_write = 2, | |
279 | access_read_write = 3, | |
280 | access_exec = 4, | |
281 | access_read_exec = 5, | |
282 | access_write_exec = 6, | |
283 | access_read_write_exec = 7, | |
284 | } access_type; | |
285 | ||
286 | ||
287 | /* Address attachement types */ | |
288 | typedef enum _attach_type { | |
289 | attach_invalid, | |
290 | attach_callback, | |
291 | attach_default, | |
292 | attach_raw_memory, | |
293 | } attach_type; | |
294 | ||
295 | ||
296 | /* Initialization: | |
297 | ||
298 | A device is made fully functional in two stages. | |
299 | ||
300 | 1. It is created. A device is created _before_ it is entered into | |
301 | the device tree. During creation any permenant structures needed | |
302 | by the device should be created/initialized. | |
303 | ||
304 | 2. It is initialized. Before a simulation run, each device in the | |
305 | device tree is initialized in prefix order. As part of this | |
306 | initialization, a device should (re)attach its self to its parent | |
307 | as needed. | |
308 | ||
309 | */ | |
310 | ||
979c3c25 | 311 | INLINE_DEVICE(device *) device_create |
93fac324 MM |
312 | (const char *name, |
313 | device *parent); | |
314 | ||
315 | /* some external functions want to create things */ | |
316 | typedef struct _device_callbacks device_callbacks; | |
317 | ||
979c3c25 | 318 | INLINE_DEVICE(device *) device_create_from |
93fac324 MM |
319 | (const char *name, |
320 | void *data, | |
321 | const device_callbacks *callbacks, | |
322 | device *parent); | |
323 | ||
979c3c25 | 324 | INLINE_DEVICE(void) device_init |
93fac324 MM |
325 | (device *me, |
326 | psim *system); | |
327 | ||
328 | /* initialize the entire tree */ | |
329 | ||
979c3c25 | 330 | INLINE_DEVICE(void) device_tree_init |
93fac324 MM |
331 | (device *root, |
332 | psim *system); | |
333 | ||
334 | ||
335 | /* Data transfers: | |
336 | ||
337 | A device may permit the reading/writing (IO) of its registers in | |
338 | one or more address spaces. For instance, a PCI device may have | |
339 | config registers in its config space and control registers in both | |
340 | the io and memory spaces of a PCI bus. | |
341 | ||
342 | Similarly, a device may initiate a data transfer (DMA) by passing | |
343 | such a request up to its parent. | |
344 | ||
345 | Init: | |
346 | ||
347 | As part of its initialization (not creation) and possibly also as a | |
348 | consequence of IO a device may attach its self to one or more of | |
349 | the address spaces of its parent device. | |
350 | ||
351 | For instance, a PCI device, during initialization would attach its | |
352 | config registers (space=0?, base=0, nr_bytes=64) to its parent PCI | |
353 | bridge. Later, due to a write to this config space, the same | |
354 | device may in turn find it necessary to also attach its self to | |
355 | it's parent's `memory' or `io' space. | |
356 | ||
357 | To perform these operations, a device will call upon its parent | |
358 | using either device_attach_address or device_detach_address. | |
359 | ||
360 | * Any address specified is according to what the device expects to | |
361 | see. | |
362 | ||
363 | * Any detach operation must exactly match a previous attach. | |
364 | ||
365 | * included with the attach or detach is the devices name, the | |
366 | parent may use this as part of determining how to map map between a | |
367 | child's address + space and its own. | |
368 | ||
369 | * at any time, at most one device can have a default mapping | |
370 | registered. | |
371 | ||
372 | ||
373 | IO: | |
374 | ||
375 | A device receives requests to perform reads/writes to its registers | |
376 | or memory either A. from a processor or B. from a parent device. | |
377 | ||
378 | The device may then in turn either A. resolve the IO request | |
379 | locally by processing the data or trigering an exception or | |
380 | B. re-mapping the access onto one of its local address spaces and | |
381 | then in turn passing that on to one of its children. | |
382 | ||
383 | * Any address passed is relative to the local device. Eg for PCI | |
384 | config registers, the address would (normally) be in the range of 0 | |
385 | to 63. | |
386 | ||
387 | * Any exception situtation triggered by an IO operation (processor | |
388 | != NULL) is handled in one of the following ways: 1. Machine check | |
389 | (and similar): issued immediatly by restarting the cpu; 2. External | |
390 | exception: issue delayed (using events.h) until the current | |
391 | instruction execution cycle is completed; 3. Slave device (and | |
392 | similar): the need for the interrupt is passed on to the devices | |
393 | parent (which being an interrupt control unit will in turn take one | |
394 | of the actions described here); 4. Forget it. | |
395 | ||
396 | * Any exception situtation trigered by a non IO operation | |
397 | (processor == NULL) is handled buy returning 0. | |
398 | ||
399 | * Transfers of size <= 8 and of a power of 2 *must* be correctly | |
400 | aligned and should be treated as a `single cycle' transfer. | |
401 | ||
402 | DMA: | |
403 | ||
404 | A device initiates a DMA transfer by calling its parent with the | |
405 | request. At the top level (if not done earlier) this is reflected | |
406 | back down the tree as io read/writes to the target device. | |
407 | ||
408 | This function is subject to change ... | |
409 | ||
410 | */ | |
411 | ||
979c3c25 | 412 | INLINE_DEVICE(void) device_attach_address |
93fac324 MM |
413 | (device *me, |
414 | const char *name, | |
415 | attach_type attach, | |
416 | int space, | |
417 | unsigned_word addr, | |
418 | unsigned nr_bytes, | |
419 | access_type access, | |
420 | device *who); /*callback/default*/ | |
421 | ||
979c3c25 | 422 | INLINE_DEVICE(void) device_detach_address |
93fac324 MM |
423 | (device *me, |
424 | const char *name, | |
425 | attach_type attach, | |
426 | int space, | |
427 | unsigned_word addr, | |
428 | unsigned nr_bytes, | |
429 | access_type access, | |
430 | device *who); /*callback/default*/ | |
431 | ||
979c3c25 | 432 | INLINE_DEVICE(unsigned) device_io_read_buffer |
93fac324 MM |
433 | (device *me, |
434 | void *dest, | |
435 | int space, | |
436 | unsigned_word addr, | |
437 | unsigned nr_bytes, | |
438 | cpu *processor, | |
439 | unsigned_word cia); | |
440 | ||
979c3c25 | 441 | INLINE_DEVICE(unsigned) device_io_write_buffer |
93fac324 MM |
442 | (device *me, |
443 | const void *source, | |
444 | int space, | |
445 | unsigned_word addr, | |
446 | unsigned nr_bytes, | |
447 | cpu *processor, | |
448 | unsigned_word cia); | |
449 | ||
979c3c25 | 450 | INLINE_DEVICE(unsigned) device_dma_read_buffer |
93fac324 MM |
451 | (device *me, |
452 | void *dest, | |
453 | int space, | |
454 | unsigned_word addr, | |
455 | unsigned nr_bytes); | |
456 | ||
979c3c25 | 457 | INLINE_DEVICE(unsigned) device_dma_write_buffer |
93fac324 MM |
458 | (device *me, |
459 | const void *source, | |
460 | int space, | |
461 | unsigned_word addr, | |
462 | unsigned nr_bytes, | |
463 | int violate_read_only_section); | |
464 | ||
465 | ||
466 | /* Interrupts: | |
467 | ||
468 | As mentioned above. Instead of handling an interrupt directly, a | |
469 | device may instead pass the need to interrupt on to its parent. | |
470 | ||
471 | Init: | |
472 | ||
473 | Before passing interrupts up to is parent, a device must first | |
474 | attach its interrupt lines to the parent device. To do this, the | |
475 | device uses the parents attach/detach calls. | |
476 | ||
477 | Interrupts: | |
478 | ||
479 | A child notifies a parent of a change in an interrupt lines status | |
480 | using the interrupt call. Similarly, a parent may notify a child | |
481 | of any `interrupt ack' sequence using the interrupt_ack call. | |
482 | ||
483 | */ | |
484 | ||
979c3c25 | 485 | INLINE_DEVICE(void) device_attach_interrupt |
93fac324 MM |
486 | (device *me, |
487 | device *who, | |
488 | int interrupt_line, | |
489 | const char *name); | |
490 | ||
979c3c25 | 491 | INLINE_DEVICE(void) device_detach_interrupt |
93fac324 MM |
492 | (device *me, |
493 | device *who, | |
494 | int interrupt_line, | |
495 | const char *name); | |
496 | ||
979c3c25 | 497 | INLINE_DEVICE(void) device_interrupt |
93fac324 MM |
498 | (device *me, |
499 | device *who, | |
500 | int interrupt_line, | |
501 | int interrupt_status, | |
502 | cpu *processor, | |
503 | unsigned_word cia); | |
504 | ||
979c3c25 | 505 | INLINE_DEVICE(void) device_interrupt_ack |
93fac324 MM |
506 | (device *me, |
507 | int interrupt_line, | |
508 | int interrupt_status); | |
509 | ||
510 | ||
511 | /* IOCTL: | |
512 | ||
513 | Very simply, a catch all for any thing that turns up that until now | |
514 | either hasn't been thought of or doesn't justify an extra function. */ | |
515 | ||
979c3c25 MM |
516 | EXTERN_DEVICE\ |
517 | (void) device_ioctl | |
93fac324 MM |
518 | (device *me, |
519 | psim *system, | |
520 | cpu *processor, | |
521 | unsigned_word cia, | |
522 | ...); | |
523 | ||
524 | ||
525 | \f | |
526 | /* Device software - the instance | |
527 | ||
528 | Under development | |
529 | ||
530 | In addition to the processor directly manipulating a device via | |
531 | read/write operations. A program may manipulate a device | |
532 | indirectly via OpenBoot calls. The following provide a higher | |
533 | level software interface to the devices */ | |
534 | ||
669b4e1e | 535 | #if 0 |
979c3c25 | 536 | INLINE_DEVICE(device_instance *)device_instance_open |
93fac324 MM |
537 | (device *me, |
538 | const char *device_specifier); | |
539 | ||
979c3c25 | 540 | INLINE_DEVICE(void) device_instance_close |
93fac324 MM |
541 | (device_instance *instance); |
542 | ||
979c3c25 | 543 | INLINE_DEVICE(int) device_instance_read |
93fac324 MM |
544 | (device_instance *instance, |
545 | void *addr, | |
546 | unsigned_word len); | |
547 | ||
979c3c25 | 548 | INLINE_DEVICE(int) device_instance_write |
93fac324 MM |
549 | (device_instance *instance, |
550 | const void *addr, | |
551 | unsigned_word len); | |
552 | ||
979c3c25 | 553 | INLINE_DEVICE(int) device_instance_seek |
93fac324 MM |
554 | (device_instance *instance, |
555 | unsigned_word pos_hi, | |
556 | unsigned_word pos_lo); | |
557 | ||
979c3c25 | 558 | INLINE_DEVICE(device *) device_instance_device |
93fac324 MM |
559 | (device_instance *instance); |
560 | ||
979c3c25 | 561 | INLINE_DEVICE(const char *) device_instance_name |
93fac324 | 562 | (device_instance *instance); |
669b4e1e | 563 | #endif |
93fac324 MM |
564 | |
565 | ||
566 | ||
567 | \f | |
568 | /* Device dregs... */ | |
569 | ||
93fac324 MM |
570 | /* Parse a device name, various formats: |
571 | ||
572 | uw: unsigned_word | |
573 | u: unsigned | |
574 | c: string */ | |
575 | ||
979c3c25 | 576 | INLINE_DEVICE(int) scand_c |
93fac324 MM |
577 | (const char *name, |
578 | char *c1, | |
579 | unsigned c1size); | |
580 | ||
979c3c25 | 581 | INLINE_DEVICE(int) scand_c_uw_u |
93fac324 MM |
582 | (const char *name, |
583 | char *c1, | |
584 | unsigned c1size, | |
585 | unsigned_word *uw2, | |
586 | unsigned *u3); | |
587 | ||
979c3c25 | 588 | INLINE_DEVICE(int) scand_uw |
93fac324 MM |
589 | (const char *name, |
590 | unsigned_word *uw1); | |
591 | ||
979c3c25 | 592 | INLINE_DEVICE(int) scand_uw_c |
93fac324 MM |
593 | (const char *name, |
594 | unsigned_word *uw1, | |
595 | char *c2, | |
596 | unsigned c2size); | |
597 | ||
979c3c25 | 598 | INLINE_DEVICE(int) scand_uw_u |
93fac324 MM |
599 | (const char *name, |
600 | unsigned_word *uw1, | |
601 | unsigned *u2); | |
602 | ||
979c3c25 | 603 | INLINE_DEVICE(int) scand_uw_u_u |
93fac324 MM |
604 | (const char *name, |
605 | unsigned_word *uw1, | |
606 | unsigned *u2, | |
607 | unsigned *u3); | |
608 | ||
979c3c25 | 609 | INLINE_DEVICE(int) scand_uw_u_u_c |
93fac324 MM |
610 | (const char *name, |
611 | unsigned_word *uw1, | |
612 | unsigned *u2, | |
613 | unsigned *u3, | |
614 | char *c4, | |
615 | unsigned c4size); | |
616 | ||
979c3c25 | 617 | INLINE_DEVICE(int) scand_uw_uw |
93fac324 MM |
618 | (const char *name, |
619 | unsigned_word *uw1, | |
620 | unsigned_word *uw2); | |
621 | ||
979c3c25 | 622 | INLINE_DEVICE(int) scand_uw_uw_u |
93fac324 MM |
623 | (const char *name, |
624 | unsigned_word *uw1, | |
625 | unsigned_word *uw2, | |
626 | unsigned *u3); | |
627 | ||
979c3c25 | 628 | INLINE_DEVICE(int) scand_uw_uw_u_u_c |
93fac324 MM |
629 | (const char *name, |
630 | unsigned_word *uw1, | |
631 | unsigned_word *uw2, | |
632 | unsigned *u3, | |
633 | unsigned *u4, | |
634 | char *c5, | |
635 | unsigned c5size); | |
636 | ||
979c3c25 | 637 | INLINE_DEVICE(int) scand_uw_uw_u_u_u |
93fac324 MM |
638 | (const char *name, |
639 | unsigned_word *uw1, | |
640 | unsigned_word *uw2, | |
641 | unsigned *u3, | |
642 | unsigned *u4, | |
643 | unsigned *u5); | |
644 | ||
645 | #endif /* _DEVICE_TREE_H_ */ |