"Das U-Boot" Source Tree
at pomera-dm250 443 lines 15 kB view raw
1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * Copyright 2021 Google LLC 4 * Written by Simon Glass <sjg@chromium.org> 5 */ 6 7#ifndef __bootdev_h 8#define __bootdev_h 9 10#include <dm/uclass-id.h> 11#include <linux/list.h> 12 13struct bootflow; 14struct bootflow_iter; 15struct bootstd_priv; 16struct udevice; 17 18/** 19 * enum bootdev_prio_t - priority of each bootdev 20 * 21 * These values are associated with each bootdev and set up by the driver. 22 * 23 * Smallest value is the highest priority. By default, bootdevs are scanned from 24 * highest to lowest priority 25 * 26 * BOOTDEVP_0_NONE: Invalid value, do not use 27 * @BOOTDEVP_6_PRE_SCAN: Scan bootdevs with this priority always, before 28 * starting any bootflow scan 29 * @BOOTDEVP_2_INTERNAL_FAST: Internal devices which don't need scanning and 30 * generally very quick to access, e.g. less than 100ms 31 * @BOOTDEVP_3_INTERNAL_SLOW: Internal devices which don't need scanning but 32 * take a significant fraction of a second to access 33 * @BOOTDEVP_4_SCAN_FAST: Extenal devices which need scanning or bus 34 * enumeration to find, but this enumeration happens quickly, typically under 35 * 100ms 36 * @BOOTDEVP_5_SCAN_SLOW: Extenal devices which need scanning or bus 37 * enumeration to find. The enumeration takes significant fraction of a second 38 * to complete 39 * @BOOTDEVP_6_NET_BASE: Basic network devices which are quickly and easily 40 * available. Typically used for an internal Ethernet device 41 * @BOOTDEVP_7_NET_FALLBACK: Secondary network devices which require extra time 42 * to start up, or are less desirable. Typically used for secondary Ethernet 43 * devices. Note that USB ethernet devices are found during USB enumeration, 44 * so do not use this priority 45 */ 46enum bootdev_prio_t { 47 BOOTDEVP_0_NONE, 48 BOOTDEVP_1_PRE_SCAN, 49 BOOTDEVP_2_INTERNAL_FAST, 50 BOOTDEVP_3_INTERNAL_SLOW, 51 BOOTDEVP_4_SCAN_FAST, 52 BOOTDEVP_5_SCAN_SLOW, 53 BOOTDEVP_6_NET_BASE, 54 BOOTDEVP_7_NET_FALLBACK, 55 56 BOOTDEVP_COUNT, 57}; 58 59struct bootdev_hunter; 60 61/** 62 * bootdev_hunter_func - function to probe for bootdevs of a given type 63 * 64 * This should hunt around for bootdevs of the given type, binding them as it 65 * finds them. This may involve bus enumeration, etc. 66 * 67 * @info: Info structure describing this hunter 68 * @show: true to show information from the hunter 69 * Returns: 0 if OK, -ENOENT on device not found, otherwise -ve on error 70 */ 71typedef int (*bootdev_hunter_func)(struct bootdev_hunter *info, bool show); 72 73/** 74 * struct bootdev_hunter - information about how to hunt for bootdevs 75 * 76 * @prio: Scanning priority of this hunter 77 * @uclass: Uclass ID for the media associated with this bootdev 78 * @drv: bootdev driver for the things found by this hunter 79 * @hunt: Function to call to hunt for bootdevs of this type (NULL if none) 80 * 81 * Some bootdevs are not visible until other devices are enumerated. For 82 * example, USB bootdevs only appear when the USB bus is enumerated. 83 * 84 * On the other hand, we don't always want to enumerate all the buses just to 85 * find the first valid bootdev. Ideally we want to work through them in 86 * priority order, so that the fastest bootdevs are discovered first. 87 * 88 * This struct holds information about the bootdev so we can determine the probe 89 * order and how to hunt for bootdevs of this type 90 */ 91struct bootdev_hunter { 92 enum bootdev_prio_t prio; 93 enum uclass_id uclass; 94 struct driver *drv; 95 bootdev_hunter_func hunt; 96}; 97 98/* declare a new bootdev hunter */ 99#define BOOTDEV_HUNTER(__name) \ 100 ll_entry_declare(struct bootdev_hunter, __name, bootdev_hunter) 101 102/* access a bootdev hunter by name */ 103#define BOOTDEV_HUNTER_GET(__name) \ 104 ll_entry_get(struct bootdev_hunter, __name, bootdev_hunter) 105 106/** 107 * struct bootdev_uc_plat - uclass information about a bootdev 108 * 109 * This is attached to each device in the bootdev uclass and accessible via 110 * dev_get_uclass_plat(dev) 111 * 112 * @piro: Priority of this bootdev 113 */ 114struct bootdev_uc_plat { 115 enum bootdev_prio_t prio; 116}; 117 118/** struct bootdev_ops - Operations for the bootdev uclass */ 119struct bootdev_ops { 120 /** 121 * get_bootflow() - get a bootflow (optional) 122 * 123 * If this is NULL then the default implementaton is used, which is 124 * default_get_bootflow() 125 * 126 * @dev: Bootflow device to check 127 * @iter: Provides current dev, part, method to get. Should update 128 * max_part if there is a partition table. Should update state, 129 * subdir, fname, buf, size according to progress 130 * @bflow: Updated bootflow if found 131 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this 132 * device, -ENOSYS if this device doesn't support bootflows, 133 * other -ve value on other error 134 */ 135 int (*get_bootflow)(struct udevice *dev, struct bootflow_iter *iter, 136 struct bootflow *bflow); 137}; 138 139#define bootdev_get_ops(dev) ((struct bootdev_ops *)(dev)->driver->ops) 140 141/** 142 * bootdev_get_bootflow() - get a bootflow 143 * 144 * @dev: Bootflow device to check 145 * @iter: Provides current part, method to get 146 * @bflow: Returns bootflow if found 147 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this device, 148 * -ENOSYS if this device doesn't support bootflows, other -ve value on 149 * other error 150 */ 151int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, 152 struct bootflow *bflow); 153 154/** 155 * bootdev_bind() - Bind a new named bootdev device 156 * 157 * @parent: Parent of the new device 158 * @drv_name: Driver name to use for the bootdev device 159 * @name: Name for the device (parent name is prepended) 160 * @devp: the new device (which has not been probed) 161 */ 162int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name, 163 struct udevice **devp); 164 165/** 166 * bootdev_find_in_blk() - Find a bootdev in a block device 167 * 168 * @dev: Bootflow device associated with this block device 169 * @blk: Block device to search 170 * @iter: Provides current dev, part, method to get. Should update 171 * max_part if there is a partition table 172 * @bflow: On entry, provides information about the partition and device to 173 * check. On exit, returns bootflow if found 174 * Return: 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error 175 */ 176int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk, 177 struct bootflow_iter *iter, struct bootflow *bflow); 178 179/** 180 * bootdev_list() - List all available bootdevs 181 * 182 * @probe: true to probe devices, false to leave them as is 183 */ 184void bootdev_list(bool probe); 185 186/** 187 * bootdev_first_bootflow() - Get the first bootflow from a bootdev 188 * 189 * Returns the first bootflow attached to a bootdev 190 * 191 * @dev: bootdev device 192 * @bflowp: Returns a pointer to the bootflow 193 * Return: 0 if found, -ENOENT if there are no bootflows 194 */ 195int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp); 196 197/** 198 * bootdev_next_bootflow() - Get the next bootflow from a bootdev 199 * 200 * Returns the next bootflow attached to a bootdev 201 * 202 * @bflowp: On entry, the last bootflow returned , e.g. from 203 * bootdev_first_bootflow() 204 * Return: 0 if found, -ENOENT if there are no more bootflows 205 */ 206int bootdev_next_bootflow(struct bootflow **bflowp); 207 208/** 209 * bootdev_find_by_label() - Look up a bootdev by label 210 * 211 * Each bootdev has a label which contains the media-uclass name and a number, 212 * e.g. 'mmc2'. This looks up the label and returns the associated bootdev 213 * 214 * The lookup is performed based on the media device's sequence number. So for 215 * 'mmc2' this looks for a device in UCLASS_MMC with a dev_seq() of 2. 216 * 217 * @label: Label to look up (e.g. "mmc1" or "mmc0") 218 * @devp: Returns the bootdev device found, or NULL if none (note it does not 219 * return the media device, but its bootdev child) 220 * @method_flagsp: If non-NULL, returns any flags implied by the label 221 * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails 222 * Return: 0 if OK, -EINVAL if the uclass is not supported by this board, 223 * -ENOENT if there is no device with that number 224 */ 225int bootdev_find_by_label(const char *label, struct udevice **devp, 226 int *method_flagsp); 227 228/** 229 * bootdev_find_by_any() - Find a bootdev by name, label or sequence 230 * 231 * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find 232 * @devp: returns the device found, on success 233 * @method_flagsp: If non-NULL, returns any flags implied by the label 234 * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails 235 * Return: 0 if OK, -EPFNOSUPPORT if the uclass is not supported by this board, 236 * -ENOENT if there is no device with that number 237 */ 238int bootdev_find_by_any(const char *name, struct udevice **devp, 239 int *method_flagsp); 240 241/** 242 * bootdev_setup_iter() - Set up iteration through bootdevs 243 * 244 * This sets up the an interation, based on the provided device or label. If 245 * neither is provided, the iteration is based on the priority of each bootdev, 246 * the * bootdev-order property in the bootstd node (or the boot_targets env 247 * var). 248 * 249 * @iter: Iterator to update with the order 250 * @label: label to scan, or NULL to scan all 251 * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single) 252 * device to scan. Returns the first device to use, which is the passed-in 253 * @devp if it was non-NULL 254 * @method_flagsp: If non-NULL, returns any flags implied by the label 255 * (enum bootflow_meth_flags_t), 0 if none 256 * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve 257 * on other error 258 */ 259int bootdev_setup_iter(struct bootflow_iter *iter, const char *label, 260 struct udevice **devp, int *method_flagsp); 261 262/** 263 * bootdev_list_hunters() - List the available bootdev hunters 264 * 265 * These provide a way to find new bootdevs by enumerating buses, etc. This 266 * function lists the available hunters 267 * 268 * @std: Pointer to bootstd private info 269 */ 270void bootdev_list_hunters(struct bootstd_priv *std); 271 272/** 273 * bootdev_hunt() - Hunt for bootdevs matching a particular spec 274 * 275 * This runs the selected hunter (or all if @spec is NULL) to try to find new 276 * bootdevs. 277 * 278 * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must 279 * match a uclass name so that the hunter can be determined. Any trailing number 280 * is ignored 281 * @show: true to show each hunter before using it 282 * Returns: 0 if OK, -ve on error 283 */ 284int bootdev_hunt(const char *spec, bool show); 285 286/** 287 * bootdev_hunt_prio() - Hunt for bootdevs of a particular priority 288 * 289 * This runs all hunters which can find bootdevs of the given priority. 290 * 291 * @prio: Priority to use 292 * @show: true to show each hunter as it is used 293 * Returns: 0 if OK, -ve on error 294 */ 295int bootdev_hunt_prio(enum bootdev_prio_t prio, bool show); 296 297/** 298 * bootdev_unhunt() - Mark a device as needing to be hunted again 299 * 300 * @id: uclass ID to update 301 * Return: 0 if done, -EALREADY if already in this state, -ENOENT if no hunter 302 * found for that uclass 303 */ 304int bootdev_unhunt(enum uclass_id id); 305 306/** 307 * bootdev_hunt_and_find_by_label() - Hunt for bootdevs by label 308 * 309 * Runs the hunter for the label, then tries to find the bootdev, possible 310 * created by the hunter 311 * 312 * @label: Label to look up (e.g. "mmc1" or "mmc0") 313 * @devp: Returns the bootdev device found, or NULL if none (note it does not 314 * return the media device, but its bootdev child) 315 * @method_flagsp: If non-NULL, returns any flags implied by the label 316 * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails 317 * Return: 0 if OK, -EINVAL if the uclass is not supported by this board, 318 * -ENOENT if there is no device with that number 319 */ 320int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp, 321 int *method_flagsp); 322 323/** 324 * bootdev_next_label() - Move to the next bootdev in the label sequence 325 * 326 * Looks through the remaining labels until it finds one that matches a bootdev. 327 * Bootdev scanners are used as needed. For example a label "mmc1" results in 328 * running the "mmc" bootdrv. 329 * 330 * @iter: Interation info, containing iter->cur_label 331 * @devp: New bootdev found, if any was found 332 * @method_flagsp: If non-NULL, returns any flags implied by the label 333 * (enum bootflow_meth_flags_t), 0 if none 334 * Returns 0 if OK, -ENODEV if no bootdev was found 335 */ 336int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp, 337 int *method_flagsp); 338 339/** 340 * bootdev_next_prio() - Find the next bootdev in priority order 341 * 342 * This moves @devp to the next bootdev with the current priority. If there is 343 * none, then it moves to the next priority and scans for new bootdevs there. 344 * 345 * @iter: Interation info, containing iter->cur_prio 346 * @devp: On entry this is the previous bootdev that was considered. On exit 347 * this is the new bootdev, if any was found 348 * Returns 0 on success (*devp is updated), -ENODEV if there are no more 349 * bootdevs at any priority 350 */ 351int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp); 352 353#if CONFIG_IS_ENABLED(BOOTSTD) 354/** 355 * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated) 356 * 357 * Please use bootdev_setup_for_sibling_blk() instead since it supports multiple 358 * (child) block devices for each media device. 359 * 360 * Creates a bootdev device as a child of @parent. This should be called from 361 * the driver's bind() method or its uclass' post_bind() method. 362 * 363 * If a child bootdev already exists, this function does nothing 364 * 365 * @parent: Parent device (e.g. MMC or Ethernet) 366 * @drv_name: Name of bootdev driver to bind 367 * Return: 0 if OK, -ve on error 368 */ 369int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name); 370 371#if CONFIG_IS_ENABLED(BOOTSTD) 372/** 373 * bootdev_setup_for_sibling_blk() - Bind a new bootdev device for a blk device 374 * 375 * Creates a bootdev device as a sibling of @blk. This should be called from 376 * the driver's bind() method or its uclass' post_bind() method, at the same 377 * time as the bould device is bound 378 * 379 * If a device of the same name already exists, this function does nothing 380 * 381 * @parent: Parent device (e.g. MMC or Ethernet) 382 * @drv_name: Name of bootdev driver to bind 383 * Return: 0 if OK, -ve on error 384 */ 385int bootdev_setup_for_sibling_blk(struct udevice *blk, const char *drv_name); 386#else 387static int bootdev_setup_for_sibling_blk(struct udevice *blk, 388 const char *drv_name) 389{ 390 return 0; 391} 392#endif 393 394/** 395 * bootdev_get_sibling_blk() - Locate the block device for a bootdev 396 * 397 * @dev: bootdev to check 398 * @blkp: returns associated block device 399 * Return: 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other 400 * error 401 */ 402int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp); 403 404/** 405 * bootdev_get_from_blk() - Get the bootdev given a block device 406 * 407 * @blk: Block device to check 408 * @bootdebp: Returns the bootdev found, if any 409 * Return 0 if OK, -ve on error 410 */ 411int bootdev_get_from_blk(struct udevice *blk, struct udevice **bootdevp); 412 413/** 414 * bootdev_unbind_dev() - Unbind a bootdev device 415 * 416 * Remove and unbind a bootdev device which is a child of @parent. This should 417 * be called from the driver's unbind() method or its uclass' post_bind() 418 * method. 419 * 420 * @parent: Parent device (e.g. MMC or Ethernet) 421 * Return: 0 if OK, -ve on error 422 */ 423int bootdev_unbind_dev(struct udevice *parent); 424#else 425static inline int bootdev_setup_for_dev(struct udevice *parent, 426 const char *drv_name) 427{ 428 return 0; 429} 430 431static inline int bootdev_setup_for_sibling_blk(struct udevice *blk, 432 const char *drv_name) 433{ 434 return 0; 435} 436 437static inline int bootdev_unbind_dev(struct udevice *parent) 438{ 439 return 0; 440} 441#endif 442 443#endif