2 * Support for Core System Resources Table (CSRT)
4 * Copyright (C) 2013, Intel Corporation
5 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
6 * Andy Shevchenko <andriy.shevchenko@linux.intel.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #define pr_fmt(fmt) "ACPI: CSRT: " fmt
15 #include <linux/acpi.h>
16 #include <linux/device.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/sizes.h>
22 ACPI_MODULE_NAME("CSRT");
24 static int __init
acpi_csrt_parse_shared_info(struct platform_device
*pdev
,
25 const struct acpi_csrt_group
*grp
)
27 const struct acpi_csrt_shared_info
*si
;
28 struct resource res
[3];
32 memset(res
, 0, sizeof(res
));
35 si
= (const struct acpi_csrt_shared_info
*)&grp
[1];
37 * The peripherals that are listed on CSRT typically support only
38 * 32-bit addresses so we only use the low part of MMIO base for
41 if (!si
->mmio_base_high
&& si
->mmio_base_low
) {
43 * There is no size of the memory resource in shared_info
44 * so we assume that it is 4k here.
46 res
[nres
].start
= si
->mmio_base_low
;
47 res
[nres
].end
= res
[0].start
+ SZ_4K
- 1;
48 res
[nres
++].flags
= IORESOURCE_MEM
;
51 if (si
->gsi_interrupt
) {
52 int irq
= acpi_register_gsi(NULL
, si
->gsi_interrupt
,
54 si
->interrupt_polarity
);
55 res
[nres
].start
= irq
;
57 res
[nres
++].flags
= IORESOURCE_IRQ
;
60 if (si
->base_request_line
|| si
->num_handshake_signals
) {
62 * We pass the driver a DMA resource describing the range
63 * of request lines the device supports.
65 res
[nres
].start
= si
->base_request_line
;
66 res
[nres
].end
= res
[nres
].start
+ si
->num_handshake_signals
- 1;
67 res
[nres
++].flags
= IORESOURCE_DMA
;
70 ret
= platform_device_add_resources(pdev
, res
, nres
);
72 if (si
->gsi_interrupt
)
73 acpi_unregister_gsi(si
->gsi_interrupt
);
81 acpi_csrt_parse_resource_group(const struct acpi_csrt_group
*grp
)
83 struct platform_device
*pdev
;
84 char vendor
[5], name
[16];
87 vendor
[0] = grp
->vendor_id
;
88 vendor
[1] = grp
->vendor_id
>> 8;
89 vendor
[2] = grp
->vendor_id
>> 16;
90 vendor
[3] = grp
->vendor_id
>> 24;
93 if (grp
->shared_info_length
!= sizeof(struct acpi_csrt_shared_info
))
96 snprintf(name
, sizeof(name
), "%s%04X", vendor
, grp
->device_id
);
97 pdev
= platform_device_alloc(name
, PLATFORM_DEVID_AUTO
);
101 /* Add resources based on the shared info */
102 ret
= acpi_csrt_parse_shared_info(pdev
, grp
);
106 ret
= platform_device_add(pdev
);
110 for (i
= 0; i
< pdev
->num_resources
; i
++)
111 dev_dbg(&pdev
->dev
, "%pR\n", &pdev
->resource
[i
]);
116 platform_device_put(pdev
);
121 * CSRT or Core System Resources Table is a proprietary ACPI table
122 * introduced by Microsoft. This table can contain devices that are not in
123 * the system DSDT table. In particular DMA controllers might be described
126 * We present these devices as normal platform devices that don't have ACPI
127 * IDs or handle. The platform device name will be something like
128 * <VENDOR><DEVID>.<n>.auto for example: INTL9C06.0.auto.
130 void __init
acpi_csrt_init(void)
132 struct acpi_csrt_group
*grp
, *end
;
133 struct acpi_table_csrt
*csrt
;
137 status
= acpi_get_table(ACPI_SIG_CSRT
, 0,
138 (struct acpi_table_header
**)&csrt
);
139 if (ACPI_FAILURE(status
)) {
140 if (status
!= AE_NOT_FOUND
)
141 pr_warn("failed to get the CSRT table\n");
145 pr_debug("parsing CSRT table for devices\n");
147 grp
= (struct acpi_csrt_group
*)(csrt
+ 1);
148 end
= (struct acpi_csrt_group
*)((void *)csrt
+ csrt
->header
.length
);
151 ret
= acpi_csrt_parse_resource_group(grp
);
153 pr_warn("error in parsing resource group: %d\n", ret
);
157 grp
= (struct acpi_csrt_group
*)((void *)grp
+ grp
->length
);