blob: db03c5c032e0b954d61e43069df6a9a4c32536d5 [file] [log] [blame]
Simon Glass017656e2022-04-24 23:31:07 -06001/* 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
12struct bootflow;
13struct bootflow_iter;
Simon Glass5acb97a2023-01-17 10:47:33 -070014struct bootstd_priv;
Simon Glass017656e2022-04-24 23:31:07 -060015struct 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 */
25enum bootdev_prio_t {
26 BOOTDEVP_0_INTERNAL_FAST = 10,
27 BOOTDEVP_1_INTERNAL_SLOW = 20,
28 BOOTDEVP_2_SCAN_FAST = 30,
29 BOOTDEVP_3_SCAN_SLOW = 40,
30 BOOTDEVP_4_NET_BASE = 50,
31 BOOTDEVP_5_NET_FALLBACK = 60,
32 BOOTDEVP_6_SYSTEM = 70,
33
34 BOOTDEVP_COUNT,
35};
36
Simon Glass5acb97a2023-01-17 10:47:33 -070037struct bootdev_hunter;
38
39/**
40 * bootdev_hunter_func - function to probe for bootdevs of a given type
41 *
42 * This should hunt around for bootdevs of the given type, binding them as it
43 * finds them. This may involve bus enumeration, etc.
44 *
45 * @info: Info structure describing this hunter
46 * @show: true to show information from the hunter
47 * Returns: 0 if OK, -ve on error
48 */
49typedef int (*bootdev_hunter_func)(struct bootdev_hunter *info, bool show);
50
51/**
52 * struct bootdev_hunter - information about how to hunt for bootdevs
53 *
54 * @prio: Scanning priority of this hunter
55 * @uclass: Uclass ID for the media associated with this bootdev
56 * @drv: bootdev driver for the things found by this hunter
57 * @hunt: Function to call to hunt for bootdevs of this type (NULL if none)
58 *
59 * Some bootdevs are not visible until other devices are enumerated. For
60 * example, USB bootdevs only appear when the USB bus is enumerated.
61 *
62 * On the other hand, we don't always want to enumerate all the buses just to
63 * find the first valid bootdev. Ideally we want to work through them in
64 * priority order, so that the fastest bootdevs are discovered first.
65 *
66 * This struct holds information about the bootdev so we can determine the probe
67 * order and how to hunt for bootdevs of this type
68 */
69struct bootdev_hunter {
70 enum bootdev_prio_t prio;
71 enum uclass_id uclass;
72 struct driver *drv;
73 bootdev_hunter_func hunt;
74};
75
76/* declare a new bootdev hunter */
77#define BOOTDEV_HUNTER(__name) \
78 ll_entry_declare(struct bootdev_hunter, __name, bootdev_hunter)
79
80/* access a bootdev hunter by name */
81#define BOOTDEV_HUNTER_GET(__name) \
82 ll_entry_get(struct bootdev_hunter, __name, bootdev_hunter)
83
Simon Glass017656e2022-04-24 23:31:07 -060084/**
85 * struct bootdev_uc_plat - uclass information about a bootdev
86 *
87 * This is attached to each device in the bootdev uclass and accessible via
88 * dev_get_uclass_plat(dev)
89 *
90 * @bootflows: List of available bootflows for this bootdev
91 * @piro: Priority of this bootdev
92 */
93struct bootdev_uc_plat {
94 struct list_head bootflow_head;
95 enum bootdev_prio_t prio;
96};
97
98/** struct bootdev_ops - Operations for the bootdev uclass */
99struct bootdev_ops {
100 /**
Simon Glassd6e39d12023-01-17 10:47:26 -0700101 * get_bootflow() - get a bootflow (optional)
102 *
103 * If this is NULL then the default implementaton is used, which is
104 * default_get_bootflow()
Simon Glass017656e2022-04-24 23:31:07 -0600105 *
106 * @dev: Bootflow device to check
107 * @iter: Provides current dev, part, method to get. Should update
108 * max_part if there is a partition table. Should update state,
109 * subdir, fname, buf, size according to progress
110 * @bflow: Updated bootflow if found
111 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this
112 * device, -ENOSYS if this device doesn't support bootflows,
113 * other -ve value on other error
114 */
115 int (*get_bootflow)(struct udevice *dev, struct bootflow_iter *iter,
116 struct bootflow *bflow);
117};
118
119#define bootdev_get_ops(dev) ((struct bootdev_ops *)(dev)->driver->ops)
120
121/**
122 * bootdev_get_bootflow() - get a bootflow
123 *
124 * @dev: Bootflow device to check
125 * @iter: Provides current part, method to get
126 * @bflow: Returns bootflow if found
127 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this device,
128 * -ENOSYS if this device doesn't support bootflows, other -ve value on
129 * other error
130 */
131int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
132 struct bootflow *bflow);
133
134/**
135 * bootdev_bind() - Bind a new named bootdev device
136 *
137 * @parent: Parent of the new device
138 * @drv_name: Driver name to use for the bootdev device
139 * @name: Name for the device (parent name is prepended)
140 * @devp: the new device (which has not been probed)
141 */
142int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name,
143 struct udevice **devp);
144
145/**
146 * bootdev_find_in_blk() - Find a bootdev in a block device
147 *
148 * @dev: Bootflow device associated with this block device
149 * @blk: Block device to search
150 * @iter: Provides current dev, part, method to get. Should update
151 * max_part if there is a partition table
152 * @bflow: On entry, provides information about the partition and device to
153 * check. On exit, returns bootflow if found
154 * Return: 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error
155 */
156int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
157 struct bootflow_iter *iter, struct bootflow *bflow);
158
159/**
160 * bootdev_list() - List all available bootdevs
161 *
162 * @probe: true to probe devices, false to leave them as is
163 */
164void bootdev_list(bool probe);
165
166/**
167 * bootdev_clear_bootflows() - Clear bootflows from a bootdev
168 *
169 * Each bootdev maintains a list of discovered bootflows. This provides a
170 * way to clear it. These bootflows are removed from the global list too.
171 *
172 * @dev: bootdev device to update
173 */
174void bootdev_clear_bootflows(struct udevice *dev);
175
176/**
177 * bootdev_add_bootflow() - Add a bootflow to the bootdev's list
178 *
179 * All fields in @bflow must be set up. Note that @bflow->dev is used to add the
180 * bootflow to that device.
181 *
182 * @dev: Bootdevice device to add to
183 * @bflow: Bootflow to add. Note that fields within bflow must be allocated
184 * since this function takes over ownership of these. This functions makes
185 * a copy of @bflow itself (without allocating its fields again), so the
186 * caller must dispose of the memory used by the @bflow pointer itself
187 * Return: 0 if OK, -ENOMEM if out of memory
188 */
189int bootdev_add_bootflow(struct bootflow *bflow);
190
191/**
192 * bootdev_first_bootflow() - Get the first bootflow from a bootdev
193 *
194 * Returns the first bootflow attached to a bootdev
195 *
196 * @dev: bootdev device
197 * @bflowp: Returns a pointer to the bootflow
198 * Return: 0 if found, -ENOENT if there are no bootflows
199 */
200int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp);
201
202/**
203 * bootdev_next_bootflow() - Get the next bootflow from a bootdev
204 *
205 * Returns the next bootflow attached to a bootdev
206 *
207 * @bflowp: On entry, the last bootflow returned , e.g. from
208 * bootdev_first_bootflow()
209 * Return: 0 if found, -ENOENT if there are no more bootflows
210 */
211int bootdev_next_bootflow(struct bootflow **bflowp);
212
213/**
214 * bootdev_find_by_label() - Look up a bootdev by label
215 *
216 * Each bootdev has a label which contains the media-uclass name and a number,
217 * e.g. 'mmc2'. This looks up the label and returns the associated bootdev
218 *
219 * The lookup is performed based on the media device's sequence number. So for
220 * 'mmc2' this looks for a device in UCLASS_MMC with a dev_seq() of 2.
221 *
222 * @label: Label to look up (e.g. "mmc1" or "mmc0")
223 * @devp: Returns the bootdev device found, or NULL if none (note it does not
224 * return the media device, but its bootdev child)
Simon Glasse22fe922023-01-17 10:48:05 -0700225 * @method_flagsp: If non-NULL, returns any flags implied by the label
226 * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
Simon Glass017656e2022-04-24 23:31:07 -0600227 * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
Simon Glasse22fe922023-01-17 10:48:05 -0700228 * -ENOENT if there is no device with that number
Simon Glass017656e2022-04-24 23:31:07 -0600229 */
Simon Glasse22fe922023-01-17 10:48:05 -0700230int bootdev_find_by_label(const char *label, struct udevice **devp,
231 int *method_flagsp);
Simon Glass017656e2022-04-24 23:31:07 -0600232
233/**
234 * bootdev_find_by_any() - Find a bootdev by name, label or sequence
235 *
236 * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
237 * @devp: returns the device found, on success
Simon Glasse22fe922023-01-17 10:48:05 -0700238 * @method_flagsp: If non-NULL, returns any flags implied by the label
239 * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
240 * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
241 * -ENOENT if there is no device with that number
Simon Glass017656e2022-04-24 23:31:07 -0600242 */
Simon Glasse22fe922023-01-17 10:48:05 -0700243int bootdev_find_by_any(const char *name, struct udevice **devp,
244 int *method_flagsp);
Simon Glass017656e2022-04-24 23:31:07 -0600245
246/**
247 * bootdev_setup_iter_order() - Set up the ordering of bootdevs to scan
248 *
249 * This sets up the ordering information in @iter, based on the priority of each
250 * bootdev and the bootdev-order property in the bootstd node
251 *
252 * If a single device is requested, no ordering is needed
253 *
254 * @iter: Iterator to update with the order
255 * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single)
256 * device to scan. Returns the first device to use, which is the passed-in
257 * @devp if it was non-NULL
258 * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
259 * on other error
260 */
261int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp);
262
Simon Glass5acb97a2023-01-17 10:47:33 -0700263/**
264 * bootdev_list_hunters() - List the available bootdev hunters
265 *
266 * These provide a way to find new bootdevs by enumerating buses, etc. This
267 * function lists the available hunters
268 *
269 * @std: Pointer to bootstd private info
270 */
271void bootdev_list_hunters(struct bootstd_priv *std);
272
Simon Glass1248d2b2023-01-17 10:47:34 -0700273/**
274 * bootdev_hunt() - Hunt for bootdevs matching a particular spec
275 *
276 * This runs the selected hunter (or all if @spec is NULL) to try to find new
277 * bootdevs.
278 *
279 * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must
280 * match a uclass name so that the hunter can be determined. Any trailing number
281 * is ignored
282 * @show: true to show each hunter before using it
283 * Returns: 0 if OK, -ve on error
284 */
285int bootdev_hunt(const char *spec, bool show);
286
Simon Glass017656e2022-04-24 23:31:07 -0600287#if CONFIG_IS_ENABLED(BOOTSTD)
288/**
Simon Glassb1dc36a2023-01-17 10:47:25 -0700289 * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)
290 *
291 * Please use bootdev_setup_sibling_blk() instead since it supports multiple
292 * (child) block devices for each media device.
Simon Glass017656e2022-04-24 23:31:07 -0600293 *
294 * Creates a bootdev device as a child of @parent. This should be called from
295 * the driver's bind() method or its uclass' post_bind() method.
296 *
297 * If a child bootdev already exists, this function does nothing
298 *
299 * @parent: Parent device (e.g. MMC or Ethernet)
300 * @drv_name: Name of bootdev driver to bind
301 * Return: 0 if OK, -ve on error
302 */
303int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name);
304
305/**
306 * bootdev_setup_for_blk() - Bind a new bootdev device for a blk device
307 *
308 * Creates a bootdev device as a sibling of @blk. This should be called from
309 * the driver's bind() method or its uclass' post_bind() method, at the same
310 * time as the bould device is bound
311 *
312 * If a device of the same name already exists, this function does nothing
313 *
314 * @parent: Parent device (e.g. MMC or Ethernet)
315 * @drv_name: Name of bootdev driver to bind
316 * Return: 0 if OK, -ve on error
317 */
318int bootdev_setup_sibling_blk(struct udevice *blk, const char *drv_name);
319
320/**
321 * bootdev_get_sibling_blk() - Locate the block device for a bootdev
322 *
323 * @dev: bootdev to check
324 * @blkp: returns associated block device
325 * Return: 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other
326 * error
327 */
328int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp);
329
330/**
331 * bootdev_unbind_dev() - Unbind a bootdev device
332 *
333 * Remove and unbind a bootdev device which is a child of @parent. This should
334 * be called from the driver's unbind() method or its uclass' post_bind()
335 * method.
336 *
337 * @parent: Parent device (e.g. MMC or Ethernet)
338 * Return: 0 if OK, -ve on error
339 */
340int bootdev_unbind_dev(struct udevice *parent);
341#else
342static inline int bootdev_setup_for_dev(struct udevice *parent,
343 const char *drv_name)
344{
345 return 0;
346}
347
348static inline int bootdev_setup_sibling_blk(struct udevice *blk,
349 const char *drv_name)
350{
351 return 0;
352}
353
354static inline int bootdev_unbind_dev(struct udevice *parent)
355{
356 return 0;
357}
358#endif
359
360#endif