949 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * pnpacpi -- PnP ACPI driver4 *5 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>6 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>7 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.8 * Bjorn Helgaas <bjorn.helgaas@hp.com>9 */10#include <linux/kernel.h>11#include <linux/acpi.h>12#include <linux/pci.h>13#include <linux/pnp.h>14#include <linux/slab.h>15#include "../base.h"16#include "pnpacpi.h"17 18static void decode_irq_flags(struct pnp_dev *dev, int flags, u8 *triggering,19 u8 *polarity, u8 *shareable)20{21 switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |22 IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE)) {23 case IORESOURCE_IRQ_LOWLEVEL:24 *triggering = ACPI_LEVEL_SENSITIVE;25 *polarity = ACPI_ACTIVE_LOW;26 break;27 case IORESOURCE_IRQ_HIGHLEVEL:28 *triggering = ACPI_LEVEL_SENSITIVE;29 *polarity = ACPI_ACTIVE_HIGH;30 break;31 case IORESOURCE_IRQ_LOWEDGE:32 *triggering = ACPI_EDGE_SENSITIVE;33 *polarity = ACPI_ACTIVE_LOW;34 break;35 case IORESOURCE_IRQ_HIGHEDGE:36 *triggering = ACPI_EDGE_SENSITIVE;37 *polarity = ACPI_ACTIVE_HIGH;38 break;39 default:40 dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",41 flags);42 *triggering = ACPI_EDGE_SENSITIVE;43 *polarity = ACPI_ACTIVE_HIGH;44 break;45 }46 47 if (flags & IORESOURCE_IRQ_SHAREABLE)48 *shareable = ACPI_SHARED;49 else50 *shareable = ACPI_EXCLUSIVE;51}52 53static int dma_flags(struct pnp_dev *dev, int type, int bus_master,54 int transfer)55{56 int flags = 0;57 58 if (bus_master)59 flags |= IORESOURCE_DMA_MASTER;60 switch (type) {61 case ACPI_COMPATIBILITY:62 flags |= IORESOURCE_DMA_COMPATIBLE;63 break;64 case ACPI_TYPE_A:65 flags |= IORESOURCE_DMA_TYPEA;66 break;67 case ACPI_TYPE_B:68 flags |= IORESOURCE_DMA_TYPEB;69 break;70 case ACPI_TYPE_F:71 flags |= IORESOURCE_DMA_TYPEF;72 break;73 default:74 /* Set a default value ? */75 flags |= IORESOURCE_DMA_COMPATIBLE;76 dev_err(&dev->dev, "invalid DMA type %d\n", type);77 }78 switch (transfer) {79 case ACPI_TRANSFER_8:80 flags |= IORESOURCE_DMA_8BIT;81 break;82 case ACPI_TRANSFER_8_16:83 flags |= IORESOURCE_DMA_8AND16BIT;84 break;85 case ACPI_TRANSFER_16:86 flags |= IORESOURCE_DMA_16BIT;87 break;88 default:89 /* Set a default value ? */90 flags |= IORESOURCE_DMA_8AND16BIT;91 dev_err(&dev->dev, "invalid DMA transfer type %d\n", transfer);92 }93 94 return flags;95}96 97/*98 * Allocated Resources99 */100 101static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)102{103 if (!(r->flags & IORESOURCE_DISABLED))104 pcibios_penalize_isa_irq(r->start, 1);105 106 pnp_add_resource(dev, r);107}108 109/*110 * Device CSRs that do not appear in PCI config space should be described111 * via ACPI. This would normally be done with Address Space Descriptors112 * marked as "consumer-only," but old versions of Windows and Linux ignore113 * the producer/consumer flag, so HP invented a vendor-defined resource to114 * describe the location and size of CSR space.115 */116static struct acpi_vendor_uuid hp_ccsr_uuid = {117 .subtype = 2,118 .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,119 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },120};121 122static int vendor_resource_matches(struct pnp_dev *dev,123 struct acpi_resource_vendor_typed *vendor,124 struct acpi_vendor_uuid *match,125 int expected_len)126{127 int uuid_len = sizeof(vendor->uuid);128 u8 uuid_subtype = vendor->uuid_subtype;129 u8 *uuid = vendor->uuid;130 int actual_len;131 132 /* byte_length includes uuid_subtype and uuid */133 actual_len = vendor->byte_length - uuid_len - 1;134 135 if (uuid_subtype == match->subtype &&136 uuid_len == sizeof(match->data) &&137 memcmp(uuid, match->data, uuid_len) == 0) {138 if (expected_len && expected_len != actual_len) {139 dev_err(&dev->dev,140 "wrong vendor descriptor size; expected %d, found %d bytes\n",141 expected_len, actual_len);142 return 0;143 }144 145 return 1;146 }147 148 return 0;149}150 151static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,152 struct acpi_resource_vendor_typed *vendor)153{154 struct { u64 start, length; } range;155 156 if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid,157 sizeof(range))) {158 memcpy(&range, vendor->byte_data, sizeof(range));159 pnp_add_mem_resource(dev, range.start, range.start +160 range.length - 1, 0);161 }162}163 164static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,165 void *data)166{167 struct pnp_dev *dev = data;168 struct acpi_resource_dma *dma;169 struct acpi_resource_vendor_typed *vendor_typed;170 struct acpi_resource_gpio *gpio;171 struct resource_win win = {{0}, 0};172 struct resource *r = &win.res;173 int i, flags;174 175 if (acpi_dev_resource_address_space(res, &win)176 || acpi_dev_resource_ext_address_space(res, &win)) {177 pnp_add_resource(dev, &win.res);178 return AE_OK;179 }180 181 r->flags = 0;182 if (acpi_dev_resource_interrupt(res, 0, r)) {183 pnpacpi_add_irqresource(dev, r);184 for (i = 1; acpi_dev_resource_interrupt(res, i, r); i++)185 pnpacpi_add_irqresource(dev, r);186 187 if (i > 1) {188 /*189 * The IRQ encoder puts a single interrupt in each190 * descriptor, so if a _CRS descriptor has more than191 * one interrupt, we won't be able to re-encode it.192 */193 if (pnp_can_write(dev)) {194 dev_warn(&dev->dev,195 "multiple interrupts in _CRS descriptor; configuration can't be changed\n");196 dev->capabilities &= ~PNP_WRITE;197 }198 }199 return AE_OK;200 } else if (acpi_gpio_get_irq_resource(res, &gpio)) {201 /*202 * If the resource is GpioInt() type then extract the IRQ203 * from GPIO resource and fill it into IRQ resource type.204 */205 i = acpi_dev_gpio_irq_get(dev->data, 0);206 if (i >= 0) {207 flags = acpi_dev_irq_flags(gpio->triggering,208 gpio->polarity,209 gpio->shareable,210 gpio->wake_capable);211 } else {212 flags = IORESOURCE_DISABLED;213 }214 pnp_add_irq_resource(dev, i, flags);215 return AE_OK;216 } else if (r->flags & IORESOURCE_DISABLED) {217 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);218 return AE_OK;219 }220 221 switch (res->type) {222 case ACPI_RESOURCE_TYPE_MEMORY24:223 case ACPI_RESOURCE_TYPE_MEMORY32:224 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:225 if (acpi_dev_resource_memory(res, r))226 pnp_add_resource(dev, r);227 break;228 case ACPI_RESOURCE_TYPE_IO:229 case ACPI_RESOURCE_TYPE_FIXED_IO:230 if (acpi_dev_resource_io(res, r))231 pnp_add_resource(dev, r);232 break;233 case ACPI_RESOURCE_TYPE_DMA:234 dma = &res->data.dma;235 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)236 flags = dma_flags(dev, dma->type, dma->bus_master,237 dma->transfer);238 else239 flags = IORESOURCE_DISABLED;240 pnp_add_dma_resource(dev, dma->channels[0], flags);241 break;242 243 case ACPI_RESOURCE_TYPE_START_DEPENDENT:244 case ACPI_RESOURCE_TYPE_END_DEPENDENT:245 break;246 247 case ACPI_RESOURCE_TYPE_VENDOR:248 vendor_typed = &res->data.vendor_typed;249 pnpacpi_parse_allocated_vendor(dev, vendor_typed);250 break;251 252 case ACPI_RESOURCE_TYPE_END_TAG:253 break;254 255 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:256 break;257 258 case ACPI_RESOURCE_TYPE_SERIAL_BUS:259 /* serial bus connections (I2C/SPI/UART) are not pnp */260 break;261 262 default:263 dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",264 res->type);265 return AE_ERROR;266 }267 268 return AE_OK;269}270 271int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)272{273 struct acpi_device *acpi_dev = dev->data;274 acpi_handle handle = acpi_dev->handle;275 acpi_status status;276 277 pnp_dbg(&dev->dev, "parse allocated resources\n");278 279 pnp_init_resources(dev);280 281 status = acpi_walk_resources(handle, METHOD_NAME__CRS,282 pnpacpi_allocated_resource, dev);283 284 if (ACPI_FAILURE(status)) {285 if (status != AE_NOT_FOUND)286 dev_err(&dev->dev, "can't evaluate _CRS: %d", status);287 return -EPERM;288 }289 return 0;290}291 292static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,293 unsigned int option_flags,294 struct acpi_resource_dma *p)295{296 int i;297 unsigned char map = 0, flags;298 299 for (i = 0; i < p->channel_count; i++)300 map |= 1 << p->channels[i];301 302 flags = dma_flags(dev, p->type, p->bus_master, p->transfer);303 pnp_register_dma_resource(dev, option_flags, map, flags);304}305 306static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,307 unsigned int option_flags,308 struct acpi_resource_irq *p)309{310 int i;311 pnp_irq_mask_t map;312 unsigned char flags;313 314 bitmap_zero(map.bits, PNP_IRQ_NR);315 for (i = 0; i < p->interrupt_count; i++)316 if (p->interrupts[i])317 __set_bit(p->interrupts[i], map.bits);318 319 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable, p->wake_capable);320 pnp_register_irq_resource(dev, option_flags, &map, flags);321}322 323static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,324 unsigned int option_flags,325 struct acpi_resource_extended_irq *p)326{327 int i;328 pnp_irq_mask_t map;329 unsigned char flags;330 331 bitmap_zero(map.bits, PNP_IRQ_NR);332 for (i = 0; i < p->interrupt_count; i++) {333 if (p->interrupts[i]) {334 if (p->interrupts[i] < PNP_IRQ_NR)335 __set_bit(p->interrupts[i], map.bits);336 else337 dev_err(&dev->dev,338 "ignoring IRQ %d option (too large for %d entry bitmap)\n",339 p->interrupts[i], PNP_IRQ_NR);340 }341 }342 343 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->shareable, p->wake_capable);344 pnp_register_irq_resource(dev, option_flags, &map, flags);345}346 347static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,348 unsigned int option_flags,349 struct acpi_resource_io *io)350{351 unsigned char flags = 0;352 353 if (io->io_decode == ACPI_DECODE_16)354 flags = IORESOURCE_IO_16BIT_ADDR;355 pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,356 io->alignment, io->address_length, flags);357}358 359static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,360 unsigned int option_flags,361 struct acpi_resource_fixed_io *io)362{363 pnp_register_port_resource(dev, option_flags, io->address, io->address,364 0, io->address_length, IORESOURCE_IO_FIXED);365}366 367static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,368 unsigned int option_flags,369 struct acpi_resource_memory24 *p)370{371 unsigned char flags = 0;372 373 if (p->write_protect == ACPI_READ_WRITE_MEMORY)374 flags = IORESOURCE_MEM_WRITEABLE;375 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,376 p->alignment, p->address_length, flags);377}378 379static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,380 unsigned int option_flags,381 struct acpi_resource_memory32 *p)382{383 unsigned char flags = 0;384 385 if (p->write_protect == ACPI_READ_WRITE_MEMORY)386 flags = IORESOURCE_MEM_WRITEABLE;387 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,388 p->alignment, p->address_length, flags);389}390 391static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,392 unsigned int option_flags,393 struct acpi_resource_fixed_memory32 *p)394{395 unsigned char flags = 0;396 397 if (p->write_protect == ACPI_READ_WRITE_MEMORY)398 flags = IORESOURCE_MEM_WRITEABLE;399 pnp_register_mem_resource(dev, option_flags, p->address, p->address,400 0, p->address_length, flags);401}402 403static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,404 unsigned int option_flags,405 struct acpi_resource *r)406{407 struct acpi_resource_address64 addr, *p = &addr;408 acpi_status status;409 unsigned char flags = 0;410 411 status = acpi_resource_to_address64(r, p);412 if (ACPI_FAILURE(status)) {413 dev_warn(&dev->dev, "can't convert resource type %d\n",414 r->type);415 return;416 }417 418 if (p->resource_type == ACPI_MEMORY_RANGE) {419 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)420 flags = IORESOURCE_MEM_WRITEABLE;421 pnp_register_mem_resource(dev, option_flags, p->address.minimum,422 p->address.minimum, 0, p->address.address_length,423 flags);424 } else if (p->resource_type == ACPI_IO_RANGE)425 pnp_register_port_resource(dev, option_flags, p->address.minimum,426 p->address.minimum, 0, p->address.address_length,427 IORESOURCE_IO_FIXED);428}429 430static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,431 unsigned int option_flags,432 struct acpi_resource *r)433{434 struct acpi_resource_extended_address64 *p = &r->data.ext_address64;435 unsigned char flags = 0;436 437 if (p->resource_type == ACPI_MEMORY_RANGE) {438 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)439 flags = IORESOURCE_MEM_WRITEABLE;440 pnp_register_mem_resource(dev, option_flags, p->address.minimum,441 p->address.minimum, 0, p->address.address_length,442 flags);443 } else if (p->resource_type == ACPI_IO_RANGE)444 pnp_register_port_resource(dev, option_flags, p->address.minimum,445 p->address.minimum, 0, p->address.address_length,446 IORESOURCE_IO_FIXED);447}448 449struct acpipnp_parse_option_s {450 struct pnp_dev *dev;451 unsigned int option_flags;452};453 454static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,455 void *data)456{457 int priority;458 struct acpipnp_parse_option_s *parse_data = data;459 struct pnp_dev *dev = parse_data->dev;460 unsigned int option_flags = parse_data->option_flags;461 462 switch (res->type) {463 case ACPI_RESOURCE_TYPE_IRQ:464 pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);465 break;466 467 case ACPI_RESOURCE_TYPE_DMA:468 pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);469 break;470 471 case ACPI_RESOURCE_TYPE_START_DEPENDENT:472 switch (res->data.start_dpf.compatibility_priority) {473 case ACPI_GOOD_CONFIGURATION:474 priority = PNP_RES_PRIORITY_PREFERRED;475 break;476 477 case ACPI_ACCEPTABLE_CONFIGURATION:478 priority = PNP_RES_PRIORITY_ACCEPTABLE;479 break;480 481 case ACPI_SUB_OPTIMAL_CONFIGURATION:482 priority = PNP_RES_PRIORITY_FUNCTIONAL;483 break;484 default:485 priority = PNP_RES_PRIORITY_INVALID;486 break;487 }488 parse_data->option_flags = pnp_new_dependent_set(dev, priority);489 break;490 491 case ACPI_RESOURCE_TYPE_END_DEPENDENT:492 parse_data->option_flags = 0;493 break;494 495 case ACPI_RESOURCE_TYPE_IO:496 pnpacpi_parse_port_option(dev, option_flags, &res->data.io);497 break;498 499 case ACPI_RESOURCE_TYPE_FIXED_IO:500 pnpacpi_parse_fixed_port_option(dev, option_flags,501 &res->data.fixed_io);502 break;503 504 case ACPI_RESOURCE_TYPE_VENDOR:505 case ACPI_RESOURCE_TYPE_END_TAG:506 break;507 508 case ACPI_RESOURCE_TYPE_MEMORY24:509 pnpacpi_parse_mem24_option(dev, option_flags,510 &res->data.memory24);511 break;512 513 case ACPI_RESOURCE_TYPE_MEMORY32:514 pnpacpi_parse_mem32_option(dev, option_flags,515 &res->data.memory32);516 break;517 518 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:519 pnpacpi_parse_fixed_mem32_option(dev, option_flags,520 &res->data.fixed_memory32);521 break;522 523 case ACPI_RESOURCE_TYPE_ADDRESS16:524 case ACPI_RESOURCE_TYPE_ADDRESS32:525 case ACPI_RESOURCE_TYPE_ADDRESS64:526 pnpacpi_parse_address_option(dev, option_flags, res);527 break;528 529 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:530 pnpacpi_parse_ext_address_option(dev, option_flags, res);531 break;532 533 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:534 pnpacpi_parse_ext_irq_option(dev, option_flags,535 &res->data.extended_irq);536 break;537 538 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:539 break;540 541 default:542 dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",543 res->type);544 return AE_ERROR;545 }546 547 return AE_OK;548}549 550int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)551{552 struct acpi_device *acpi_dev = dev->data;553 acpi_handle handle = acpi_dev->handle;554 acpi_status status;555 struct acpipnp_parse_option_s parse_data;556 557 pnp_dbg(&dev->dev, "parse resource options\n");558 559 parse_data.dev = dev;560 parse_data.option_flags = 0;561 562 status = acpi_walk_resources(handle, METHOD_NAME__PRS,563 pnpacpi_option_resource, &parse_data);564 565 if (ACPI_FAILURE(status)) {566 if (status != AE_NOT_FOUND)567 dev_err(&dev->dev, "can't evaluate _PRS: %d", status);568 return -EPERM;569 }570 return 0;571}572 573static int pnpacpi_supported_resource(struct acpi_resource *res)574{575 switch (res->type) {576 case ACPI_RESOURCE_TYPE_IRQ:577 case ACPI_RESOURCE_TYPE_DMA:578 case ACPI_RESOURCE_TYPE_IO:579 case ACPI_RESOURCE_TYPE_FIXED_IO:580 case ACPI_RESOURCE_TYPE_MEMORY24:581 case ACPI_RESOURCE_TYPE_MEMORY32:582 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:583 case ACPI_RESOURCE_TYPE_ADDRESS16:584 case ACPI_RESOURCE_TYPE_ADDRESS32:585 case ACPI_RESOURCE_TYPE_ADDRESS64:586 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:587 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:588 return 1;589 }590 return 0;591}592 593/*594 * Set resource595 */596static acpi_status pnpacpi_count_resources(struct acpi_resource *res,597 void *data)598{599 int *res_cnt = data;600 601 if (pnpacpi_supported_resource(res))602 (*res_cnt)++;603 return AE_OK;604}605 606static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)607{608 struct acpi_resource **resource = data;609 610 if (pnpacpi_supported_resource(res)) {611 (*resource)->type = res->type;612 (*resource)->length = sizeof(struct acpi_resource);613 if (res->type == ACPI_RESOURCE_TYPE_IRQ)614 (*resource)->data.irq.descriptor_length =615 res->data.irq.descriptor_length;616 (*resource)++;617 }618 619 return AE_OK;620}621 622int pnpacpi_build_resource_template(struct pnp_dev *dev,623 struct acpi_buffer *buffer)624{625 struct acpi_device *acpi_dev = dev->data;626 acpi_handle handle = acpi_dev->handle;627 struct acpi_resource *resource;628 int res_cnt = 0;629 acpi_status status;630 631 status = acpi_walk_resources(handle, METHOD_NAME__CRS,632 pnpacpi_count_resources, &res_cnt);633 if (ACPI_FAILURE(status)) {634 dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);635 return -EINVAL;636 }637 if (!res_cnt)638 return -EINVAL;639 buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;640 buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);641 if (!buffer->pointer)642 return -ENOMEM;643 644 resource = (struct acpi_resource *)buffer->pointer;645 status = acpi_walk_resources(handle, METHOD_NAME__CRS,646 pnpacpi_type_resources, &resource);647 if (ACPI_FAILURE(status)) {648 kfree(buffer->pointer);649 dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);650 return -EINVAL;651 }652 /* resource will pointer the end resource now */653 resource->type = ACPI_RESOURCE_TYPE_END_TAG;654 resource->length = sizeof(struct acpi_resource);655 656 return 0;657}658 659static void pnpacpi_encode_irq(struct pnp_dev *dev,660 struct acpi_resource *resource,661 struct resource *p)662{663 struct acpi_resource_irq *irq = &resource->data.irq;664 u8 triggering, polarity, shareable;665 666 if (!pnp_resource_enabled(p)) {667 irq->interrupt_count = 0;668 pnp_dbg(&dev->dev, " encode irq (%s)\n",669 p ? "disabled" : "missing");670 return;671 }672 673 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);674 irq->triggering = triggering;675 irq->polarity = polarity;676 irq->shareable = shareable;677 irq->interrupt_count = 1;678 irq->interrupts[0] = p->start;679 680 pnp_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n",681 (int) p->start,682 triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",683 polarity == ACPI_ACTIVE_LOW ? "low" : "high",684 irq->shareable == ACPI_SHARED ? "shared" : "exclusive",685 irq->descriptor_length);686}687 688static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,689 struct acpi_resource *resource,690 struct resource *p)691{692 struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;693 u8 triggering, polarity, shareable;694 695 if (!pnp_resource_enabled(p)) {696 extended_irq->interrupt_count = 0;697 pnp_dbg(&dev->dev, " encode extended irq (%s)\n",698 p ? "disabled" : "missing");699 return;700 }701 702 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);703 extended_irq->producer_consumer = ACPI_CONSUMER;704 extended_irq->triggering = triggering;705 extended_irq->polarity = polarity;706 extended_irq->shareable = shareable;707 extended_irq->interrupt_count = 1;708 extended_irq->interrupts[0] = p->start;709 710 pnp_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,711 triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",712 polarity == ACPI_ACTIVE_LOW ? "low" : "high",713 extended_irq->shareable == ACPI_SHARED ? "shared" : "exclusive");714}715 716static void pnpacpi_encode_dma(struct pnp_dev *dev,717 struct acpi_resource *resource,718 struct resource *p)719{720 struct acpi_resource_dma *dma = &resource->data.dma;721 722 if (!pnp_resource_enabled(p)) {723 dma->channel_count = 0;724 pnp_dbg(&dev->dev, " encode dma (%s)\n",725 p ? "disabled" : "missing");726 return;727 }728 729 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */730 switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {731 case IORESOURCE_DMA_TYPEA:732 dma->type = ACPI_TYPE_A;733 break;734 case IORESOURCE_DMA_TYPEB:735 dma->type = ACPI_TYPE_B;736 break;737 case IORESOURCE_DMA_TYPEF:738 dma->type = ACPI_TYPE_F;739 break;740 default:741 dma->type = ACPI_COMPATIBILITY;742 }743 744 switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {745 case IORESOURCE_DMA_8BIT:746 dma->transfer = ACPI_TRANSFER_8;747 break;748 case IORESOURCE_DMA_8AND16BIT:749 dma->transfer = ACPI_TRANSFER_8_16;750 break;751 default:752 dma->transfer = ACPI_TRANSFER_16;753 }754 755 dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);756 dma->channel_count = 1;757 dma->channels[0] = p->start;758 759 pnp_dbg(&dev->dev, " encode dma %d "760 "type %#x transfer %#x master %d\n",761 (int) p->start, dma->type, dma->transfer, dma->bus_master);762}763 764static void pnpacpi_encode_io(struct pnp_dev *dev,765 struct acpi_resource *resource,766 struct resource *p)767{768 struct acpi_resource_io *io = &resource->data.io;769 770 if (pnp_resource_enabled(p)) {771 /* Note: pnp_assign_port copies pnp_port->flags into p->flags */772 io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ?773 ACPI_DECODE_16 : ACPI_DECODE_10;774 io->minimum = p->start;775 io->maximum = p->end;776 io->alignment = 0; /* Correct? */777 io->address_length = resource_size(p);778 } else {779 io->minimum = 0;780 io->address_length = 0;781 }782 783 pnp_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,784 io->minimum + io->address_length - 1, io->io_decode);785}786 787static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,788 struct acpi_resource *resource,789 struct resource *p)790{791 struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;792 793 if (pnp_resource_enabled(p)) {794 fixed_io->address = p->start;795 fixed_io->address_length = resource_size(p);796 } else {797 fixed_io->address = 0;798 fixed_io->address_length = 0;799 }800 801 pnp_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,802 fixed_io->address + fixed_io->address_length - 1);803}804 805static void pnpacpi_encode_mem24(struct pnp_dev *dev,806 struct acpi_resource *resource,807 struct resource *p)808{809 struct acpi_resource_memory24 *memory24 = &resource->data.memory24;810 811 if (pnp_resource_enabled(p)) {812 /* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */813 memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?814 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;815 memory24->minimum = p->start;816 memory24->maximum = p->end;817 memory24->alignment = 0;818 memory24->address_length = resource_size(p);819 } else {820 memory24->minimum = 0;821 memory24->address_length = 0;822 }823 824 pnp_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",825 memory24->minimum,826 memory24->minimum + memory24->address_length - 1,827 memory24->write_protect);828}829 830static void pnpacpi_encode_mem32(struct pnp_dev *dev,831 struct acpi_resource *resource,832 struct resource *p)833{834 struct acpi_resource_memory32 *memory32 = &resource->data.memory32;835 836 if (pnp_resource_enabled(p)) {837 memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?838 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;839 memory32->minimum = p->start;840 memory32->maximum = p->end;841 memory32->alignment = 0;842 memory32->address_length = resource_size(p);843 } else {844 memory32->minimum = 0;845 memory32->alignment = 0;846 }847 848 pnp_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",849 memory32->minimum,850 memory32->minimum + memory32->address_length - 1,851 memory32->write_protect);852}853 854static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,855 struct acpi_resource *resource,856 struct resource *p)857{858 struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;859 860 if (pnp_resource_enabled(p)) {861 fixed_memory32->write_protect =862 p->flags & IORESOURCE_MEM_WRITEABLE ?863 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;864 fixed_memory32->address = p->start;865 fixed_memory32->address_length = resource_size(p);866 } else {867 fixed_memory32->address = 0;868 fixed_memory32->address_length = 0;869 }870 871 pnp_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",872 fixed_memory32->address,873 fixed_memory32->address + fixed_memory32->address_length - 1,874 fixed_memory32->write_protect);875}876 877int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)878{879 int i = 0;880 /* pnpacpi_build_resource_template allocates extra mem */881 int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;882 struct acpi_resource *resource = buffer->pointer;883 unsigned int port = 0, irq = 0, dma = 0, mem = 0;884 885 pnp_dbg(&dev->dev, "encode %d resources\n", res_cnt);886 while (i < res_cnt) {887 switch (resource->type) {888 case ACPI_RESOURCE_TYPE_IRQ:889 pnpacpi_encode_irq(dev, resource,890 pnp_get_resource(dev, IORESOURCE_IRQ, irq));891 irq++;892 break;893 894 case ACPI_RESOURCE_TYPE_DMA:895 pnpacpi_encode_dma(dev, resource,896 pnp_get_resource(dev, IORESOURCE_DMA, dma));897 dma++;898 break;899 case ACPI_RESOURCE_TYPE_IO:900 pnpacpi_encode_io(dev, resource,901 pnp_get_resource(dev, IORESOURCE_IO, port));902 port++;903 break;904 case ACPI_RESOURCE_TYPE_FIXED_IO:905 pnpacpi_encode_fixed_io(dev, resource,906 pnp_get_resource(dev, IORESOURCE_IO, port));907 port++;908 break;909 case ACPI_RESOURCE_TYPE_MEMORY24:910 pnpacpi_encode_mem24(dev, resource,911 pnp_get_resource(dev, IORESOURCE_MEM, mem));912 mem++;913 break;914 case ACPI_RESOURCE_TYPE_MEMORY32:915 pnpacpi_encode_mem32(dev, resource,916 pnp_get_resource(dev, IORESOURCE_MEM, mem));917 mem++;918 break;919 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:920 pnpacpi_encode_fixed_mem32(dev, resource,921 pnp_get_resource(dev, IORESOURCE_MEM, mem));922 mem++;923 break;924 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:925 pnpacpi_encode_ext_irq(dev, resource,926 pnp_get_resource(dev, IORESOURCE_IRQ, irq));927 irq++;928 break;929 case ACPI_RESOURCE_TYPE_START_DEPENDENT:930 case ACPI_RESOURCE_TYPE_END_DEPENDENT:931 case ACPI_RESOURCE_TYPE_VENDOR:932 case ACPI_RESOURCE_TYPE_END_TAG:933 case ACPI_RESOURCE_TYPE_ADDRESS16:934 case ACPI_RESOURCE_TYPE_ADDRESS32:935 case ACPI_RESOURCE_TYPE_ADDRESS64:936 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:937 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:938 default: /* other type */939 dev_warn(&dev->dev,940 "can't encode unknown resource type %d\n",941 resource->type);942 return -EINVAL;943 }944 resource++;945 i++;946 }947 return 0;948}949