1 /* SPDX-License-Identifier: GPL-2.0+ */
3 * Copyright 2021 Google LLC
4 * Written by Simon Glass <sjg@chromium.org>
10 #include <linux/list.h>
17 * enum bootdev_prio_t - priority of each bootdev
19 * These values are associated with each bootdev and set up by the driver.
21 * Smallest value is the highest priority. By default, bootdevs are scanned from
22 * highest to lowest priority
25 BOOTDEVP_0_INTERNAL_FAST = 10,
26 BOOTDEVP_1_INTERNAL_SLOW = 20,
27 BOOTDEVP_2_SCAN_FAST = 30,
28 BOOTDEVP_3_SCAN_SLOW = 40,
29 BOOTDEVP_4_NET_BASE = 50,
30 BOOTDEVP_5_NET_FALLBACK = 60,
31 BOOTDEVP_6_SYSTEM = 70,
37 * struct bootdev_uc_plat - uclass information about a bootdev
39 * This is attached to each device in the bootdev uclass and accessible via
40 * dev_get_uclass_plat(dev)
42 * @bootflows: List of available bootflows for this bootdev
43 * @piro: Priority of this bootdev
45 struct bootdev_uc_plat {
46 struct list_head bootflow_head;
47 enum bootdev_prio_t prio;
50 /** struct bootdev_ops - Operations for the bootdev uclass */
53 * get_bootflow() - get a bootflow
55 * @dev: Bootflow device to check
56 * @iter: Provides current dev, part, method to get. Should update
57 * max_part if there is a partition table. Should update state,
58 * subdir, fname, buf, size according to progress
59 * @bflow: Updated bootflow if found
60 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this
61 * device, -ENOSYS if this device doesn't support bootflows,
62 * other -ve value on other error
64 int (*get_bootflow)(struct udevice *dev, struct bootflow_iter *iter,
65 struct bootflow *bflow);
68 #define bootdev_get_ops(dev) ((struct bootdev_ops *)(dev)->driver->ops)
71 * bootdev_get_bootflow() - get a bootflow
73 * @dev: Bootflow device to check
74 * @iter: Provides current part, method to get
75 * @bflow: Returns bootflow if found
76 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this device,
77 * -ENOSYS if this device doesn't support bootflows, other -ve value on
80 int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
81 struct bootflow *bflow);
84 * bootdev_bind() - Bind a new named bootdev device
86 * @parent: Parent of the new device
87 * @drv_name: Driver name to use for the bootdev device
88 * @name: Name for the device (parent name is prepended)
89 * @devp: the new device (which has not been probed)
91 int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name,
92 struct udevice **devp);
95 * bootdev_find_in_blk() - Find a bootdev in a block device
97 * @dev: Bootflow device associated with this block device
98 * @blk: Block device to search
99 * @iter: Provides current dev, part, method to get. Should update
100 * max_part if there is a partition table
101 * @bflow: On entry, provides information about the partition and device to
102 * check. On exit, returns bootflow if found
103 * Return: 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error
105 int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
106 struct bootflow_iter *iter, struct bootflow *bflow);
109 * bootdev_list() - List all available bootdevs
111 * @probe: true to probe devices, false to leave them as is
113 void bootdev_list(bool probe);
116 * bootdev_clear_bootflows() - Clear bootflows from a bootdev
118 * Each bootdev maintains a list of discovered bootflows. This provides a
119 * way to clear it. These bootflows are removed from the global list too.
121 * @dev: bootdev device to update
123 void bootdev_clear_bootflows(struct udevice *dev);
126 * bootdev_add_bootflow() - Add a bootflow to the bootdev's list
128 * All fields in @bflow must be set up. Note that @bflow->dev is used to add the
129 * bootflow to that device.
131 * @dev: Bootdevice device to add to
132 * @bflow: Bootflow to add. Note that fields within bflow must be allocated
133 * since this function takes over ownership of these. This functions makes
134 * a copy of @bflow itself (without allocating its fields again), so the
135 * caller must dispose of the memory used by the @bflow pointer itself
136 * Return: 0 if OK, -ENOMEM if out of memory
138 int bootdev_add_bootflow(struct bootflow *bflow);
141 * bootdev_first_bootflow() - Get the first bootflow from a bootdev
143 * Returns the first bootflow attached to a bootdev
145 * @dev: bootdev device
146 * @bflowp: Returns a pointer to the bootflow
147 * Return: 0 if found, -ENOENT if there are no bootflows
149 int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp);
152 * bootdev_next_bootflow() - Get the next bootflow from a bootdev
154 * Returns the next bootflow attached to a bootdev
156 * @bflowp: On entry, the last bootflow returned , e.g. from
157 * bootdev_first_bootflow()
158 * Return: 0 if found, -ENOENT if there are no more bootflows
160 int bootdev_next_bootflow(struct bootflow **bflowp);
163 * bootdev_find_by_label() - Look up a bootdev by label
165 * Each bootdev has a label which contains the media-uclass name and a number,
166 * e.g. 'mmc2'. This looks up the label and returns the associated bootdev
168 * The lookup is performed based on the media device's sequence number. So for
169 * 'mmc2' this looks for a device in UCLASS_MMC with a dev_seq() of 2.
171 * @label: Label to look up (e.g. "mmc1" or "mmc0")
172 * @devp: Returns the bootdev device found, or NULL if none (note it does not
173 * return the media device, but its bootdev child)
174 * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
175 * -ENOENT if there is no device with that number
177 int bootdev_find_by_label(const char *label, struct udevice **devp);
180 * bootdev_find_by_any() - Find a bootdev by name, label or sequence
182 * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
183 * @devp: returns the device found, on success
184 * Return: 0 if OK, -ve on error
186 int bootdev_find_by_any(const char *name, struct udevice **devp);
189 * bootdev_setup_iter_order() - Set up the ordering of bootdevs to scan
191 * This sets up the ordering information in @iter, based on the priority of each
192 * bootdev and the bootdev-order property in the bootstd node
194 * If a single device is requested, no ordering is needed
196 * @iter: Iterator to update with the order
197 * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single)
198 * device to scan. Returns the first device to use, which is the passed-in
199 * @devp if it was non-NULL
200 * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
203 int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp);
205 #if CONFIG_IS_ENABLED(BOOTSTD)
207 * bootdev_setup_for_dev() - Bind a new bootdev device
209 * Creates a bootdev device as a child of @parent. This should be called from
210 * the driver's bind() method or its uclass' post_bind() method.
212 * If a child bootdev already exists, this function does nothing
214 * @parent: Parent device (e.g. MMC or Ethernet)
215 * @drv_name: Name of bootdev driver to bind
216 * Return: 0 if OK, -ve on error
218 int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name);
221 * bootdev_setup_for_blk() - Bind a new bootdev device for a blk device
223 * Creates a bootdev device as a sibling of @blk. This should be called from
224 * the driver's bind() method or its uclass' post_bind() method, at the same
225 * time as the bould device is bound
227 * If a device of the same name already exists, this function does nothing
229 * @parent: Parent device (e.g. MMC or Ethernet)
230 * @drv_name: Name of bootdev driver to bind
231 * Return: 0 if OK, -ve on error
233 int bootdev_setup_sibling_blk(struct udevice *blk, const char *drv_name);
236 * bootdev_get_sibling_blk() - Locate the block device for a bootdev
238 * @dev: bootdev to check
239 * @blkp: returns associated block device
240 * Return: 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other
243 int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp);
246 * bootdev_unbind_dev() - Unbind a bootdev device
248 * Remove and unbind a bootdev device which is a child of @parent. This should
249 * be called from the driver's unbind() method or its uclass' post_bind()
252 * @parent: Parent device (e.g. MMC or Ethernet)
253 * Return: 0 if OK, -ve on error
255 int bootdev_unbind_dev(struct udevice *parent);
257 static inline int bootdev_setup_for_dev(struct udevice *parent,
258 const char *drv_name)
263 static inline int bootdev_setup_sibling_blk(struct udevice *blk,
264 const char *drv_name)
269 static inline int bootdev_unbind_dev(struct udevice *parent)