blob: fe1aae35e5bb0d5f03f5d77f8974bcaf3cb36a2f [file] [log] [blame]
Furquan Shaikh69395742020-05-15 15:43:15 -07001/* SPDX-License-Identifier: GPL-2.0-only */
2
Furquan Shaikh69395742020-05-15 15:43:15 -07003#include <device/device.h>
Elyes Haouas04c3b5a2022-10-07 10:08:05 +02004#include <stddef.h>
Furquan Shaikh69395742020-05-15 15:43:15 -07005
6struct pick_largest_state {
7 struct resource *last;
8 const struct device *result_dev;
9 struct resource *result;
10 int seen_last;
11};
12
13static void pick_largest_resource(void *gp, struct device *dev,
14 struct resource *resource)
15{
16 struct pick_largest_state *state = gp;
17 struct resource *last;
18
19 last = state->last;
20
21 /* Be certain to pick the successor to last. */
22 if (resource == last) {
23 state->seen_last = 1;
24 return;
25 }
26 if (resource->flags & IORESOURCE_FIXED)
27 return; /* Skip it. */
28 if (last && ((last->align < resource->align) ||
29 ((last->align == resource->align) &&
30 (last->size < resource->size)) ||
31 ((last->align == resource->align) &&
32 (last->size == resource->size) && (!state->seen_last)))) {
33 return;
34 }
35 if (!state->result ||
36 (state->result->align < resource->align) ||
37 ((state->result->align == resource->align) &&
38 (state->result->size < resource->size))) {
39 state->result_dev = dev;
40 state->result = resource;
41 }
42}
43
44const struct device *largest_resource(struct bus *bus,
45 struct resource **result_res,
46 unsigned long type_mask,
47 unsigned long type)
48{
49 struct pick_largest_state state;
50
51 state.last = *result_res;
52 state.result_dev = NULL;
53 state.result = NULL;
54 state.seen_last = 0;
55
56 search_bus_resources(bus, type_mask, type, pick_largest_resource,
57 &state);
58
59 *result_res = state.result;
60 return state.result_dev;
61}