1046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki/* 2046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * drivers/acpi/resource.c - ACPI device resources interpretation. 3046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 4046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * Copyright (C) 2012, Intel Corp. 5046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> 6046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 7046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 9046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * This program is free software; you can redistribute it and/or modify 10046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * it under the terms of the GNU General Public License version 2 as published 11046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * by the Free Software Foundation. 12046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 13046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * This program is distributed in the hope that it will be useful, but 14046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * WITHOUT ANY WARRANTY; without even the implied warranty of 15046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * General Public License for more details. 17046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 18046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * You should have received a copy of the GNU General Public License along 19046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * with this program; if not, write to the Free Software Foundation, Inc., 20046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 21046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 22046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 24046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 25046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#include <linux/acpi.h> 26046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#include <linux/device.h> 27046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#include <linux/export.h> 28046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#include <linux/ioport.h> 298e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki#include <linux/slab.h> 30046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 31046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#ifdef CONFIG_X86 32046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#define valid_IRQ(i) (((i) != 0) && ((i) != 2)) 33046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#else 34046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#define valid_IRQ(i) (true) 35046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki#endif 36046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 37046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockistatic unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect, 38046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki bool window) 39046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 40046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki unsigned long flags = IORESOURCE_MEM; 41046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 42046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (len == 0) 43046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags |= IORESOURCE_DISABLED; 44046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 45046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (write_protect == ACPI_READ_WRITE_MEMORY) 46046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags |= IORESOURCE_MEM_WRITEABLE; 47046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 48046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (window) 49046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags |= IORESOURCE_WINDOW; 50046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 51046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return flags; 52046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 53046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 54046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockistatic void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, 55046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u8 write_protect) 56046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 57046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->start = start; 58046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->end = start + len - 1; 59046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = acpi_dev_memresource_flags(len, write_protect, false); 60046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 61046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 62046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki/** 63046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * acpi_dev_resource_memory - Extract ACPI memory resource information. 64046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @ares: Input ACPI resource object. 65046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @res: Output generic resource object. 66046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 67046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * Check if the given ACPI resource object represents a memory resource and 68046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * if that's the case, use the information in it to populate the generic 69046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * resource object pointed to by @res. 70046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 71046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockibool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) 72046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 73046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_memory24 *memory24; 74046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_memory32 *memory32; 75046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_fixed_memory32 *fixed_memory32; 76046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 77046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki switch (ares->type) { 78046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_MEMORY24: 79046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki memory24 = &ares->data.memory24; 80867f9d463b82462793ea4610e748be0b04b37fc7Andy Whitcroft if (!memory24->minimum && !memory24->address_length) 81b355cee88e3b1a193f0e9a81db810f6f83ad728bZhang Rui return false; 82046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_get_memresource(res, memory24->minimum, 83046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki memory24->address_length, 84046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki memory24->write_protect); 85046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 86046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_MEMORY32: 87046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki memory32 = &ares->data.memory32; 88867f9d463b82462793ea4610e748be0b04b37fc7Andy Whitcroft if (!memory32->minimum && !memory32->address_length) 89b355cee88e3b1a193f0e9a81db810f6f83ad728bZhang Rui return false; 90046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_get_memresource(res, memory32->minimum, 91046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki memory32->address_length, 92046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki memory32->write_protect); 93046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 94046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 95046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki fixed_memory32 = &ares->data.fixed_memory32; 96867f9d463b82462793ea4610e748be0b04b37fc7Andy Whitcroft if (!fixed_memory32->address && !fixed_memory32->address_length) 97b355cee88e3b1a193f0e9a81db810f6f83ad728bZhang Rui return false; 98046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_get_memresource(res, fixed_memory32->address, 99046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki fixed_memory32->address_length, 100046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki fixed_memory32->write_protect); 101046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 102046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki default: 103046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return false; 104046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 105046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return true; 106046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 107046d9ce6820e99087e81511284045eada94950e8Rafael J. WysockiEXPORT_SYMBOL_GPL(acpi_dev_resource_memory); 108046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 109046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockistatic unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode, 110046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki bool window) 111046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 112046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki int flags = IORESOURCE_IO; 113046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 114046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (io_decode == ACPI_DECODE_16) 115046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags |= IORESOURCE_IO_16BIT_ADDR; 116046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 117046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (start > end || end >= 0x10003) 118046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags |= IORESOURCE_DISABLED; 119046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 120046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (window) 121046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags |= IORESOURCE_WINDOW; 122046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 123046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return flags; 124046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 125046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 126046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockistatic void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, 127046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u8 io_decode) 128046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 129046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u64 end = start + len - 1; 130046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 131046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->start = start; 132046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->end = end; 133046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false); 134046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 135046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 136046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki/** 137046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * acpi_dev_resource_io - Extract ACPI I/O resource information. 138046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @ares: Input ACPI resource object. 139046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @res: Output generic resource object. 140046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 141046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * Check if the given ACPI resource object represents an I/O resource and 142046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * if that's the case, use the information in it to populate the generic 143046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * resource object pointed to by @res. 144046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 145046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockibool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) 146046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 147046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_io *io; 148046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_fixed_io *fixed_io; 149046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 150046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki switch (ares->type) { 151046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_IO: 152046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki io = &ares->data.io; 153867f9d463b82462793ea4610e748be0b04b37fc7Andy Whitcroft if (!io->minimum && !io->address_length) 154b355cee88e3b1a193f0e9a81db810f6f83ad728bZhang Rui return false; 155046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_get_ioresource(res, io->minimum, 156046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki io->address_length, 157046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki io->io_decode); 158046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 159046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_FIXED_IO: 160046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki fixed_io = &ares->data.fixed_io; 161867f9d463b82462793ea4610e748be0b04b37fc7Andy Whitcroft if (!fixed_io->address && !fixed_io->address_length) 162b355cee88e3b1a193f0e9a81db810f6f83ad728bZhang Rui return false; 163046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_get_ioresource(res, fixed_io->address, 164046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki fixed_io->address_length, 165046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki ACPI_DECODE_10); 166046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 167046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki default: 168046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return false; 169046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 170046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return true; 171046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 172046d9ce6820e99087e81511284045eada94950e8Rafael J. WysockiEXPORT_SYMBOL_GPL(acpi_dev_resource_io); 173046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 174046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki/** 175046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * acpi_dev_resource_address_space - Extract ACPI address space information. 176046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @ares: Input ACPI resource object. 177046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @res: Output generic resource object. 178046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 179046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * Check if the given ACPI resource object represents an address space resource 180046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * and if that's the case, use the information in it to populate the generic 181046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * resource object pointed to by @res. 182046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 183046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockibool acpi_dev_resource_address_space(struct acpi_resource *ares, 184046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct resource *res) 185046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 186046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_status status; 187046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_address64 addr; 188046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki bool window; 189046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u64 len; 190046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u8 io_decode; 191046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 192046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki switch (ares->type) { 193046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_ADDRESS16: 194046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_ADDRESS32: 195046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_ADDRESS64: 196046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 197046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki default: 198046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return false; 199046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 200046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 201046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki status = acpi_resource_to_address64(ares, &addr); 202046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (ACPI_FAILURE(status)) 203046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return true; 204046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 205046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->start = addr.minimum; 206046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->end = addr.maximum; 207046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki window = addr.producer_consumer == ACPI_PRODUCER; 208046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 209046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki switch(addr.resource_type) { 210046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_MEMORY_RANGE: 211046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki len = addr.maximum - addr.minimum + 1; 212046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = acpi_dev_memresource_flags(len, 213046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki addr.info.mem.write_protect, 214046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki window); 215046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 216046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_IO_RANGE: 217046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki io_decode = addr.granularity == 0xfff ? 218046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki ACPI_DECODE_10 : ACPI_DECODE_16; 219046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = acpi_dev_ioresource_flags(addr.minimum, 220046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki addr.maximum, 221046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki io_decode, window); 222046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 223046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_BUS_NUMBER_RANGE: 224046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = IORESOURCE_BUS; 225046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 226046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki default: 227046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = 0; 228046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 229046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 230046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return true; 231046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 232046d9ce6820e99087e81511284045eada94950e8Rafael J. WysockiEXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); 233046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 234046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki/** 235046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * acpi_dev_resource_ext_address_space - Extract ACPI address space information. 236046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @ares: Input ACPI resource object. 237046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @res: Output generic resource object. 238046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 239046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * Check if the given ACPI resource object represents an extended address space 240046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * resource and if that's the case, use the information in it to populate the 241046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * generic resource object pointed to by @res. 242046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 243046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockibool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, 244046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct resource *res) 245046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 246046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_extended_address64 *ext_addr; 247046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki bool window; 248046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u64 len; 249046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u8 io_decode; 250046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 251046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) 252046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return false; 253046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 254046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki ext_addr = &ares->data.ext_address64; 255046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 256046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->start = ext_addr->minimum; 257046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->end = ext_addr->maximum; 258046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki window = ext_addr->producer_consumer == ACPI_PRODUCER; 259046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 260046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki switch(ext_addr->resource_type) { 261046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_MEMORY_RANGE: 262046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki len = ext_addr->maximum - ext_addr->minimum + 1; 263046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = acpi_dev_memresource_flags(len, 264046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki ext_addr->info.mem.write_protect, 265046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki window); 266046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 267046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_IO_RANGE: 268046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki io_decode = ext_addr->granularity == 0xfff ? 269046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki ACPI_DECODE_10 : ACPI_DECODE_16; 270046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = acpi_dev_ioresource_flags(ext_addr->minimum, 271046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki ext_addr->maximum, 272046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki io_decode, window); 273046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 274046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_BUS_NUMBER_RANGE: 275046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = IORESOURCE_BUS; 276046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 277046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki default: 278046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = 0; 279046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 280046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 281046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return true; 282046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 283046d9ce6820e99087e81511284045eada94950e8Rafael J. WysockiEXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); 284046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 285046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki/** 286046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * acpi_dev_irq_flags - Determine IRQ resource flags. 287046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @triggering: Triggering type as provided by ACPI. 288046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @polarity: Interrupt polarity as provided by ACPI. 289046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @shareable: Whether or not the interrupt is shareable. 290046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 291046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockiunsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable) 292046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 293046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki unsigned long flags; 294046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 295046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (triggering == ACPI_LEVEL_SENSITIVE) 296046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags = polarity == ACPI_ACTIVE_LOW ? 297046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL; 298046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki else 299046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags = polarity == ACPI_ACTIVE_LOW ? 300046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE; 301046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 302046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (shareable == ACPI_SHARED) 303046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki flags |= IORESOURCE_IRQ_SHAREABLE; 304046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 305046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return flags | IORESOURCE_IRQ; 306046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 307046d9ce6820e99087e81511284045eada94950e8Rafael J. WysockiEXPORT_SYMBOL_GPL(acpi_dev_irq_flags); 308046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 309046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockistatic void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) 310046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 311046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->start = gsi; 312046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->end = gsi; 313046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED; 314046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 315046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 316046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockistatic void acpi_dev_get_irqresource(struct resource *res, u32 gsi, 317204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg u8 triggering, u8 polarity, u8 shareable, 318204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg bool legacy) 319046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 320046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki int irq, p, t; 321046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 322046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (!valid_IRQ(gsi)) { 323046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_irqresource_disabled(res, gsi); 324046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return; 325046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 326046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 327046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki /* 328046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * In IO-APIC mode, use overrided attribute. Two reasons: 329046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 1. BIOS bug in DSDT 330046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 2. BIOS uses IO-APIC mode Interrupt Source Override 331204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg * 332204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg * We do this only if we are dealing with IRQ() or IRQNoFlags() 333204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg * resource (the legacy ISA resources). With modern ACPI 5 devices 334204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg * using extended IRQ descriptors we take the IRQ configuration 335204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg * from _CRS directly. 336046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 337204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg if (legacy && !acpi_get_override_irq(gsi, &t, &p)) { 338046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; 339046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; 340046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 341046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (triggering != trig || polarity != pol) { 342046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi, 343204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg t ? "level" : "edge", p ? "low" : "high"); 344046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki triggering = trig; 345046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki polarity = pol; 346046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 347046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 348046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 349046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->flags = acpi_dev_irq_flags(triggering, polarity, shareable); 350046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki irq = acpi_register_gsi(NULL, gsi, triggering, polarity); 351046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (irq >= 0) { 352046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->start = irq; 353046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki res->end = irq; 354046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } else { 355046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_irqresource_disabled(res, gsi); 356046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 357046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 358046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 359046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki/** 360046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information. 361046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @ares: Input ACPI resource object. 362046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @index: Index into the array of GSIs represented by the resource. 363046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * @res: Output generic resource object. 364046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * 365046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * Check if the given ACPI resource object represents an interrupt resource 366046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * and @index does not exceed the resource's interrupt count (true is returned 367046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * in that case regardless of the results of the other checks)). If that's the 368046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * case, register the GSI corresponding to @index from the array of interrupts 369046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * represented by the resource and populate the generic resource object pointed 370046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * to by @res accordingly. If the registration of the GSI is not successful, 371046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * IORESOURCE_DISABLED will be set it that object's flags. 372046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 373046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysockibool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, 374046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct resource *res) 375046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki{ 376046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_irq *irq; 377046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki struct acpi_resource_extended_irq *ext_irq; 378046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 379046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki switch (ares->type) { 380046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_IRQ: 381046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki /* 382046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * Per spec, only one interrupt per descriptor is allowed in 383046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki * _CRS, but some firmware violates this, so parse them all. 384046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki */ 385046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki irq = &ares->data.irq; 386046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (index >= irq->interrupt_count) { 387046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_irqresource_disabled(res, 0); 388046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return false; 389046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 390046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_get_irqresource(res, irq->interrupts[index], 391046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki irq->triggering, irq->polarity, 392204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg irq->sharable, true); 393046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 394046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 395046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki ext_irq = &ares->data.extended_irq; 396046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki if (index >= ext_irq->interrupt_count) { 397046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_irqresource_disabled(res, 0); 398046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return false; 399046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 400046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki acpi_dev_get_irqresource(res, ext_irq->interrupts[index], 401046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki ext_irq->triggering, ext_irq->polarity, 402204ebc0aa30a7115f300cac39fbb7eeb66524881Mika Westerberg ext_irq->sharable, false); 403046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki break; 404046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki default: 405046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return false; 406046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki } 407046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki 408046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki return true; 409046d9ce6820e99087e81511284045eada94950e8Rafael J. Wysocki} 410046d9ce6820e99087e81511284045eada94950e8Rafael J. WysockiEXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt); 4118e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4128e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki/** 4138e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources(). 4148e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * @list: The head of the resource list to free. 4158e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki */ 4168e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysockivoid acpi_dev_free_resource_list(struct list_head *list) 4178e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki{ 4188e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki struct resource_list_entry *rentry, *re; 4198e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4208e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki list_for_each_entry_safe(rentry, re, list, node) { 4218e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki list_del(&rentry->node); 4228e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki kfree(rentry); 4238e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki } 4248e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki} 4258e345c991c8c7a3c081199ef77deada79e37618aRafael J. WysockiEXPORT_SYMBOL_GPL(acpi_dev_free_resource_list); 4268e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4278e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysockistruct res_proc_context { 4288e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki struct list_head *list; 4298e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki int (*preproc)(struct acpi_resource *, void *); 4308e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki void *preproc_data; 4318e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki int count; 4328e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki int error; 4338e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki}; 4348e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4358e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysockistatic acpi_status acpi_dev_new_resource_entry(struct resource *r, 4368e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki struct res_proc_context *c) 4378e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki{ 4388e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki struct resource_list_entry *rentry; 4398e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4408e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki rentry = kmalloc(sizeof(*rentry), GFP_KERNEL); 4418e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki if (!rentry) { 4428e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki c->error = -ENOMEM; 4438e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return AE_NO_MEMORY; 4448e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki } 4458e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki rentry->res = *r; 4468e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki list_add_tail(&rentry->node, c->list); 4478e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki c->count++; 4488e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return AE_OK; 4498e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki} 4508e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4518e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysockistatic acpi_status acpi_dev_process_resource(struct acpi_resource *ares, 4528e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki void *context) 4538e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki{ 4548e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki struct res_proc_context *c = context; 4558e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki struct resource r; 4568e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki int i; 4578e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4588e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki if (c->preproc) { 4598e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki int ret; 4608e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4618e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki ret = c->preproc(ares, c->preproc_data); 4628e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki if (ret < 0) { 4638e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki c->error = ret; 4648a66790b7850a6669129af078768a1d42076a0efRafael J. Wysocki return AE_CTRL_TERMINATE; 4658e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki } else if (ret > 0) { 4668e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return AE_OK; 4678e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki } 4688e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki } 4698e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4708e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki memset(&r, 0, sizeof(r)); 4718e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4728e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki if (acpi_dev_resource_memory(ares, &r) 4738e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki || acpi_dev_resource_io(ares, &r) 4748e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki || acpi_dev_resource_address_space(ares, &r) 4758e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki || acpi_dev_resource_ext_address_space(ares, &r)) 4768e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return acpi_dev_new_resource_entry(&r, c); 4778e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4788e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) { 4798e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki acpi_status status; 4808e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4818e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki status = acpi_dev_new_resource_entry(&r, c); 4828e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki if (ACPI_FAILURE(status)) 4838e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return status; 4848e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki } 4858e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4868e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return AE_OK; 4878e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki} 4888e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 4898e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki/** 4908e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * acpi_dev_get_resources - Get current resources of a device. 4918e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * @adev: ACPI device node to get the resources for. 4928e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * @list: Head of the resultant list of resources (must be empty). 4938e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * @preproc: The caller's preprocessing routine. 4948e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * @preproc_data: Pointer passed to the caller's preprocessing routine. 4958e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * 4968e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * Evaluate the _CRS method for the given device node and process its output by 4978e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * (1) executing the @preproc() rountine provided by the caller, passing the 4988e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * resource pointer and @preproc_data to it as arguments, for each ACPI resource 4998e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * returned and (2) converting all of the returned ACPI resources into struct 5008e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * resource objects if possible. If the return value of @preproc() in step (1) 5018e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * is different from 0, step (2) is not applied to the given ACPI resource and 5028e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * if that value is negative, the whole processing is aborted and that value is 5038e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * returned as the final error code. 5048e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * 5058e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * The resultant struct resource objects are put on the list pointed to by 5068e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * @list, that must be empty initially, as members of struct resource_list_entry 5078e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * objects. Callers of this routine should use %acpi_dev_free_resource_list() to 5088e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * free that list. 5098e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * 5108e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * The number of resources in the output list is returned on success, an error 5118e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki * code reflecting the error condition is returned otherwise. 5128e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki */ 5138e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysockiint acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, 5148e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki int (*preproc)(struct acpi_resource *, void *), 5158e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki void *preproc_data) 5168e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki{ 5178e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki struct res_proc_context c; 5188e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki acpi_status status; 5198e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 5208e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki if (!adev || !adev->handle || !list_empty(list)) 5218e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return -EINVAL; 5228e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 523952c63e9512b63220886105cfc791507046fa39aJiang Liu if (!acpi_has_method(adev->handle, METHOD_NAME__CRS)) 5248e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return 0; 5258e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 5268e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki c.list = list; 5278e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki c.preproc = preproc; 5288e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki c.preproc_data = preproc_data; 5298e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki c.count = 0; 5308e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki c.error = 0; 5318e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS, 5328e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki acpi_dev_process_resource, &c); 5338e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki if (ACPI_FAILURE(status)) { 5348e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki acpi_dev_free_resource_list(list); 5358e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return c.error ? c.error : -EIO; 5368e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki } 5378e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki 5388e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki return c.count; 5398e345c991c8c7a3c081199ef77deada79e37618aRafael J. Wysocki} 5408e345c991c8c7a3c081199ef77deada79e37618aRafael J. WysockiEXPORT_SYMBOL_GPL(acpi_dev_get_resources); 541