1 /* 2 * Copyright (c) 2011 The Chromium OS Authors. 3 * See file CREDITS for list of people who contributed to this 4 * project. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 * MA 02111-1307 USA 20 */ 21 22 #include <common.h> 23 #include <serial.h> 24 #include <libfdt.h> 25 #include <fdtdec.h> 26 27 DECLARE_GLOBAL_DATA_PTR; 28 29 /* 30 * Here are the type we know about. One day we might allow drivers to 31 * register. For now we just put them here. The COMPAT macro allows us to 32 * turn this into a sparse list later, and keeps the ID with the name. 33 */ 34 #define COMPAT(id, name) name 35 static const char * const compat_names[COMPAT_COUNT] = { 36 }; 37 38 /** 39 * Look in the FDT for an alias with the given name and return its node. 40 * 41 * @param blob FDT blob 42 * @param name alias name to look up 43 * @return node offset if found, or an error code < 0 otherwise 44 */ 45 static int find_alias_node(const void *blob, const char *name) 46 { 47 const char *path; 48 int alias_node; 49 50 debug("find_alias_node: %s\n", name); 51 alias_node = fdt_path_offset(blob, "/aliases"); 52 if (alias_node < 0) 53 return alias_node; 54 path = fdt_getprop(blob, alias_node, name, NULL); 55 if (!path) 56 return -FDT_ERR_NOTFOUND; 57 return fdt_path_offset(blob, path); 58 } 59 60 fdt_addr_t fdtdec_get_addr(const void *blob, int node, 61 const char *prop_name) 62 { 63 const fdt_addr_t *cell; 64 int len; 65 66 debug("get_addr: %s\n", prop_name); 67 cell = fdt_getprop(blob, node, prop_name, &len); 68 if (cell && (len == sizeof(fdt_addr_t) || 69 len == sizeof(fdt_addr_t) * 2)) 70 return fdt_addr_to_cpu(*cell); 71 return FDT_ADDR_T_NONE; 72 } 73 74 s32 fdtdec_get_int(const void *blob, int node, const char *prop_name, 75 s32 default_val) 76 { 77 const s32 *cell; 78 int len; 79 80 debug("get_size: %s\n", prop_name); 81 cell = fdt_getprop(blob, node, prop_name, &len); 82 if (cell && len >= sizeof(s32)) 83 return fdt32_to_cpu(cell[0]); 84 return default_val; 85 } 86 87 int fdtdec_get_is_enabled(const void *blob, int node, int default_val) 88 { 89 const char *cell; 90 91 cell = fdt_getprop(blob, node, "status", NULL); 92 if (cell) 93 return 0 == strcmp(cell, "ok"); 94 return default_val; 95 } 96 97 enum fdt_compat_id fd_dec_lookup(const void *blob, int node) 98 { 99 enum fdt_compat_id id; 100 101 /* Search our drivers */ 102 for (id = COMPAT_UNKNOWN; id < COMPAT_COUNT; id++) 103 if (0 == fdt_node_check_compatible(blob, node, 104 compat_names[id])) 105 return id; 106 return COMPAT_UNKNOWN; 107 } 108 109 int fdtdec_next_compatible(const void *blob, int node, 110 enum fdt_compat_id id) 111 { 112 return fdt_node_offset_by_compatible(blob, node, compat_names[id]); 113 } 114 115 int fdtdec_next_alias(const void *blob, const char *name, 116 enum fdt_compat_id id, int *upto) 117 { 118 #define MAX_STR_LEN 20 119 char str[MAX_STR_LEN + 20]; 120 int node, err; 121 122 /* snprintf() is not available */ 123 assert(strlen(name) < MAX_STR_LEN); 124 sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto); 125 (*upto)++; 126 node = find_alias_node(blob, str); 127 if (node < 0) 128 return node; 129 err = fdt_node_check_compatible(blob, node, compat_names[id]); 130 if (err < 0) 131 return err; 132 return err ? -FDT_ERR_NOTFOUND : node; 133 } 134 135 /* 136 * This function is a little odd in that it accesses global data. At some 137 * point if the architecture board.c files merge this will make more sense. 138 * Even now, it is common code. 139 */ 140 int fdtdec_check_fdt(void) 141 { 142 /* We must have an fdt */ 143 if (fdt_check_header(gd->fdt_blob)) 144 panic("No valid fdt found - please append one to U-Boot\n" 145 "binary or define CONFIG_OF_EMBED\n"); 146 return 0; 147 } 148