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