]> Git Repo - J-u-boot.git/blob - include/bootdev.h
Merge patch series "Introduce basic support for TI's AM62Px SoC family"
[J-u-boot.git] / include / bootdev.h
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Copyright 2021 Google LLC
4  * Written by Simon Glass <[email protected]>
5  */
6
7 #ifndef __bootdev_h
8 #define __bootdev_h
9
10 #include <dm/uclass-id.h>
11 #include <linux/list.h>
12
13 struct bootflow;
14 struct bootflow_iter;
15 struct bootstd_priv;
16 struct 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  */
46 enum 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
59 struct 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  */
71 typedef 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  */
91 struct 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  * @bootflows: List of available bootflows for this bootdev
113  * @piro: Priority of this bootdev
114  */
115 struct bootdev_uc_plat {
116         struct list_head bootflow_head;
117         enum bootdev_prio_t prio;
118 };
119
120 /** struct bootdev_ops - Operations for the bootdev uclass */
121 struct bootdev_ops {
122         /**
123          * get_bootflow() - get a bootflow (optional)
124          *
125          * If this is NULL then the default implementaton is used, which is
126          * default_get_bootflow()
127          *
128          * @dev:        Bootflow device to check
129          * @iter:       Provides current dev, part, method to get. Should update
130          *      max_part if there is a partition table. Should update state,
131          *      subdir, fname, buf, size according to progress
132          * @bflow:      Updated bootflow if found
133          * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this
134          *      device, -ENOSYS if this device doesn't support bootflows,
135          *      other -ve value on other error
136          */
137         int (*get_bootflow)(struct udevice *dev, struct bootflow_iter *iter,
138                             struct bootflow *bflow);
139 };
140
141 #define bootdev_get_ops(dev)  ((struct bootdev_ops *)(dev)->driver->ops)
142
143 /**
144  * bootdev_get_bootflow() - get a bootflow
145  *
146  * @dev:        Bootflow device to check
147  * @iter:       Provides current  part, method to get
148  * @bflow:      Returns bootflow if found
149  * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this device,
150  *      -ENOSYS if this device doesn't support bootflows, other -ve value on
151  *      other error
152  */
153 int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
154                          struct bootflow *bflow);
155
156 /**
157  * bootdev_bind() - Bind a new named bootdev device
158  *
159  * @parent:     Parent of the new device
160  * @drv_name:   Driver name to use for the bootdev device
161  * @name:       Name for the device (parent name is prepended)
162  * @devp:       the new device (which has not been probed)
163  */
164 int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name,
165                  struct udevice **devp);
166
167 /**
168  * bootdev_find_in_blk() - Find a bootdev in a block device
169  *
170  * @dev: Bootflow device associated with this block device
171  * @blk: Block device to search
172  * @iter:       Provides current dev, part, method to get. Should update
173  *      max_part if there is a partition table
174  * @bflow: On entry, provides information about the partition and device to
175  *      check. On exit, returns bootflow if found
176  * Return: 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error
177  */
178 int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
179                         struct bootflow_iter *iter, struct bootflow *bflow);
180
181 /**
182  * bootdev_list() - List all available bootdevs
183  *
184  * @probe: true to probe devices, false to leave them as is
185  */
186 void bootdev_list(bool probe);
187
188 /**
189  * bootdev_clear_bootflows() - Clear bootflows from a bootdev
190  *
191  * Each bootdev maintains a list of discovered bootflows. This provides a
192  * way to clear it. These bootflows are removed from the global list too.
193  *
194  * @dev: bootdev device to update
195  */
196 void bootdev_clear_bootflows(struct udevice *dev);
197
198 /**
199  * bootdev_add_bootflow() - Add a bootflow to the bootdev's list
200  *
201  * All fields in @bflow must be set up. Note that @bflow->dev is used to add the
202  * bootflow to that device.
203  *
204  * @dev: Bootdev device to add to
205  * @bflow: Bootflow to add. Note that fields within bflow must be allocated
206  *      since this function takes over ownership of these. This functions makes
207  *      a copy of @bflow itself (without allocating its fields again), so the
208  *      caller must dispose of the memory used by the @bflow pointer itself
209  * Return: 0 if OK, -ENOMEM if out of memory
210  */
211 int bootdev_add_bootflow(struct bootflow *bflow);
212
213 /**
214  * bootdev_first_bootflow() - Get the first bootflow from a bootdev
215  *
216  * Returns the first bootflow attached to a bootdev
217  *
218  * @dev: bootdev device
219  * @bflowp: Returns a pointer to the bootflow
220  * Return: 0 if found, -ENOENT if there are no bootflows
221  */
222 int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp);
223
224 /**
225  * bootdev_next_bootflow() - Get the next bootflow from a bootdev
226  *
227  * Returns the next bootflow attached to a bootdev
228  *
229  * @bflowp: On entry, the last bootflow returned , e.g. from
230  *      bootdev_first_bootflow()
231  * Return: 0 if found, -ENOENT if there are no more bootflows
232  */
233 int bootdev_next_bootflow(struct bootflow **bflowp);
234
235 /**
236  * bootdev_find_by_label() - Look up a bootdev by label
237  *
238  * Each bootdev has a label which contains the media-uclass name and a number,
239  * e.g. 'mmc2'. This looks up the label and returns the associated bootdev
240  *
241  * The lookup is performed based on the media device's sequence number. So for
242  * 'mmc2' this looks for a device in UCLASS_MMC with a dev_seq() of 2.
243  *
244  * @label: Label to look up (e.g. "mmc1" or "mmc0")
245  * @devp: Returns the bootdev device found, or NULL if none (note it does not
246  *      return the media device, but its bootdev child)
247  * @method_flagsp: If non-NULL, returns any flags implied by the label
248  * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
249  * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
250  * -ENOENT if there is no device with that number
251  */
252 int bootdev_find_by_label(const char *label, struct udevice **devp,
253                           int *method_flagsp);
254
255 /**
256  * bootdev_find_by_any() - Find a bootdev by name, label or sequence
257  *
258  * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
259  * @devp: returns the device found, on success
260  * @method_flagsp: If non-NULL, returns any flags implied by the label
261  * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
262  * Return: 0 if OK, -EPFNOSUPPORT if the uclass is not supported by this board,
263  * -ENOENT if there is no device with that number
264  */
265 int bootdev_find_by_any(const char *name, struct udevice **devp,
266                         int *method_flagsp);
267
268 /**
269  * bootdev_setup_iter() - Set up iteration through bootdevs
270  *
271  * This sets up the an interation, based on the provided device or label. If
272  * neither is provided, the iteration is based on the priority of each bootdev,
273  * the * bootdev-order property in the bootstd node (or the boot_targets env
274  * var).
275  *
276  * @iter: Iterator to update with the order
277  * @label: label to scan, or NULL to scan all
278  * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single)
279  *      device to scan. Returns the first device to use, which is the passed-in
280  *      @devp if it was non-NULL
281  * @method_flagsp: If non-NULL, returns any flags implied by the label
282  * (enum bootflow_meth_flags_t), 0 if none
283  * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
284  *      on other error
285  */
286 int bootdev_setup_iter(struct bootflow_iter *iter, const char *label,
287                        struct udevice **devp, int *method_flagsp);
288
289 /**
290  * bootdev_list_hunters() - List the available bootdev hunters
291  *
292  * These provide a way to find new bootdevs by enumerating buses, etc. This
293  * function lists the available hunters
294  *
295  * @std: Pointer to bootstd private info
296  */
297 void bootdev_list_hunters(struct bootstd_priv *std);
298
299 /**
300  * bootdev_hunt() - Hunt for bootdevs matching a particular spec
301  *
302  * This runs the selected hunter (or all if @spec is NULL) to try to find new
303  * bootdevs.
304  *
305  * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must
306  * match a uclass name so that the hunter can be determined. Any trailing number
307  * is ignored
308  * @show: true to show each hunter before using it
309  * Returns: 0 if OK, -ve on error
310  */
311 int bootdev_hunt(const char *spec, bool show);
312
313 /**
314  * bootdev_hunt_prio() - Hunt for bootdevs of a particular priority
315  *
316  * This runs all hunters which can find bootdevs of the given priority.
317  *
318  * @prio: Priority to use
319  * @show: true to show each hunter as it is used
320  * Returns: 0 if OK, -ve on error
321  */
322 int bootdev_hunt_prio(enum bootdev_prio_t prio, bool show);
323
324 /**
325  * bootdev_unhunt() - Mark a device as needing to be hunted again
326  *
327  * @id: uclass ID to update
328  * Return: 0 if done, -EALREADY if already in this state, -ENOENT if no hunter
329  * found for that uclass
330  */
331 int bootdev_unhunt(enum uclass_id id);
332
333 /**
334  * bootdev_hunt_and_find_by_label() - Hunt for bootdevs by label
335  *
336  * Runs the hunter for the label, then tries to find the bootdev, possible
337  * created by the hunter
338  *
339  * @label: Label to look up (e.g. "mmc1" or "mmc0")
340  * @devp: Returns the bootdev device found, or NULL if none (note it does not
341  *      return the media device, but its bootdev child)
342  * @method_flagsp: If non-NULL, returns any flags implied by the label
343  * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
344  * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
345  * -ENOENT if there is no device with that number
346  */
347 int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp,
348                                    int *method_flagsp);
349
350 /**
351  * bootdev_next_label() - Move to the next bootdev in the label sequence
352  *
353  * Looks through the remaining labels until it finds one that matches a bootdev.
354  * Bootdev scanners are used as needed. For example a label "mmc1" results in
355  * running the "mmc" bootdrv.
356  *
357  * @iter: Interation info, containing iter->cur_label
358  * @devp: New bootdev found, if any was found
359  * @method_flagsp: If non-NULL, returns any flags implied by the label
360  * (enum bootflow_meth_flags_t), 0 if none
361  * Returns 0 if OK, -ENODEV if no bootdev was found
362  */
363 int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
364                        int *method_flagsp);
365
366 /**
367  * bootdev_next_prio() - Find the next bootdev in priority order
368  *
369  * This moves @devp to the next bootdev with the current priority. If there is
370  * none, then it moves to the next priority and scans for new bootdevs there.
371  *
372  * @iter: Interation info, containing iter->cur_prio
373  * @devp: On entry this is the previous bootdev that was considered. On exit
374  *      this is the new bootdev, if any was found
375  * Returns 0 on success (*devp is updated), -ENODEV if there are no more
376  * bootdevs at any priority
377  */
378 int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp);
379
380 #if CONFIG_IS_ENABLED(BOOTSTD)
381 /**
382  * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)
383  *
384  * Please use bootdev_setup_for_sibling_blk() instead since it supports multiple
385  * (child) block devices for each media device.
386  *
387  * Creates a bootdev device as a child of @parent. This should be called from
388  * the driver's bind() method or its uclass' post_bind() method.
389  *
390  * If a child bootdev already exists, this function does nothing
391  *
392  * @parent: Parent device (e.g. MMC or Ethernet)
393  * @drv_name: Name of bootdev driver to bind
394  * Return: 0 if OK, -ve on error
395  */
396 int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name);
397
398 /**
399  * bootdev_setup_for_sibling_blk() - Bind a new bootdev device for a blk device
400  *
401  * Creates a bootdev device as a sibling of @blk. This should be called from
402  * the driver's bind() method or its uclass' post_bind() method, at the same
403  * time as the bould device is bound
404  *
405  * If a device of the same name already exists, this function does nothing
406  *
407  * @parent: Parent device (e.g. MMC or Ethernet)
408  * @drv_name: Name of bootdev driver to bind
409  * Return: 0 if OK, -ve on error
410  */
411 int bootdev_setup_for_sibling_blk(struct udevice *blk, const char *drv_name);
412
413 /**
414  * bootdev_get_sibling_blk() - Locate the block device for a bootdev
415  *
416  * @dev: bootdev to check
417  * @blkp: returns associated block device
418  * Return: 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other
419  *      error
420  */
421 int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp);
422
423 /**
424  * bootdev_unbind_dev() - Unbind a bootdev device
425  *
426  * Remove and unbind a bootdev device which is a child of @parent. This should
427  * be called from the driver's unbind() method or its uclass' post_bind()
428  * method.
429  *
430  * @parent: Parent device (e.g. MMC or Ethernet)
431  * Return: 0 if OK, -ve on error
432  */
433 int bootdev_unbind_dev(struct udevice *parent);
434 #else
435 static inline int bootdev_setup_for_dev(struct udevice *parent,
436                                         const char *drv_name)
437 {
438         return 0;
439 }
440
441 static inline int bootdev_setup_for_sibling_blk(struct udevice *blk,
442                                                 const char *drv_name)
443 {
444         return 0;
445 }
446
447 static inline int bootdev_unbind_dev(struct udevice *parent)
448 {
449         return 0;
450 }
451 #endif
452
453 #endif
This page took 0.050105 seconds and 4 git commands to generate.