aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-14 18:30:01 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-14 18:30:01 -0500
commit046d9ce6820e99087e81511284045eada94950e8 (patch)
treeee711962f10007ca4f439aedbe8986ac531a4988 /drivers/pnp
parentb4b6cae2f36d92b31788f10816709d5290a1119a (diff)
ACPI: Move device resources interpretation code from PNP to ACPI core
Move some code used for parsing ACPI device resources from the PNP subsystem to the ACPI core, so that other bus types (platform, SPI, I2C) can use the same routines for parsing resources in a consistent way, without duplicating code. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/pnp')
-rw-r--r--drivers/pnp/base.h2
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c296
-rw-r--r--drivers/pnp/resource.c16
3 files changed, 50 insertions, 264 deletions
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index fa4e0a5db3f8..ffd53e3eb92f 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -159,6 +159,8 @@ struct pnp_resource {
159 159
160void pnp_free_resource(struct pnp_resource *pnp_res); 160void pnp_free_resource(struct pnp_resource *pnp_res);
161 161
162struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
163 struct resource *res);
162struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, 164struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
163 int flags); 165 int flags);
164struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, 166struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 5be4a392a3ae..b8f4ea7b27fc 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -28,37 +28,6 @@
28#include "../base.h" 28#include "../base.h"
29#include "pnpacpi.h" 29#include "pnpacpi.h"
30 30
31#ifdef CONFIG_IA64
32#define valid_IRQ(i) (1)
33#else
34#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
35#endif
36
37/*
38 * Allocated Resources
39 */
40static int irq_flags(int triggering, int polarity, int shareable)
41{
42 int flags;
43
44 if (triggering == ACPI_LEVEL_SENSITIVE) {
45 if (polarity == ACPI_ACTIVE_LOW)
46 flags = IORESOURCE_IRQ_LOWLEVEL;
47 else
48 flags = IORESOURCE_IRQ_HIGHLEVEL;
49 } else {
50 if (polarity == ACPI_ACTIVE_LOW)
51 flags = IORESOURCE_IRQ_LOWEDGE;
52 else
53 flags = IORESOURCE_IRQ_HIGHEDGE;
54 }
55
56 if (shareable == ACPI_SHARED)
57 flags |= IORESOURCE_IRQ_SHAREABLE;
58
59 return flags;
60}
61
62static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, 31static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
63 int *polarity, int *shareable) 32 int *polarity, int *shareable)
64{ 33{
@@ -94,45 +63,6 @@ static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
94 *shareable = ACPI_EXCLUSIVE; 63 *shareable = ACPI_EXCLUSIVE;
95} 64}
96 65
97static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
98 u32 gsi, int triggering,
99 int polarity, int shareable)
100{
101 int irq, flags;
102 int p, t;
103
104 if (!valid_IRQ(gsi)) {
105 pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
106 return;
107 }
108
109 /*
110 * in IO-APIC mode, use overrided attribute. Two reasons:
111 * 1. BIOS bug in DSDT
112 * 2. BIOS uses IO-APIC mode Interrupt Source Override
113 */
114 if (!acpi_get_override_irq(gsi, &t, &p)) {
115 t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
116 p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
117
118 if (triggering != t || polarity != p) {
119 dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
120 gsi, t ? "edge":"level", p ? "low":"high");
121 triggering = t;
122 polarity = p;
123 }
124 }
125
126 flags = irq_flags(triggering, polarity, shareable);
127 irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
128 if (irq >= 0)
129 pcibios_penalize_isa_irq(irq, 1);
130 else
131 flags |= IORESOURCE_DISABLED;
132
133 pnp_add_irq_resource(dev, irq, flags);
134}
135
136static int dma_flags(struct pnp_dev *dev, int type, int bus_master, 66static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
137 int transfer) 67 int transfer)
138{ 68{
@@ -177,21 +107,16 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
177 return flags; 107 return flags;
178} 108}
179 109
180static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, 110/*
181 u64 len, int io_decode, 111 * Allocated Resources
182 int window) 112 */
183{
184 int flags = 0;
185 u64 end = start + len - 1;
186 113
187 if (io_decode == ACPI_DECODE_16) 114static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
188 flags |= IORESOURCE_IO_16BIT_ADDR; 115{
189 if (len == 0 || end >= 0x10003) 116 if (!(r->flags & IORESOURCE_DISABLED))
190 flags |= IORESOURCE_DISABLED; 117 pcibios_penalize_isa_irq(r->start, 1);
191 if (window)
192 flags |= IORESOURCE_WINDOW;
193 118
194 pnp_add_io_resource(dev, start, end, flags); 119 pnp_add_resource(dev, r);
195} 120}
196 121
197/* 122/*
@@ -249,130 +174,49 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
249 } 174 }
250} 175}
251 176
252static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
253 u64 start, u64 len,
254 int write_protect, int window)
255{
256 int flags = 0;
257 u64 end = start + len - 1;
258
259 if (len == 0)
260 flags |= IORESOURCE_DISABLED;
261 if (write_protect == ACPI_READ_WRITE_MEMORY)
262 flags |= IORESOURCE_MEM_WRITEABLE;
263 if (window)
264 flags |= IORESOURCE_WINDOW;
265
266 pnp_add_mem_resource(dev, start, end, flags);
267}
268
269static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
270 u64 start, u64 len)
271{
272 u64 end = start + len - 1;
273
274 pnp_add_bus_resource(dev, start, end);
275}
276
277static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
278 struct acpi_resource *res)
279{
280 struct acpi_resource_address64 addr, *p = &addr;
281 acpi_status status;
282 int window;
283 u64 len;
284
285 status = acpi_resource_to_address64(res, p);
286 if (!ACPI_SUCCESS(status)) {
287 dev_warn(&dev->dev, "failed to convert resource type %d\n",
288 res->type);
289 return;
290 }
291
292 /* Windows apparently computes length rather than using _LEN */
293 len = p->maximum - p->minimum + 1;
294 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
295
296 if (p->resource_type == ACPI_MEMORY_RANGE)
297 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
298 p->info.mem.write_protect, window);
299 else if (p->resource_type == ACPI_IO_RANGE)
300 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
301 p->granularity == 0xfff ? ACPI_DECODE_10 :
302 ACPI_DECODE_16, window);
303 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
304 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
305}
306
307static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
308 struct acpi_resource *res)
309{
310 struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
311 int window;
312 u64 len;
313
314 /* Windows apparently computes length rather than using _LEN */
315 len = p->maximum - p->minimum + 1;
316 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
317
318 if (p->resource_type == ACPI_MEMORY_RANGE)
319 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
320 p->info.mem.write_protect, window);
321 else if (p->resource_type == ACPI_IO_RANGE)
322 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
323 p->granularity == 0xfff ? ACPI_DECODE_10 :
324 ACPI_DECODE_16, window);
325 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
326 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
327}
328
329static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, 177static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
330 void *data) 178 void *data)
331{ 179{
332 struct pnp_dev *dev = data; 180 struct pnp_dev *dev = data;
333 struct acpi_resource_irq *irq;
334 struct acpi_resource_dma *dma; 181 struct acpi_resource_dma *dma;
335 struct acpi_resource_io *io;
336 struct acpi_resource_fixed_io *fixed_io;
337 struct acpi_resource_vendor_typed *vendor_typed; 182 struct acpi_resource_vendor_typed *vendor_typed;
338 struct acpi_resource_memory24 *memory24; 183 struct resource r;
339 struct acpi_resource_memory32 *memory32;
340 struct acpi_resource_fixed_memory32 *fixed_memory32;
341 struct acpi_resource_extended_irq *extended_irq;
342 int i, flags; 184 int i, flags;
343 185
344 switch (res->type) { 186 if (acpi_dev_resource_memory(res, &r)
345 case ACPI_RESOURCE_TYPE_IRQ: 187 || acpi_dev_resource_io(res, &r)
346 /* 188 || acpi_dev_resource_address_space(res, &r)
347 * Per spec, only one interrupt per descriptor is allowed in 189 || acpi_dev_resource_ext_address_space(res, &r)) {
348 * _CRS, but some firmware violates this, so parse them all. 190 pnp_add_resource(dev, &r);
349 */ 191 return AE_OK;
350 irq = &res->data.irq; 192 }
351 if (irq->interrupt_count == 0)
352 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
353 else {
354 for (i = 0; i < irq->interrupt_count; i++) {
355 pnpacpi_parse_allocated_irqresource(dev,
356 irq->interrupts[i],
357 irq->triggering,
358 irq->polarity,
359 irq->sharable);
360 }
361 193
194 r.flags = 0;
195 if (acpi_dev_resource_interrupt(res, 0, &r)) {
196 pnpacpi_add_irqresource(dev, &r);
197 for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++)
198 pnpacpi_add_irqresource(dev, &r);
199
200 if (i > 1) {
362 /* 201 /*
363 * The IRQ encoder puts a single interrupt in each 202 * The IRQ encoder puts a single interrupt in each
364 * descriptor, so if a _CRS descriptor has more than 203 * descriptor, so if a _CRS descriptor has more than
365 * one interrupt, we won't be able to re-encode it. 204 * one interrupt, we won't be able to re-encode it.
366 */ 205 */
367 if (pnp_can_write(dev) && irq->interrupt_count > 1) { 206 if (pnp_can_write(dev)) {
368 dev_warn(&dev->dev, "multiple interrupts in " 207 dev_warn(&dev->dev, "multiple interrupts in "
369 "_CRS descriptor; configuration can't " 208 "_CRS descriptor; configuration can't "
370 "be changed\n"); 209 "be changed\n");
371 dev->capabilities &= ~PNP_WRITE; 210 dev->capabilities &= ~PNP_WRITE;
372 } 211 }
373 } 212 }
374 break; 213 return AE_OK;
214 } else if (r.flags & IORESOURCE_DISABLED) {
215 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
216 return AE_OK;
217 }
375 218
219 switch (res->type) {
376 case ACPI_RESOURCE_TYPE_DMA: 220 case ACPI_RESOURCE_TYPE_DMA:
377 dma = &res->data.dma; 221 dma = &res->data.dma;
378 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1) 222 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
@@ -383,26 +227,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
383 pnp_add_dma_resource(dev, dma->channels[0], flags); 227 pnp_add_dma_resource(dev, dma->channels[0], flags);
384 break; 228 break;
385 229
386 case ACPI_RESOURCE_TYPE_IO:
387 io = &res->data.io;
388 pnpacpi_parse_allocated_ioresource(dev,
389 io->minimum,
390 io->address_length,
391 io->io_decode, 0);
392 break;
393
394 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 230 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
395 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 231 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
396 break; 232 break;
397 233
398 case ACPI_RESOURCE_TYPE_FIXED_IO:
399 fixed_io = &res->data.fixed_io;
400 pnpacpi_parse_allocated_ioresource(dev,
401 fixed_io->address,
402 fixed_io->address_length,
403 ACPI_DECODE_10, 0);
404 break;
405
406 case ACPI_RESOURCE_TYPE_VENDOR: 234 case ACPI_RESOURCE_TYPE_VENDOR:
407 vendor_typed = &res->data.vendor_typed; 235 vendor_typed = &res->data.vendor_typed;
408 pnpacpi_parse_allocated_vendor(dev, vendor_typed); 236 pnpacpi_parse_allocated_vendor(dev, vendor_typed);
@@ -411,66 +239,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
411 case ACPI_RESOURCE_TYPE_END_TAG: 239 case ACPI_RESOURCE_TYPE_END_TAG:
412 break; 240 break;
413 241
414 case ACPI_RESOURCE_TYPE_MEMORY24:
415 memory24 = &res->data.memory24;
416 pnpacpi_parse_allocated_memresource(dev,
417 memory24->minimum,
418 memory24->address_length,
419 memory24->write_protect, 0);
420 break;
421 case ACPI_RESOURCE_TYPE_MEMORY32:
422 memory32 = &res->data.memory32;
423 pnpacpi_parse_allocated_memresource(dev,
424 memory32->minimum,
425 memory32->address_length,
426 memory32->write_protect, 0);
427 break;
428 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
429 fixed_memory32 = &res->data.fixed_memory32;
430 pnpacpi_parse_allocated_memresource(dev,
431 fixed_memory32->address,
432 fixed_memory32->address_length,
433 fixed_memory32->write_protect, 0);
434 break;
435 case ACPI_RESOURCE_TYPE_ADDRESS16:
436 case ACPI_RESOURCE_TYPE_ADDRESS32:
437 case ACPI_RESOURCE_TYPE_ADDRESS64:
438 pnpacpi_parse_allocated_address_space(dev, res);
439 break;
440
441 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
442 pnpacpi_parse_allocated_ext_address_space(dev, res);
443 break;
444
445 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
446 extended_irq = &res->data.extended_irq;
447
448 if (extended_irq->interrupt_count == 0)
449 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
450 else {
451 for (i = 0; i < extended_irq->interrupt_count; i++) {
452 pnpacpi_parse_allocated_irqresource(dev,
453 extended_irq->interrupts[i],
454 extended_irq->triggering,
455 extended_irq->polarity,
456 extended_irq->sharable);
457 }
458
459 /*
460 * The IRQ encoder puts a single interrupt in each
461 * descriptor, so if a _CRS descriptor has more than
462 * one interrupt, we won't be able to re-encode it.
463 */
464 if (pnp_can_write(dev) &&
465 extended_irq->interrupt_count > 1) {
466 dev_warn(&dev->dev, "multiple interrupts in "
467 "_CRS descriptor; configuration can't "
468 "be changed\n");
469 dev->capabilities &= ~PNP_WRITE;
470 }
471 }
472 break;
473
474 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 242 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
475 break; 243 break;
476 244
@@ -531,7 +299,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
531 if (p->interrupts[i]) 299 if (p->interrupts[i])
532 __set_bit(p->interrupts[i], map.bits); 300 __set_bit(p->interrupts[i], map.bits);
533 301
534 flags = irq_flags(p->triggering, p->polarity, p->sharable); 302 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
535 pnp_register_irq_resource(dev, option_flags, &map, flags); 303 pnp_register_irq_resource(dev, option_flags, &map, flags);
536} 304}
537 305
@@ -555,7 +323,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
555 } 323 }
556 } 324 }
557 325
558 flags = irq_flags(p->triggering, p->polarity, p->sharable); 326 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
559 pnp_register_irq_resource(dev, option_flags, &map, flags); 327 pnp_register_irq_resource(dev, option_flags, &map, flags);
560} 328}
561 329
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index b0ecacbe53b1..3e6db1c1dc29 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -503,6 +503,22 @@ static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
503 return pnp_res; 503 return pnp_res;
504} 504}
505 505
506struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
507 struct resource *res)
508{
509 struct pnp_resource *pnp_res;
510
511 pnp_res = pnp_new_resource(dev);
512 if (!pnp_res) {
513 dev_err(&dev->dev, "can't add resource %pR\n", res);
514 return NULL;
515 }
516
517 pnp_res->res = *res;
518 dev_dbg(&dev->dev, "%pR\n", res);
519 return pnp_res;
520}
521
506struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, 522struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
507 int flags) 523 int flags)
508{ 524{