blob: 1cb189592ea07f38a7354e23d977ca9c5a34a2c9 [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>
4
5struct pick_largest_state {
6 struct resource *last;
7 const struct device *result_dev;
8 struct resource *result;
9 int seen_last;
10};
11
12static void pick_largest_resource(void *gp, struct device *dev,
13 struct resource *resource)
14{
15 struct pick_largest_state *state = gp;
16 struct resource *last;
17
18 last = state->last;
19
20 /* Be certain to pick the successor to last. */
21 if (resource == last) {
22 state->seen_last = 1;
23 return;
24 }
25 if (resource->flags & IORESOURCE_FIXED)
26 return; /* Skip it. */
27 if (last && ((last->align < resource->align) ||
28 ((last->align == resource->align) &&
29 (last->size < resource->size)) ||
30 ((last->align == resource->align) &&
31 (last->size == resource->size) && (!state->seen_last)))) {
32 return;
33 }
34 if (!state->result ||
35 (state->result->align < resource->align) ||
36 ((state->result->align == resource->align) &&
37 (state->result->size < resource->size))) {
38 state->result_dev = dev;
39 state->result = resource;
40 }
41}
42
43const struct device *largest_resource(struct bus *bus,
44 struct resource **result_res,
45 unsigned long type_mask,
46 unsigned long type)
47{
48 struct pick_largest_state state;
49
50 state.last = *result_res;
51 state.result_dev = NULL;
52 state.result = NULL;
53 state.seen_last = 0;
54
55 search_bus_resources(bus, type_mask, type, pick_largest_resource,
56 &state);
57
58 *result_res = state.result;
59 return state.result_dev;
60}