162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * drivers/acpi/resource.c - ACPI device resources interpretation.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2012, Intel Corp.
662306a36Sopenharmony_ci * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/acpi.h>
1462306a36Sopenharmony_ci#include <linux/device.h>
1562306a36Sopenharmony_ci#include <linux/export.h>
1662306a36Sopenharmony_ci#include <linux/ioport.h>
1762306a36Sopenharmony_ci#include <linux/slab.h>
1862306a36Sopenharmony_ci#include <linux/irq.h>
1962306a36Sopenharmony_ci#include <linux/dmi.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#ifdef CONFIG_X86
2262306a36Sopenharmony_ci#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
2362306a36Sopenharmony_cistatic inline bool acpi_iospace_resource_valid(struct resource *res)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	/* On X86 IO space is limited to the [0 - 64K] IO port range */
2662306a36Sopenharmony_ci	return res->end < 0x10003;
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci#else
2962306a36Sopenharmony_ci#define valid_IRQ(i) (true)
3062306a36Sopenharmony_ci/*
3162306a36Sopenharmony_ci * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical
3262306a36Sopenharmony_ci * addresses mapping IO space in CPU physical address space, IO space
3362306a36Sopenharmony_ci * resources can be placed anywhere in the 64-bit physical address space.
3462306a36Sopenharmony_ci */
3562306a36Sopenharmony_cistatic inline bool
3662306a36Sopenharmony_ciacpi_iospace_resource_valid(struct resource *res) { return true; }
3762306a36Sopenharmony_ci#endif
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)
4062306a36Sopenharmony_cistatic inline bool is_gsi(struct acpi_resource_extended_irq *ext_irq)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	return ext_irq->resource_source.string_length == 0 &&
4362306a36Sopenharmony_ci	       ext_irq->producer_consumer == ACPI_CONSUMER;
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci#else
4662306a36Sopenharmony_cistatic inline bool is_gsi(struct acpi_resource_extended_irq *ext_irq)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	return true;
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci#endif
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	u64 reslen = end - start + 1;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	/*
5762306a36Sopenharmony_ci	 * CHECKME: len might be required to check versus a minimum
5862306a36Sopenharmony_ci	 * length as well. 1 for io is fine, but for memory it does
5962306a36Sopenharmony_ci	 * not make any sense at all.
6062306a36Sopenharmony_ci	 * Note: some BIOSes report incorrect length for ACPI address space
6162306a36Sopenharmony_ci	 * descriptor, so remove check of 'reslen == len' to avoid regression.
6262306a36Sopenharmony_ci	 */
6362306a36Sopenharmony_ci	if (len && reslen && start <= end)
6462306a36Sopenharmony_ci		return true;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
6762306a36Sopenharmony_ci		io ? "io" : "mem", start, end, len);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	return false;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic void acpi_dev_memresource_flags(struct resource *res, u64 len,
7362306a36Sopenharmony_ci				       u8 write_protect)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	res->flags = IORESOURCE_MEM;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))
7862306a36Sopenharmony_ci		res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	if (write_protect == ACPI_READ_WRITE_MEMORY)
8162306a36Sopenharmony_ci		res->flags |= IORESOURCE_MEM_WRITEABLE;
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
8562306a36Sopenharmony_ci				     u8 write_protect)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	res->start = start;
8862306a36Sopenharmony_ci	res->end = start + len - 1;
8962306a36Sopenharmony_ci	acpi_dev_memresource_flags(res, len, write_protect);
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/**
9362306a36Sopenharmony_ci * acpi_dev_resource_memory - Extract ACPI memory resource information.
9462306a36Sopenharmony_ci * @ares: Input ACPI resource object.
9562306a36Sopenharmony_ci * @res: Output generic resource object.
9662306a36Sopenharmony_ci *
9762306a36Sopenharmony_ci * Check if the given ACPI resource object represents a memory resource and
9862306a36Sopenharmony_ci * if that's the case, use the information in it to populate the generic
9962306a36Sopenharmony_ci * resource object pointed to by @res.
10062306a36Sopenharmony_ci *
10162306a36Sopenharmony_ci * Return:
10262306a36Sopenharmony_ci * 1) false with res->flags setting to zero: not the expected resource type
10362306a36Sopenharmony_ci * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
10462306a36Sopenharmony_ci * 3) true: valid assigned resource
10562306a36Sopenharmony_ci */
10662306a36Sopenharmony_cibool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	struct acpi_resource_memory24 *memory24;
10962306a36Sopenharmony_ci	struct acpi_resource_memory32 *memory32;
11062306a36Sopenharmony_ci	struct acpi_resource_fixed_memory32 *fixed_memory32;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	switch (ares->type) {
11362306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_MEMORY24:
11462306a36Sopenharmony_ci		memory24 = &ares->data.memory24;
11562306a36Sopenharmony_ci		acpi_dev_get_memresource(res, memory24->minimum << 8,
11662306a36Sopenharmony_ci					 memory24->address_length << 8,
11762306a36Sopenharmony_ci					 memory24->write_protect);
11862306a36Sopenharmony_ci		break;
11962306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_MEMORY32:
12062306a36Sopenharmony_ci		memory32 = &ares->data.memory32;
12162306a36Sopenharmony_ci		acpi_dev_get_memresource(res, memory32->minimum,
12262306a36Sopenharmony_ci					 memory32->address_length,
12362306a36Sopenharmony_ci					 memory32->write_protect);
12462306a36Sopenharmony_ci		break;
12562306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
12662306a36Sopenharmony_ci		fixed_memory32 = &ares->data.fixed_memory32;
12762306a36Sopenharmony_ci		acpi_dev_get_memresource(res, fixed_memory32->address,
12862306a36Sopenharmony_ci					 fixed_memory32->address_length,
12962306a36Sopenharmony_ci					 fixed_memory32->write_protect);
13062306a36Sopenharmony_ci		break;
13162306a36Sopenharmony_ci	default:
13262306a36Sopenharmony_ci		res->flags = 0;
13362306a36Sopenharmony_ci		return false;
13462306a36Sopenharmony_ci	}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	return !(res->flags & IORESOURCE_DISABLED);
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic void acpi_dev_ioresource_flags(struct resource *res, u64 len,
14162306a36Sopenharmony_ci				      u8 io_decode, u8 translation_type)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	res->flags = IORESOURCE_IO;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
14662306a36Sopenharmony_ci		res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	if (!acpi_iospace_resource_valid(res))
14962306a36Sopenharmony_ci		res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	if (io_decode == ACPI_DECODE_16)
15262306a36Sopenharmony_ci		res->flags |= IORESOURCE_IO_16BIT_ADDR;
15362306a36Sopenharmony_ci	if (translation_type == ACPI_SPARSE_TRANSLATION)
15462306a36Sopenharmony_ci		res->flags |= IORESOURCE_IO_SPARSE;
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
15862306a36Sopenharmony_ci				    u8 io_decode)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	res->start = start;
16162306a36Sopenharmony_ci	res->end = start + len - 1;
16262306a36Sopenharmony_ci	acpi_dev_ioresource_flags(res, len, io_decode, 0);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/**
16662306a36Sopenharmony_ci * acpi_dev_resource_io - Extract ACPI I/O resource information.
16762306a36Sopenharmony_ci * @ares: Input ACPI resource object.
16862306a36Sopenharmony_ci * @res: Output generic resource object.
16962306a36Sopenharmony_ci *
17062306a36Sopenharmony_ci * Check if the given ACPI resource object represents an I/O resource and
17162306a36Sopenharmony_ci * if that's the case, use the information in it to populate the generic
17262306a36Sopenharmony_ci * resource object pointed to by @res.
17362306a36Sopenharmony_ci *
17462306a36Sopenharmony_ci * Return:
17562306a36Sopenharmony_ci * 1) false with res->flags setting to zero: not the expected resource type
17662306a36Sopenharmony_ci * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
17762306a36Sopenharmony_ci * 3) true: valid assigned resource
17862306a36Sopenharmony_ci */
17962306a36Sopenharmony_cibool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	struct acpi_resource_io *io;
18262306a36Sopenharmony_ci	struct acpi_resource_fixed_io *fixed_io;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	switch (ares->type) {
18562306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_IO:
18662306a36Sopenharmony_ci		io = &ares->data.io;
18762306a36Sopenharmony_ci		acpi_dev_get_ioresource(res, io->minimum,
18862306a36Sopenharmony_ci					io->address_length,
18962306a36Sopenharmony_ci					io->io_decode);
19062306a36Sopenharmony_ci		break;
19162306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_FIXED_IO:
19262306a36Sopenharmony_ci		fixed_io = &ares->data.fixed_io;
19362306a36Sopenharmony_ci		acpi_dev_get_ioresource(res, fixed_io->address,
19462306a36Sopenharmony_ci					fixed_io->address_length,
19562306a36Sopenharmony_ci					ACPI_DECODE_10);
19662306a36Sopenharmony_ci		break;
19762306a36Sopenharmony_ci	default:
19862306a36Sopenharmony_ci		res->flags = 0;
19962306a36Sopenharmony_ci		return false;
20062306a36Sopenharmony_ci	}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	return !(res->flags & IORESOURCE_DISABLED);
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_resource_io);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic bool acpi_decode_space(struct resource_win *win,
20762306a36Sopenharmony_ci			      struct acpi_resource_address *addr,
20862306a36Sopenharmony_ci			      struct acpi_address64_attribute *attr)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
21162306a36Sopenharmony_ci	bool wp = addr->info.mem.write_protect;
21262306a36Sopenharmony_ci	u64 len = attr->address_length;
21362306a36Sopenharmony_ci	u64 start, end, offset = 0;
21462306a36Sopenharmony_ci	struct resource *res = &win->res;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	/*
21762306a36Sopenharmony_ci	 * Filter out invalid descriptor according to ACPI Spec 5.0, section
21862306a36Sopenharmony_ci	 * 6.4.3.5 Address Space Resource Descriptors.
21962306a36Sopenharmony_ci	 */
22062306a36Sopenharmony_ci	if ((addr->min_address_fixed != addr->max_address_fixed && len) ||
22162306a36Sopenharmony_ci	    (addr->min_address_fixed && addr->max_address_fixed && !len))
22262306a36Sopenharmony_ci		pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",
22362306a36Sopenharmony_ci			 addr->min_address_fixed, addr->max_address_fixed, len);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	/*
22662306a36Sopenharmony_ci	 * For bridges that translate addresses across the bridge,
22762306a36Sopenharmony_ci	 * translation_offset is the offset that must be added to the
22862306a36Sopenharmony_ci	 * address on the secondary side to obtain the address on the
22962306a36Sopenharmony_ci	 * primary side. Non-bridge devices must list 0 for all Address
23062306a36Sopenharmony_ci	 * Translation offset bits.
23162306a36Sopenharmony_ci	 */
23262306a36Sopenharmony_ci	if (addr->producer_consumer == ACPI_PRODUCER)
23362306a36Sopenharmony_ci		offset = attr->translation_offset;
23462306a36Sopenharmony_ci	else if (attr->translation_offset)
23562306a36Sopenharmony_ci		pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
23662306a36Sopenharmony_ci			 attr->translation_offset);
23762306a36Sopenharmony_ci	start = attr->minimum + offset;
23862306a36Sopenharmony_ci	end = attr->maximum + offset;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	win->offset = offset;
24162306a36Sopenharmony_ci	res->start = start;
24262306a36Sopenharmony_ci	res->end = end;
24362306a36Sopenharmony_ci	if (sizeof(resource_size_t) < sizeof(u64) &&
24462306a36Sopenharmony_ci	    (offset != win->offset || start != res->start || end != res->end)) {
24562306a36Sopenharmony_ci		pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",
24662306a36Sopenharmony_ci			attr->minimum, attr->maximum);
24762306a36Sopenharmony_ci		return false;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	switch (addr->resource_type) {
25162306a36Sopenharmony_ci	case ACPI_MEMORY_RANGE:
25262306a36Sopenharmony_ci		acpi_dev_memresource_flags(res, len, wp);
25362306a36Sopenharmony_ci		break;
25462306a36Sopenharmony_ci	case ACPI_IO_RANGE:
25562306a36Sopenharmony_ci		acpi_dev_ioresource_flags(res, len, iodec,
25662306a36Sopenharmony_ci					  addr->info.io.translation_type);
25762306a36Sopenharmony_ci		break;
25862306a36Sopenharmony_ci	case ACPI_BUS_NUMBER_RANGE:
25962306a36Sopenharmony_ci		res->flags = IORESOURCE_BUS;
26062306a36Sopenharmony_ci		break;
26162306a36Sopenharmony_ci	default:
26262306a36Sopenharmony_ci		return false;
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	if (addr->producer_consumer == ACPI_PRODUCER)
26662306a36Sopenharmony_ci		res->flags |= IORESOURCE_WINDOW;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
26962306a36Sopenharmony_ci		res->flags |= IORESOURCE_PREFETCH;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	return !(res->flags & IORESOURCE_DISABLED);
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci/**
27562306a36Sopenharmony_ci * acpi_dev_resource_address_space - Extract ACPI address space information.
27662306a36Sopenharmony_ci * @ares: Input ACPI resource object.
27762306a36Sopenharmony_ci * @win: Output generic resource object.
27862306a36Sopenharmony_ci *
27962306a36Sopenharmony_ci * Check if the given ACPI resource object represents an address space resource
28062306a36Sopenharmony_ci * and if that's the case, use the information in it to populate the generic
28162306a36Sopenharmony_ci * resource object pointed to by @win.
28262306a36Sopenharmony_ci *
28362306a36Sopenharmony_ci * Return:
28462306a36Sopenharmony_ci * 1) false with win->res.flags setting to zero: not the expected resource type
28562306a36Sopenharmony_ci * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned
28662306a36Sopenharmony_ci *    resource
28762306a36Sopenharmony_ci * 3) true: valid assigned resource
28862306a36Sopenharmony_ci */
28962306a36Sopenharmony_cibool acpi_dev_resource_address_space(struct acpi_resource *ares,
29062306a36Sopenharmony_ci				     struct resource_win *win)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	struct acpi_resource_address64 addr;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	win->res.flags = 0;
29562306a36Sopenharmony_ci	if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))
29662306a36Sopenharmony_ci		return false;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	return acpi_decode_space(win, (struct acpi_resource_address *)&addr,
29962306a36Sopenharmony_ci				 &addr.address);
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci/**
30462306a36Sopenharmony_ci * acpi_dev_resource_ext_address_space - Extract ACPI address space information.
30562306a36Sopenharmony_ci * @ares: Input ACPI resource object.
30662306a36Sopenharmony_ci * @win: Output generic resource object.
30762306a36Sopenharmony_ci *
30862306a36Sopenharmony_ci * Check if the given ACPI resource object represents an extended address space
30962306a36Sopenharmony_ci * resource and if that's the case, use the information in it to populate the
31062306a36Sopenharmony_ci * generic resource object pointed to by @win.
31162306a36Sopenharmony_ci *
31262306a36Sopenharmony_ci * Return:
31362306a36Sopenharmony_ci * 1) false with win->res.flags setting to zero: not the expected resource type
31462306a36Sopenharmony_ci * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned
31562306a36Sopenharmony_ci *    resource
31662306a36Sopenharmony_ci * 3) true: valid assigned resource
31762306a36Sopenharmony_ci */
31862306a36Sopenharmony_cibool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
31962306a36Sopenharmony_ci					 struct resource_win *win)
32062306a36Sopenharmony_ci{
32162306a36Sopenharmony_ci	struct acpi_resource_extended_address64 *ext_addr;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	win->res.flags = 0;
32462306a36Sopenharmony_ci	if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
32562306a36Sopenharmony_ci		return false;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	ext_addr = &ares->data.ext_address64;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	return acpi_decode_space(win, (struct acpi_resource_address *)ext_addr,
33062306a36Sopenharmony_ci				 &ext_addr->address);
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci/**
33562306a36Sopenharmony_ci * acpi_dev_irq_flags - Determine IRQ resource flags.
33662306a36Sopenharmony_ci * @triggering: Triggering type as provided by ACPI.
33762306a36Sopenharmony_ci * @polarity: Interrupt polarity as provided by ACPI.
33862306a36Sopenharmony_ci * @shareable: Whether or not the interrupt is shareable.
33962306a36Sopenharmony_ci * @wake_capable: Wake capability as provided by ACPI.
34062306a36Sopenharmony_ci */
34162306a36Sopenharmony_ciunsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable, u8 wake_capable)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	unsigned long flags;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	if (triggering == ACPI_LEVEL_SENSITIVE)
34662306a36Sopenharmony_ci		flags = polarity == ACPI_ACTIVE_LOW ?
34762306a36Sopenharmony_ci			IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;
34862306a36Sopenharmony_ci	else
34962306a36Sopenharmony_ci		flags = polarity == ACPI_ACTIVE_LOW ?
35062306a36Sopenharmony_ci			IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (shareable == ACPI_SHARED)
35362306a36Sopenharmony_ci		flags |= IORESOURCE_IRQ_SHAREABLE;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	if (wake_capable == ACPI_WAKE_CAPABLE)
35662306a36Sopenharmony_ci		flags |= IORESOURCE_IRQ_WAKECAPABLE;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	return flags | IORESOURCE_IRQ;
35962306a36Sopenharmony_ci}
36062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci/**
36362306a36Sopenharmony_ci * acpi_dev_get_irq_type - Determine irq type.
36462306a36Sopenharmony_ci * @triggering: Triggering type as provided by ACPI.
36562306a36Sopenharmony_ci * @polarity: Interrupt polarity as provided by ACPI.
36662306a36Sopenharmony_ci */
36762306a36Sopenharmony_ciunsigned int acpi_dev_get_irq_type(int triggering, int polarity)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	switch (polarity) {
37062306a36Sopenharmony_ci	case ACPI_ACTIVE_LOW:
37162306a36Sopenharmony_ci		return triggering == ACPI_EDGE_SENSITIVE ?
37262306a36Sopenharmony_ci		       IRQ_TYPE_EDGE_FALLING :
37362306a36Sopenharmony_ci		       IRQ_TYPE_LEVEL_LOW;
37462306a36Sopenharmony_ci	case ACPI_ACTIVE_HIGH:
37562306a36Sopenharmony_ci		return triggering == ACPI_EDGE_SENSITIVE ?
37662306a36Sopenharmony_ci		       IRQ_TYPE_EDGE_RISING :
37762306a36Sopenharmony_ci		       IRQ_TYPE_LEVEL_HIGH;
37862306a36Sopenharmony_ci	case ACPI_ACTIVE_BOTH:
37962306a36Sopenharmony_ci		if (triggering == ACPI_EDGE_SENSITIVE)
38062306a36Sopenharmony_ci			return IRQ_TYPE_EDGE_BOTH;
38162306a36Sopenharmony_ci		fallthrough;
38262306a36Sopenharmony_ci	default:
38362306a36Sopenharmony_ci		return IRQ_TYPE_NONE;
38462306a36Sopenharmony_ci	}
38562306a36Sopenharmony_ci}
38662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_cistatic const struct dmi_system_id medion_laptop[] = {
38962306a36Sopenharmony_ci	{
39062306a36Sopenharmony_ci		.ident = "MEDION P15651",
39162306a36Sopenharmony_ci		.matches = {
39262306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
39362306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "M15T"),
39462306a36Sopenharmony_ci		},
39562306a36Sopenharmony_ci	},
39662306a36Sopenharmony_ci	{
39762306a36Sopenharmony_ci		.ident = "MEDION S17405",
39862306a36Sopenharmony_ci		.matches = {
39962306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
40062306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "M17T"),
40162306a36Sopenharmony_ci		},
40262306a36Sopenharmony_ci	},
40362306a36Sopenharmony_ci	{
40462306a36Sopenharmony_ci		.ident = "MEDION S17413",
40562306a36Sopenharmony_ci		.matches = {
40662306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
40762306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "M1xA"),
40862306a36Sopenharmony_ci		},
40962306a36Sopenharmony_ci	},
41062306a36Sopenharmony_ci	{ }
41162306a36Sopenharmony_ci};
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic const struct dmi_system_id asus_laptop[] = {
41462306a36Sopenharmony_ci	{
41562306a36Sopenharmony_ci		.ident = "Asus Vivobook K3402ZA",
41662306a36Sopenharmony_ci		.matches = {
41762306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
41862306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"),
41962306a36Sopenharmony_ci		},
42062306a36Sopenharmony_ci	},
42162306a36Sopenharmony_ci	{
42262306a36Sopenharmony_ci		.ident = "Asus Vivobook K3502ZA",
42362306a36Sopenharmony_ci		.matches = {
42462306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
42562306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"),
42662306a36Sopenharmony_ci		},
42762306a36Sopenharmony_ci	},
42862306a36Sopenharmony_ci	{
42962306a36Sopenharmony_ci		.ident = "Asus Vivobook S5402ZA",
43062306a36Sopenharmony_ci		.matches = {
43162306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
43262306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"),
43362306a36Sopenharmony_ci		},
43462306a36Sopenharmony_ci	},
43562306a36Sopenharmony_ci	{
43662306a36Sopenharmony_ci		.ident = "Asus Vivobook S5602ZA",
43762306a36Sopenharmony_ci		.matches = {
43862306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
43962306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"),
44062306a36Sopenharmony_ci		},
44162306a36Sopenharmony_ci	},
44262306a36Sopenharmony_ci	{
44362306a36Sopenharmony_ci		.ident = "Asus ExpertBook B1402CBA",
44462306a36Sopenharmony_ci		.matches = {
44562306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
44662306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"),
44762306a36Sopenharmony_ci		},
44862306a36Sopenharmony_ci	},
44962306a36Sopenharmony_ci	{
45062306a36Sopenharmony_ci		/* Asus ExpertBook B1402CVA */
45162306a36Sopenharmony_ci		.matches = {
45262306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
45362306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "B1402CVA"),
45462306a36Sopenharmony_ci		},
45562306a36Sopenharmony_ci	},
45662306a36Sopenharmony_ci	{
45762306a36Sopenharmony_ci		.ident = "Asus ExpertBook B1502CBA",
45862306a36Sopenharmony_ci		.matches = {
45962306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
46062306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "B1502CBA"),
46162306a36Sopenharmony_ci		},
46262306a36Sopenharmony_ci	},
46362306a36Sopenharmony_ci	{
46462306a36Sopenharmony_ci		.ident = "Asus ExpertBook B2402CBA",
46562306a36Sopenharmony_ci		.matches = {
46662306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
46762306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"),
46862306a36Sopenharmony_ci		},
46962306a36Sopenharmony_ci	},
47062306a36Sopenharmony_ci	{
47162306a36Sopenharmony_ci		.ident = "Asus ExpertBook B2402FBA",
47262306a36Sopenharmony_ci		.matches = {
47362306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
47462306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "B2402FBA"),
47562306a36Sopenharmony_ci		},
47662306a36Sopenharmony_ci	},
47762306a36Sopenharmony_ci	{
47862306a36Sopenharmony_ci		.ident = "Asus ExpertBook B2502",
47962306a36Sopenharmony_ci		.matches = {
48062306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
48162306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"),
48262306a36Sopenharmony_ci		},
48362306a36Sopenharmony_ci	},
48462306a36Sopenharmony_ci	{ }
48562306a36Sopenharmony_ci};
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic const struct dmi_system_id tongfang_gm_rg[] = {
48862306a36Sopenharmony_ci	{
48962306a36Sopenharmony_ci		.ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD",
49062306a36Sopenharmony_ci		.matches = {
49162306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
49262306a36Sopenharmony_ci		},
49362306a36Sopenharmony_ci	},
49462306a36Sopenharmony_ci	{ }
49562306a36Sopenharmony_ci};
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_cistatic const struct dmi_system_id maingear_laptop[] = {
49862306a36Sopenharmony_ci	{
49962306a36Sopenharmony_ci		.ident = "MAINGEAR Vector Pro 2 15",
50062306a36Sopenharmony_ci		.matches = {
50162306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
50262306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),
50362306a36Sopenharmony_ci		}
50462306a36Sopenharmony_ci	},
50562306a36Sopenharmony_ci	{
50662306a36Sopenharmony_ci		/* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */
50762306a36Sopenharmony_ci		.matches = {
50862306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
50962306a36Sopenharmony_ci		},
51062306a36Sopenharmony_ci	},
51162306a36Sopenharmony_ci	{
51262306a36Sopenharmony_ci		/* TongFang GMxXGxx sold as Eluktronics Inc. RP-15 */
51362306a36Sopenharmony_ci		.matches = {
51462306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Eluktronics Inc."),
51562306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "RP-15"),
51662306a36Sopenharmony_ci		},
51762306a36Sopenharmony_ci	},
51862306a36Sopenharmony_ci	{
51962306a36Sopenharmony_ci		/* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */
52062306a36Sopenharmony_ci		.matches = {
52162306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
52262306a36Sopenharmony_ci		},
52362306a36Sopenharmony_ci	},
52462306a36Sopenharmony_ci	{
52562306a36Sopenharmony_ci		.ident = "MAINGEAR Vector Pro 2 17",
52662306a36Sopenharmony_ci		.matches = {
52762306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
52862306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"),
52962306a36Sopenharmony_ci		},
53062306a36Sopenharmony_ci	},
53162306a36Sopenharmony_ci	{ }
53262306a36Sopenharmony_ci};
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_cistatic const struct dmi_system_id pcspecialist_laptop[] = {
53562306a36Sopenharmony_ci	{
53662306a36Sopenharmony_ci		/* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */
53762306a36Sopenharmony_ci		.matches = {
53862306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "GM6BGEQ"),
53962306a36Sopenharmony_ci		},
54062306a36Sopenharmony_ci	},
54162306a36Sopenharmony_ci	{
54262306a36Sopenharmony_ci		/* TongFang GM6BG5Q, RTX 4050 */
54362306a36Sopenharmony_ci		.matches = {
54462306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "GM6BG5Q"),
54562306a36Sopenharmony_ci		},
54662306a36Sopenharmony_ci	},
54762306a36Sopenharmony_ci	{
54862306a36Sopenharmony_ci		/* TongFang GM6BG0Q / PCSpecialist Elimina Pro 16 M, RTX 4060 */
54962306a36Sopenharmony_ci		.matches = {
55062306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "GM6BG0Q"),
55162306a36Sopenharmony_ci		},
55262306a36Sopenharmony_ci	},
55362306a36Sopenharmony_ci	{
55462306a36Sopenharmony_ci		/* Infinity E15-5A165-BM */
55562306a36Sopenharmony_ci		.matches = {
55662306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "GM5RG1E0009COM"),
55762306a36Sopenharmony_ci		},
55862306a36Sopenharmony_ci	},
55962306a36Sopenharmony_ci	{
56062306a36Sopenharmony_ci		/* Infinity E15-5A305-1M */
56162306a36Sopenharmony_ci		.matches = {
56262306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "GM5RGEE0016COM"),
56362306a36Sopenharmony_ci		},
56462306a36Sopenharmony_ci	},
56562306a36Sopenharmony_ci	{
56662306a36Sopenharmony_ci		/* Lunnen Ground 15 / AMD Ryzen 5 5500U */
56762306a36Sopenharmony_ci		.matches = {
56862306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),
56962306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "LLL5DAW"),
57062306a36Sopenharmony_ci		},
57162306a36Sopenharmony_ci	},
57262306a36Sopenharmony_ci	{
57362306a36Sopenharmony_ci		/* Lunnen Ground 16 / AMD Ryzen 7 5800U */
57462306a36Sopenharmony_ci		.matches = {
57562306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),
57662306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "LL6FA"),
57762306a36Sopenharmony_ci		},
57862306a36Sopenharmony_ci	},
57962306a36Sopenharmony_ci	{
58062306a36Sopenharmony_ci		/* MAIBENBEN X577 */
58162306a36Sopenharmony_ci		.matches = {
58262306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "MAIBENBEN"),
58362306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "X577"),
58462306a36Sopenharmony_ci		},
58562306a36Sopenharmony_ci	},
58662306a36Sopenharmony_ci	{ }
58762306a36Sopenharmony_ci};
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cistatic const struct dmi_system_id lg_laptop[] = {
59062306a36Sopenharmony_ci	{
59162306a36Sopenharmony_ci		.ident = "LG Electronics 17U70P",
59262306a36Sopenharmony_ci		.matches = {
59362306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
59462306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "17U70P"),
59562306a36Sopenharmony_ci		},
59662306a36Sopenharmony_ci	},
59762306a36Sopenharmony_ci	{ }
59862306a36Sopenharmony_ci};
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_cistruct irq_override_cmp {
60162306a36Sopenharmony_ci	const struct dmi_system_id *system;
60262306a36Sopenharmony_ci	unsigned char irq;
60362306a36Sopenharmony_ci	unsigned char triggering;
60462306a36Sopenharmony_ci	unsigned char polarity;
60562306a36Sopenharmony_ci	unsigned char shareable;
60662306a36Sopenharmony_ci	bool override;
60762306a36Sopenharmony_ci};
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_cistatic const struct irq_override_cmp override_table[] = {
61062306a36Sopenharmony_ci	{ medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
61162306a36Sopenharmony_ci	{ asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
61262306a36Sopenharmony_ci	{ tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
61362306a36Sopenharmony_ci	{ maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
61462306a36Sopenharmony_ci	{ pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
61562306a36Sopenharmony_ci	{ lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
61662306a36Sopenharmony_ci};
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_cistatic bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
61962306a36Sopenharmony_ci				  u8 shareable)
62062306a36Sopenharmony_ci{
62162306a36Sopenharmony_ci	int i;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(override_table); i++) {
62462306a36Sopenharmony_ci		const struct irq_override_cmp *entry = &override_table[i];
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci		if (dmi_check_system(entry->system) &&
62762306a36Sopenharmony_ci		    entry->irq == gsi &&
62862306a36Sopenharmony_ci		    entry->triggering == triggering &&
62962306a36Sopenharmony_ci		    entry->polarity == polarity &&
63062306a36Sopenharmony_ci		    entry->shareable == shareable)
63162306a36Sopenharmony_ci			return entry->override;
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci#ifdef CONFIG_X86
63562306a36Sopenharmony_ci	/*
63662306a36Sopenharmony_ci	 * Always use the MADT override info, except for the i8042 PS/2 ctrl
63762306a36Sopenharmony_ci	 * IRQs (1 and 12). For these the DSDT IRQ settings should sometimes
63862306a36Sopenharmony_ci	 * be used otherwise PS/2 keyboards / mice will not work.
63962306a36Sopenharmony_ci	 */
64062306a36Sopenharmony_ci	if (gsi != 1 && gsi != 12)
64162306a36Sopenharmony_ci		return true;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	/* If the override comes from an INT_SRC_OVR MADT entry, honor it. */
64462306a36Sopenharmony_ci	if (acpi_int_src_ovr[gsi])
64562306a36Sopenharmony_ci		return true;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	/*
64862306a36Sopenharmony_ci	 * IRQ override isn't needed on modern AMD Zen systems and
64962306a36Sopenharmony_ci	 * this override breaks active low IRQs on AMD Ryzen 6000 and
65062306a36Sopenharmony_ci	 * newer systems. Skip it.
65162306a36Sopenharmony_ci	 */
65262306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_ZEN))
65362306a36Sopenharmony_ci		return false;
65462306a36Sopenharmony_ci#endif
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	return true;
65762306a36Sopenharmony_ci}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_cistatic void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
66062306a36Sopenharmony_ci				     u8 triggering, u8 polarity, u8 shareable,
66162306a36Sopenharmony_ci				     u8 wake_capable, bool check_override)
66262306a36Sopenharmony_ci{
66362306a36Sopenharmony_ci	int irq, p, t;
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	if (!valid_IRQ(gsi)) {
66662306a36Sopenharmony_ci		irqresource_disabled(res, gsi);
66762306a36Sopenharmony_ci		return;
66862306a36Sopenharmony_ci	}
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	/*
67162306a36Sopenharmony_ci	 * In IO-APIC mode, use overridden attribute. Two reasons:
67262306a36Sopenharmony_ci	 * 1. BIOS bug in DSDT
67362306a36Sopenharmony_ci	 * 2. BIOS uses IO-APIC mode Interrupt Source Override
67462306a36Sopenharmony_ci	 *
67562306a36Sopenharmony_ci	 * We do this only if we are dealing with IRQ() or IRQNoFlags()
67662306a36Sopenharmony_ci	 * resource (the legacy ISA resources). With modern ACPI 5 devices
67762306a36Sopenharmony_ci	 * using extended IRQ descriptors we take the IRQ configuration
67862306a36Sopenharmony_ci	 * from _CRS directly.
67962306a36Sopenharmony_ci	 */
68062306a36Sopenharmony_ci	if (check_override &&
68162306a36Sopenharmony_ci	    acpi_dev_irq_override(gsi, triggering, polarity, shareable) &&
68262306a36Sopenharmony_ci	    !acpi_get_override_irq(gsi, &t, &p)) {
68362306a36Sopenharmony_ci		u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
68462306a36Sopenharmony_ci		u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci		if (triggering != trig || polarity != pol) {
68762306a36Sopenharmony_ci			pr_warn("ACPI: IRQ %d override to %s%s, %s%s\n", gsi,
68862306a36Sopenharmony_ci				t ? "level" : "edge",
68962306a36Sopenharmony_ci				trig == triggering ? "" : "(!)",
69062306a36Sopenharmony_ci				p ? "low" : "high",
69162306a36Sopenharmony_ci				pol == polarity ? "" : "(!)");
69262306a36Sopenharmony_ci			triggering = trig;
69362306a36Sopenharmony_ci			polarity = pol;
69462306a36Sopenharmony_ci		}
69562306a36Sopenharmony_ci	}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	res->flags = acpi_dev_irq_flags(triggering, polarity, shareable, wake_capable);
69862306a36Sopenharmony_ci	irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
69962306a36Sopenharmony_ci	if (irq >= 0) {
70062306a36Sopenharmony_ci		res->start = irq;
70162306a36Sopenharmony_ci		res->end = irq;
70262306a36Sopenharmony_ci	} else {
70362306a36Sopenharmony_ci		irqresource_disabled(res, gsi);
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci}
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci/**
70862306a36Sopenharmony_ci * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
70962306a36Sopenharmony_ci * @ares: Input ACPI resource object.
71062306a36Sopenharmony_ci * @index: Index into the array of GSIs represented by the resource.
71162306a36Sopenharmony_ci * @res: Output generic resource object.
71262306a36Sopenharmony_ci *
71362306a36Sopenharmony_ci * Check if the given ACPI resource object represents an interrupt resource
71462306a36Sopenharmony_ci * and @index does not exceed the resource's interrupt count (true is returned
71562306a36Sopenharmony_ci * in that case regardless of the results of the other checks)).  If that's the
71662306a36Sopenharmony_ci * case, register the GSI corresponding to @index from the array of interrupts
71762306a36Sopenharmony_ci * represented by the resource and populate the generic resource object pointed
71862306a36Sopenharmony_ci * to by @res accordingly.  If the registration of the GSI is not successful,
71962306a36Sopenharmony_ci * IORESOURCE_DISABLED will be set it that object's flags.
72062306a36Sopenharmony_ci *
72162306a36Sopenharmony_ci * Return:
72262306a36Sopenharmony_ci * 1) false with res->flags setting to zero: not the expected resource type
72362306a36Sopenharmony_ci * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
72462306a36Sopenharmony_ci * 3) true: valid assigned resource
72562306a36Sopenharmony_ci */
72662306a36Sopenharmony_cibool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
72762306a36Sopenharmony_ci				 struct resource *res)
72862306a36Sopenharmony_ci{
72962306a36Sopenharmony_ci	struct acpi_resource_irq *irq;
73062306a36Sopenharmony_ci	struct acpi_resource_extended_irq *ext_irq;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	switch (ares->type) {
73362306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_IRQ:
73462306a36Sopenharmony_ci		/*
73562306a36Sopenharmony_ci		 * Per spec, only one interrupt per descriptor is allowed in
73662306a36Sopenharmony_ci		 * _CRS, but some firmware violates this, so parse them all.
73762306a36Sopenharmony_ci		 */
73862306a36Sopenharmony_ci		irq = &ares->data.irq;
73962306a36Sopenharmony_ci		if (index >= irq->interrupt_count) {
74062306a36Sopenharmony_ci			irqresource_disabled(res, 0);
74162306a36Sopenharmony_ci			return false;
74262306a36Sopenharmony_ci		}
74362306a36Sopenharmony_ci		acpi_dev_get_irqresource(res, irq->interrupts[index],
74462306a36Sopenharmony_ci					 irq->triggering, irq->polarity,
74562306a36Sopenharmony_ci					 irq->shareable, irq->wake_capable,
74662306a36Sopenharmony_ci					 true);
74762306a36Sopenharmony_ci		break;
74862306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
74962306a36Sopenharmony_ci		ext_irq = &ares->data.extended_irq;
75062306a36Sopenharmony_ci		if (index >= ext_irq->interrupt_count) {
75162306a36Sopenharmony_ci			irqresource_disabled(res, 0);
75262306a36Sopenharmony_ci			return false;
75362306a36Sopenharmony_ci		}
75462306a36Sopenharmony_ci		if (is_gsi(ext_irq))
75562306a36Sopenharmony_ci			acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
75662306a36Sopenharmony_ci					 ext_irq->triggering, ext_irq->polarity,
75762306a36Sopenharmony_ci					 ext_irq->shareable, ext_irq->wake_capable,
75862306a36Sopenharmony_ci					 false);
75962306a36Sopenharmony_ci		else
76062306a36Sopenharmony_ci			irqresource_disabled(res, 0);
76162306a36Sopenharmony_ci		break;
76262306a36Sopenharmony_ci	default:
76362306a36Sopenharmony_ci		res->flags = 0;
76462306a36Sopenharmony_ci		return false;
76562306a36Sopenharmony_ci	}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	return true;
76862306a36Sopenharmony_ci}
76962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci/**
77262306a36Sopenharmony_ci * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().
77362306a36Sopenharmony_ci * @list: The head of the resource list to free.
77462306a36Sopenharmony_ci */
77562306a36Sopenharmony_civoid acpi_dev_free_resource_list(struct list_head *list)
77662306a36Sopenharmony_ci{
77762306a36Sopenharmony_ci	resource_list_free(list);
77862306a36Sopenharmony_ci}
77962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_cistruct res_proc_context {
78262306a36Sopenharmony_ci	struct list_head *list;
78362306a36Sopenharmony_ci	int (*preproc)(struct acpi_resource *, void *);
78462306a36Sopenharmony_ci	void *preproc_data;
78562306a36Sopenharmony_ci	int count;
78662306a36Sopenharmony_ci	int error;
78762306a36Sopenharmony_ci};
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_cistatic acpi_status acpi_dev_new_resource_entry(struct resource_win *win,
79062306a36Sopenharmony_ci					       struct res_proc_context *c)
79162306a36Sopenharmony_ci{
79262306a36Sopenharmony_ci	struct resource_entry *rentry;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	rentry = resource_list_create_entry(NULL, 0);
79562306a36Sopenharmony_ci	if (!rentry) {
79662306a36Sopenharmony_ci		c->error = -ENOMEM;
79762306a36Sopenharmony_ci		return AE_NO_MEMORY;
79862306a36Sopenharmony_ci	}
79962306a36Sopenharmony_ci	*rentry->res = win->res;
80062306a36Sopenharmony_ci	rentry->offset = win->offset;
80162306a36Sopenharmony_ci	resource_list_add_tail(rentry, c->list);
80262306a36Sopenharmony_ci	c->count++;
80362306a36Sopenharmony_ci	return AE_OK;
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_cistatic acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
80762306a36Sopenharmony_ci					     void *context)
80862306a36Sopenharmony_ci{
80962306a36Sopenharmony_ci	struct res_proc_context *c = context;
81062306a36Sopenharmony_ci	struct resource_win win;
81162306a36Sopenharmony_ci	struct resource *res = &win.res;
81262306a36Sopenharmony_ci	int i;
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	if (c->preproc) {
81562306a36Sopenharmony_ci		int ret;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci		ret = c->preproc(ares, c->preproc_data);
81862306a36Sopenharmony_ci		if (ret < 0) {
81962306a36Sopenharmony_ci			c->error = ret;
82062306a36Sopenharmony_ci			return AE_ABORT_METHOD;
82162306a36Sopenharmony_ci		} else if (ret > 0) {
82262306a36Sopenharmony_ci			return AE_OK;
82362306a36Sopenharmony_ci		}
82462306a36Sopenharmony_ci	}
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	memset(&win, 0, sizeof(win));
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	if (acpi_dev_resource_memory(ares, res)
82962306a36Sopenharmony_ci	    || acpi_dev_resource_io(ares, res)
83062306a36Sopenharmony_ci	    || acpi_dev_resource_address_space(ares, &win)
83162306a36Sopenharmony_ci	    || acpi_dev_resource_ext_address_space(ares, &win))
83262306a36Sopenharmony_ci		return acpi_dev_new_resource_entry(&win, c);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	for (i = 0; acpi_dev_resource_interrupt(ares, i, res); i++) {
83562306a36Sopenharmony_ci		acpi_status status;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci		status = acpi_dev_new_resource_entry(&win, c);
83862306a36Sopenharmony_ci		if (ACPI_FAILURE(status))
83962306a36Sopenharmony_ci			return status;
84062306a36Sopenharmony_ci	}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	return AE_OK;
84362306a36Sopenharmony_ci}
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_cistatic int __acpi_dev_get_resources(struct acpi_device *adev,
84662306a36Sopenharmony_ci				    struct list_head *list,
84762306a36Sopenharmony_ci				    int (*preproc)(struct acpi_resource *, void *),
84862306a36Sopenharmony_ci				    void *preproc_data, char *method)
84962306a36Sopenharmony_ci{
85062306a36Sopenharmony_ci	struct res_proc_context c;
85162306a36Sopenharmony_ci	acpi_status status;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	if (!adev || !adev->handle || !list_empty(list))
85462306a36Sopenharmony_ci		return -EINVAL;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	if (!acpi_has_method(adev->handle, method))
85762306a36Sopenharmony_ci		return 0;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	c.list = list;
86062306a36Sopenharmony_ci	c.preproc = preproc;
86162306a36Sopenharmony_ci	c.preproc_data = preproc_data;
86262306a36Sopenharmony_ci	c.count = 0;
86362306a36Sopenharmony_ci	c.error = 0;
86462306a36Sopenharmony_ci	status = acpi_walk_resources(adev->handle, method,
86562306a36Sopenharmony_ci				     acpi_dev_process_resource, &c);
86662306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
86762306a36Sopenharmony_ci		acpi_dev_free_resource_list(list);
86862306a36Sopenharmony_ci		return c.error ? c.error : -EIO;
86962306a36Sopenharmony_ci	}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	return c.count;
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci/**
87562306a36Sopenharmony_ci * acpi_dev_get_resources - Get current resources of a device.
87662306a36Sopenharmony_ci * @adev: ACPI device node to get the resources for.
87762306a36Sopenharmony_ci * @list: Head of the resultant list of resources (must be empty).
87862306a36Sopenharmony_ci * @preproc: The caller's preprocessing routine.
87962306a36Sopenharmony_ci * @preproc_data: Pointer passed to the caller's preprocessing routine.
88062306a36Sopenharmony_ci *
88162306a36Sopenharmony_ci * Evaluate the _CRS method for the given device node and process its output by
88262306a36Sopenharmony_ci * (1) executing the @preproc() routine provided by the caller, passing the
88362306a36Sopenharmony_ci * resource pointer and @preproc_data to it as arguments, for each ACPI resource
88462306a36Sopenharmony_ci * returned and (2) converting all of the returned ACPI resources into struct
88562306a36Sopenharmony_ci * resource objects if possible.  If the return value of @preproc() in step (1)
88662306a36Sopenharmony_ci * is different from 0, step (2) is not applied to the given ACPI resource and
88762306a36Sopenharmony_ci * if that value is negative, the whole processing is aborted and that value is
88862306a36Sopenharmony_ci * returned as the final error code.
88962306a36Sopenharmony_ci *
89062306a36Sopenharmony_ci * The resultant struct resource objects are put on the list pointed to by
89162306a36Sopenharmony_ci * @list, that must be empty initially, as members of struct resource_entry
89262306a36Sopenharmony_ci * objects.  Callers of this routine should use %acpi_dev_free_resource_list() to
89362306a36Sopenharmony_ci * free that list.
89462306a36Sopenharmony_ci *
89562306a36Sopenharmony_ci * The number of resources in the output list is returned on success, an error
89662306a36Sopenharmony_ci * code reflecting the error condition is returned otherwise.
89762306a36Sopenharmony_ci */
89862306a36Sopenharmony_ciint acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
89962306a36Sopenharmony_ci			   int (*preproc)(struct acpi_resource *, void *),
90062306a36Sopenharmony_ci			   void *preproc_data)
90162306a36Sopenharmony_ci{
90262306a36Sopenharmony_ci	return __acpi_dev_get_resources(adev, list, preproc, preproc_data,
90362306a36Sopenharmony_ci					METHOD_NAME__CRS);
90462306a36Sopenharmony_ci}
90562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_get_resources);
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_cistatic int is_memory(struct acpi_resource *ares, void *not_used)
90862306a36Sopenharmony_ci{
90962306a36Sopenharmony_ci	struct resource_win win;
91062306a36Sopenharmony_ci	struct resource *res = &win.res;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	memset(&win, 0, sizeof(win));
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	if (acpi_dev_filter_resource_type(ares, IORESOURCE_MEM))
91562306a36Sopenharmony_ci		return 1;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	return !(acpi_dev_resource_memory(ares, res)
91862306a36Sopenharmony_ci	       || acpi_dev_resource_address_space(ares, &win)
91962306a36Sopenharmony_ci	       || acpi_dev_resource_ext_address_space(ares, &win));
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci/**
92362306a36Sopenharmony_ci * acpi_dev_get_dma_resources - Get current DMA resources of a device.
92462306a36Sopenharmony_ci * @adev: ACPI device node to get the resources for.
92562306a36Sopenharmony_ci * @list: Head of the resultant list of resources (must be empty).
92662306a36Sopenharmony_ci *
92762306a36Sopenharmony_ci * Evaluate the _DMA method for the given device node and process its
92862306a36Sopenharmony_ci * output.
92962306a36Sopenharmony_ci *
93062306a36Sopenharmony_ci * The resultant struct resource objects are put on the list pointed to
93162306a36Sopenharmony_ci * by @list, that must be empty initially, as members of struct
93262306a36Sopenharmony_ci * resource_entry objects.  Callers of this routine should use
93362306a36Sopenharmony_ci * %acpi_dev_free_resource_list() to free that list.
93462306a36Sopenharmony_ci *
93562306a36Sopenharmony_ci * The number of resources in the output list is returned on success,
93662306a36Sopenharmony_ci * an error code reflecting the error condition is returned otherwise.
93762306a36Sopenharmony_ci */
93862306a36Sopenharmony_ciint acpi_dev_get_dma_resources(struct acpi_device *adev, struct list_head *list)
93962306a36Sopenharmony_ci{
94062306a36Sopenharmony_ci	return __acpi_dev_get_resources(adev, list, is_memory, NULL,
94162306a36Sopenharmony_ci					METHOD_NAME__DMA);
94262306a36Sopenharmony_ci}
94362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_get_dma_resources);
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci/**
94662306a36Sopenharmony_ci * acpi_dev_get_memory_resources - Get current memory resources of a device.
94762306a36Sopenharmony_ci * @adev: ACPI device node to get the resources for.
94862306a36Sopenharmony_ci * @list: Head of the resultant list of resources (must be empty).
94962306a36Sopenharmony_ci *
95062306a36Sopenharmony_ci * This is a helper function that locates all memory type resources of @adev
95162306a36Sopenharmony_ci * with acpi_dev_get_resources().
95262306a36Sopenharmony_ci *
95362306a36Sopenharmony_ci * The number of resources in the output list is returned on success, an error
95462306a36Sopenharmony_ci * code reflecting the error condition is returned otherwise.
95562306a36Sopenharmony_ci */
95662306a36Sopenharmony_ciint acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list)
95762306a36Sopenharmony_ci{
95862306a36Sopenharmony_ci	return acpi_dev_get_resources(adev, list, is_memory, NULL);
95962306a36Sopenharmony_ci}
96062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_get_memory_resources);
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci/**
96362306a36Sopenharmony_ci * acpi_dev_filter_resource_type - Filter ACPI resource according to resource
96462306a36Sopenharmony_ci *				   types
96562306a36Sopenharmony_ci * @ares: Input ACPI resource object.
96662306a36Sopenharmony_ci * @types: Valid resource types of IORESOURCE_XXX
96762306a36Sopenharmony_ci *
96862306a36Sopenharmony_ci * This is a helper function to support acpi_dev_get_resources(), which filters
96962306a36Sopenharmony_ci * ACPI resource objects according to resource types.
97062306a36Sopenharmony_ci */
97162306a36Sopenharmony_ciint acpi_dev_filter_resource_type(struct acpi_resource *ares,
97262306a36Sopenharmony_ci				  unsigned long types)
97362306a36Sopenharmony_ci{
97462306a36Sopenharmony_ci	unsigned long type = 0;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	switch (ares->type) {
97762306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_MEMORY24:
97862306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_MEMORY32:
97962306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
98062306a36Sopenharmony_ci		type = IORESOURCE_MEM;
98162306a36Sopenharmony_ci		break;
98262306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_IO:
98362306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_FIXED_IO:
98462306a36Sopenharmony_ci		type = IORESOURCE_IO;
98562306a36Sopenharmony_ci		break;
98662306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_IRQ:
98762306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
98862306a36Sopenharmony_ci		type = IORESOURCE_IRQ;
98962306a36Sopenharmony_ci		break;
99062306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_DMA:
99162306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_FIXED_DMA:
99262306a36Sopenharmony_ci		type = IORESOURCE_DMA;
99362306a36Sopenharmony_ci		break;
99462306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
99562306a36Sopenharmony_ci		type = IORESOURCE_REG;
99662306a36Sopenharmony_ci		break;
99762306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_ADDRESS16:
99862306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_ADDRESS32:
99962306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_ADDRESS64:
100062306a36Sopenharmony_ci	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
100162306a36Sopenharmony_ci		if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)
100262306a36Sopenharmony_ci			type = IORESOURCE_MEM;
100362306a36Sopenharmony_ci		else if (ares->data.address.resource_type == ACPI_IO_RANGE)
100462306a36Sopenharmony_ci			type = IORESOURCE_IO;
100562306a36Sopenharmony_ci		else if (ares->data.address.resource_type ==
100662306a36Sopenharmony_ci			 ACPI_BUS_NUMBER_RANGE)
100762306a36Sopenharmony_ci			type = IORESOURCE_BUS;
100862306a36Sopenharmony_ci		break;
100962306a36Sopenharmony_ci	default:
101062306a36Sopenharmony_ci		break;
101162306a36Sopenharmony_ci	}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	return (type & types) ? 0 : 1;
101462306a36Sopenharmony_ci}
101562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_cistatic int acpi_dev_consumes_res(struct acpi_device *adev, struct resource *res)
101862306a36Sopenharmony_ci{
101962306a36Sopenharmony_ci	struct list_head resource_list;
102062306a36Sopenharmony_ci	struct resource_entry *rentry;
102162306a36Sopenharmony_ci	int ret, found = 0;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	INIT_LIST_HEAD(&resource_list);
102462306a36Sopenharmony_ci	ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
102562306a36Sopenharmony_ci	if (ret < 0)
102662306a36Sopenharmony_ci		return 0;
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	list_for_each_entry(rentry, &resource_list, node) {
102962306a36Sopenharmony_ci		if (resource_contains(rentry->res, res)) {
103062306a36Sopenharmony_ci			found = 1;
103162306a36Sopenharmony_ci			break;
103262306a36Sopenharmony_ci		}
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	acpi_dev_free_resource_list(&resource_list);
103762306a36Sopenharmony_ci	return found;
103862306a36Sopenharmony_ci}
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_cistatic acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,
104162306a36Sopenharmony_ci					 void *context, void **ret)
104262306a36Sopenharmony_ci{
104362306a36Sopenharmony_ci	struct resource *res = context;
104462306a36Sopenharmony_ci	struct acpi_device **consumer = (struct acpi_device **) ret;
104562306a36Sopenharmony_ci	struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	if (!adev)
104862306a36Sopenharmony_ci		return AE_OK;
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	if (acpi_dev_consumes_res(adev, res)) {
105162306a36Sopenharmony_ci		*consumer = adev;
105262306a36Sopenharmony_ci		return AE_CTRL_TERMINATE;
105362306a36Sopenharmony_ci	}
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	return AE_OK;
105662306a36Sopenharmony_ci}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci/**
105962306a36Sopenharmony_ci * acpi_resource_consumer - Find the ACPI device that consumes @res.
106062306a36Sopenharmony_ci * @res: Resource to search for.
106162306a36Sopenharmony_ci *
106262306a36Sopenharmony_ci * Search the current resource settings (_CRS) of every ACPI device node
106362306a36Sopenharmony_ci * for @res.  If we find an ACPI device whose _CRS includes @res, return
106462306a36Sopenharmony_ci * it.  Otherwise, return NULL.
106562306a36Sopenharmony_ci */
106662306a36Sopenharmony_cistruct acpi_device *acpi_resource_consumer(struct resource *res)
106762306a36Sopenharmony_ci{
106862306a36Sopenharmony_ci	struct acpi_device *consumer = NULL;
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	acpi_get_devices(NULL, acpi_res_consumer_cb, res, (void **) &consumer);
107162306a36Sopenharmony_ci	return consumer;
107262306a36Sopenharmony_ci}
1073