blob: deef7890489855797716c9b6f70f9852efed712e [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)
225 * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
226 * -ENOENT if there is no device with that number
227 */
228int bootdev_find_by_label(const char *label, struct udevice **devp);
229
230/**
231 * bootdev_find_by_any() - Find a bootdev by name, label or sequence
232 *
233 * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
234 * @devp: returns the device found, on success
235 * Return: 0 if OK, -ve on error
236 */
237int bootdev_find_by_any(const char *name, struct udevice **devp);
238
239/**
240 * bootdev_setup_iter_order() - Set up the ordering of bootdevs to scan
241 *
242 * This sets up the ordering information in @iter, based on the priority of each
243 * bootdev and the bootdev-order property in the bootstd node
244 *
245 * If a single device is requested, no ordering is needed
246 *
247 * @iter: Iterator to update with the order
248 * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single)
249 * device to scan. Returns the first device to use, which is the passed-in
250 * @devp if it was non-NULL
251 * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
252 * on other error
253 */
254int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp);
255
Simon Glass5acb97a2023-01-17 10:47:33 -0700256/**
257 * bootdev_list_hunters() - List the available bootdev hunters
258 *
259 * These provide a way to find new bootdevs by enumerating buses, etc. This
260 * function lists the available hunters
261 *
262 * @std: Pointer to bootstd private info
263 */
264void bootdev_list_hunters(struct bootstd_priv *std);
265
Simon Glass1248d2b2023-01-17 10:47:34 -0700266/**
267 * bootdev_hunt() - Hunt for bootdevs matching a particular spec
268 *
269 * This runs the selected hunter (or all if @spec is NULL) to try to find new
270 * bootdevs.
271 *
272 * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must
273 * match a uclass name so that the hunter can be determined. Any trailing number
274 * is ignored
275 * @show: true to show each hunter before using it
276 * Returns: 0 if OK, -ve on error
277 */
278int bootdev_hunt(const char *spec, bool show);
279
Simon Glass017656e2022-04-24 23:31:07 -0600280#if CONFIG_IS_ENABLED(BOOTSTD)
281/**
Simon Glassb1dc36a2023-01-17 10:47:25 -0700282 * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)
283 *
284 * Please use bootdev_setup_sibling_blk() instead since it supports multiple
285 * (child) block devices for each media device.
Simon Glass017656e2022-04-24 23:31:07 -0600286 *
287 * Creates a bootdev device as a child of @parent. This should be called from
288 * the driver's bind() method or its uclass' post_bind() method.
289 *
290 * If a child bootdev already exists, this function does nothing
291 *
292 * @parent: Parent device (e.g. MMC or Ethernet)
293 * @drv_name: Name of bootdev driver to bind
294 * Return: 0 if OK, -ve on error
295 */
296int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name);
297
298/**
299 * bootdev_setup_for_blk() - Bind a new bootdev device for a blk device
300 *
301 * Creates a bootdev device as a sibling of @blk. This should be called from
302 * the driver's bind() method or its uclass' post_bind() method, at the same
303 * time as the bould device is bound
304 *
305 * If a device of the same name already exists, this function does nothing
306 *
307 * @parent: Parent device (e.g. MMC or Ethernet)
308 * @drv_name: Name of bootdev driver to bind
309 * Return: 0 if OK, -ve on error
310 */
311int bootdev_setup_sibling_blk(struct udevice *blk, const char *drv_name);
312
313/**
314 * bootdev_get_sibling_blk() - Locate the block device for a bootdev
315 *
316 * @dev: bootdev to check
317 * @blkp: returns associated block device
318 * Return: 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other
319 * error
320 */
321int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp);
322
323/**
324 * bootdev_unbind_dev() - Unbind a bootdev device
325 *
326 * Remove and unbind a bootdev device which is a child of @parent. This should
327 * be called from the driver's unbind() method or its uclass' post_bind()
328 * method.
329 *
330 * @parent: Parent device (e.g. MMC or Ethernet)
331 * Return: 0 if OK, -ve on error
332 */
333int bootdev_unbind_dev(struct udevice *parent);
334#else
335static inline int bootdev_setup_for_dev(struct udevice *parent,
336 const char *drv_name)
337{
338 return 0;
339}
340
341static inline int bootdev_setup_sibling_blk(struct udevice *blk,
342 const char *drv_name)
343{
344 return 0;
345}
346
347static inline int bootdev_unbind_dev(struct udevice *parent)
348{
349 return 0;
350}
351#endif
352
353#endif