1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2013 Google, Inc 4 * 5 * (C) Copyright 2012 6 * Marek Vasut <marex@denx.de> 7 */ 8 9 #include <common.h> 10 #include <errno.h> 11 #include <dm/device.h> 12 #include <dm/device-internal.h> 13 #include <dm/lists.h> 14 #include <dm/platdata.h> 15 #include <dm/uclass.h> 16 #include <dm/util.h> 17 #include <fdtdec.h> 18 #include <linux/compiler.h> 19 20 struct driver *lists_driver_lookup_name(const char *name) 21 { 22 struct driver *drv = 23 ll_entry_start(struct driver, driver); 24 const int n_ents = ll_entry_count(struct driver, driver); 25 struct driver *entry; 26 27 for (entry = drv; entry != drv + n_ents; entry++) { 28 if (!strcmp(name, entry->name)) 29 return entry; 30 } 31 32 /* Not found */ 33 return NULL; 34 } 35 36 struct uclass_driver *lists_uclass_lookup(enum uclass_id id) 37 { 38 struct uclass_driver *uclass = 39 ll_entry_start(struct uclass_driver, uclass); 40 const int n_ents = ll_entry_count(struct uclass_driver, uclass); 41 struct uclass_driver *entry; 42 43 for (entry = uclass; entry != uclass + n_ents; entry++) { 44 if (entry->id == id) 45 return entry; 46 } 47 48 return NULL; 49 } 50 51 int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only) 52 { 53 struct driver_info *info = 54 ll_entry_start(struct driver_info, driver_info); 55 const int n_ents = ll_entry_count(struct driver_info, driver_info); 56 struct driver_info *entry; 57 struct udevice *dev; 58 int result = 0; 59 int ret; 60 61 for (entry = info; entry != info + n_ents; entry++) { 62 ret = device_bind_by_name(parent, pre_reloc_only, entry, &dev); 63 if (ret && ret != -EPERM) { 64 dm_warn("No match for driver '%s'\n", entry->name); 65 if (!result || ret != -ENOENT) 66 result = ret; 67 } 68 } 69 70 return result; 71 } 72 73 int device_bind_driver(struct udevice *parent, const char *drv_name, 74 const char *dev_name, struct udevice **devp) 75 { 76 return device_bind_driver_to_node(parent, drv_name, dev_name, 77 ofnode_null(), devp); 78 } 79 80 int device_bind_driver_to_node(struct udevice *parent, const char *drv_name, 81 const char *dev_name, ofnode node, 82 struct udevice **devp) 83 { 84 struct driver *drv; 85 int ret; 86 87 drv = lists_driver_lookup_name(drv_name); 88 if (!drv) { 89 debug("Cannot find driver '%s'\n", drv_name); 90 return -ENOENT; 91 } 92 ret = device_bind_with_driver_data(parent, drv, dev_name, 0 /* data */, 93 node, devp); 94 95 return ret; 96 } 97 98 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 99 /** 100 * driver_check_compatible() - Check if a driver matches a compatible string 101 * 102 * @param of_match: List of compatible strings to match 103 * @param of_idp: Returns the match that was found 104 * @param compat: The compatible string to search for 105 * @return 0 if there is a match, -ENOENT if no match 106 */ 107 static int driver_check_compatible(const struct udevice_id *of_match, 108 const struct udevice_id **of_idp, 109 const char *compat) 110 { 111 if (!of_match) 112 return -ENOENT; 113 114 while (of_match->compatible) { 115 if (!strcmp(of_match->compatible, compat)) { 116 *of_idp = of_match; 117 return 0; 118 } 119 of_match++; 120 } 121 122 return -ENOENT; 123 } 124 125 int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp) 126 { 127 struct driver *driver = ll_entry_start(struct driver, driver); 128 const int n_ents = ll_entry_count(struct driver, driver); 129 const struct udevice_id *id; 130 struct driver *entry; 131 struct udevice *dev; 132 bool found = false; 133 const char *name, *compat_list, *compat; 134 int compat_length, i; 135 int result = 0; 136 int ret = 0; 137 138 if (devp) 139 *devp = NULL; 140 name = ofnode_get_name(node); 141 pr_debug("bind node %s\n", name); 142 143 compat_list = ofnode_get_property(node, "compatible", &compat_length); 144 if (!compat_list) { 145 if (compat_length == -FDT_ERR_NOTFOUND) { 146 pr_debug("Device '%s' has no compatible string\n", 147 name); 148 return 0; 149 } 150 151 dm_warn("Device tree error at node '%s'\n", name); 152 return compat_length; 153 } 154 155 /* 156 * Walk through the compatible string list, attempting to match each 157 * compatible string in order such that we match in order of priority 158 * from the first string to the last. 159 */ 160 for (i = 0; i < compat_length; i += strlen(compat) + 1) { 161 compat = compat_list + i; 162 pr_debug(" - attempt to match compatible string '%s'\n", 163 compat); 164 165 for (entry = driver; entry != driver + n_ents; entry++) { 166 ret = driver_check_compatible(entry->of_match, &id, 167 compat); 168 if (!ret) 169 break; 170 } 171 if (entry == driver + n_ents) 172 continue; 173 174 pr_debug(" - found match at '%s'\n", entry->name); 175 ret = device_bind_with_driver_data(parent, entry, name, 176 id->data, node, &dev); 177 if (ret == -ENODEV) { 178 pr_debug("Driver '%s' refuses to bind\n", entry->name); 179 continue; 180 } 181 if (ret) { 182 dm_warn("Error binding driver '%s': %d\n", entry->name, 183 ret); 184 return ret; 185 } else { 186 found = true; 187 if (devp) 188 *devp = dev; 189 } 190 break; 191 } 192 193 if (!found && !result && ret != -ENODEV) 194 pr_debug("No match for node '%s'\n", name); 195 196 return result; 197 } 198 #endif 199