0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <linux/err.h>
0035 #include <linux/init.h>
0036 #include <linux/interrupt.h>
0037 #include <linux/list.h>
0038 #include <linux/platform_device.h>
0039 #include <linux/acpi.h>
0040
0041 #define MODULE_NAME "acpi-ged"
0042
0043 struct acpi_ged_device {
0044 struct device *dev;
0045 struct list_head event_list;
0046 };
0047
0048 struct acpi_ged_event {
0049 struct list_head node;
0050 struct device *dev;
0051 unsigned int gsi;
0052 unsigned int irq;
0053 acpi_handle handle;
0054 };
0055
0056 static irqreturn_t acpi_ged_irq_handler(int irq, void *data)
0057 {
0058 struct acpi_ged_event *event = data;
0059 acpi_status acpi_ret;
0060
0061 acpi_ret = acpi_execute_simple_method(event->handle, NULL, event->gsi);
0062 if (ACPI_FAILURE(acpi_ret))
0063 dev_err_once(event->dev, "IRQ method execution failed\n");
0064
0065 return IRQ_HANDLED;
0066 }
0067
0068 static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
0069 void *context)
0070 {
0071 struct acpi_ged_event *event;
0072 unsigned int irq;
0073 unsigned int gsi;
0074 unsigned int irqflags = IRQF_ONESHOT;
0075 struct acpi_ged_device *geddev = context;
0076 struct device *dev = geddev->dev;
0077 acpi_handle handle = ACPI_HANDLE(dev);
0078 acpi_handle evt_handle;
0079 struct resource r;
0080 struct acpi_resource_irq *p = &ares->data.irq;
0081 struct acpi_resource_extended_irq *pext = &ares->data.extended_irq;
0082 char ev_name[5];
0083 u8 trigger;
0084
0085 if (ares->type == ACPI_RESOURCE_TYPE_END_TAG)
0086 return AE_OK;
0087
0088 if (!acpi_dev_resource_interrupt(ares, 0, &r)) {
0089 dev_err(dev, "unable to parse IRQ resource\n");
0090 return AE_ERROR;
0091 }
0092 if (ares->type == ACPI_RESOURCE_TYPE_IRQ) {
0093 gsi = p->interrupts[0];
0094 trigger = p->triggering;
0095 } else {
0096 gsi = pext->interrupts[0];
0097 trigger = pext->triggering;
0098 }
0099
0100 irq = r.start;
0101
0102 switch (gsi) {
0103 case 0 ... 255:
0104 sprintf(ev_name, "_%c%02X",
0105 trigger == ACPI_EDGE_SENSITIVE ? 'E' : 'L', gsi);
0106
0107 if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
0108 break;
0109 fallthrough;
0110 default:
0111 if (ACPI_SUCCESS(acpi_get_handle(handle, "_EVT", &evt_handle)))
0112 break;
0113
0114 dev_err(dev, "cannot locate _EVT method\n");
0115 return AE_ERROR;
0116 }
0117
0118 event = devm_kzalloc(dev, sizeof(*event), GFP_KERNEL);
0119 if (!event)
0120 return AE_ERROR;
0121
0122 event->gsi = gsi;
0123 event->dev = dev;
0124 event->irq = irq;
0125 event->handle = evt_handle;
0126
0127 if (r.flags & IORESOURCE_IRQ_SHAREABLE)
0128 irqflags |= IRQF_SHARED;
0129
0130 if (request_threaded_irq(irq, NULL, acpi_ged_irq_handler,
0131 irqflags, "ACPI:Ged", event)) {
0132 dev_err(dev, "failed to setup event handler for irq %u\n", irq);
0133 return AE_ERROR;
0134 }
0135
0136 dev_dbg(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq);
0137 list_add_tail(&event->node, &geddev->event_list);
0138 return AE_OK;
0139 }
0140
0141 static int ged_probe(struct platform_device *pdev)
0142 {
0143 struct acpi_ged_device *geddev;
0144 acpi_status acpi_ret;
0145
0146 geddev = devm_kzalloc(&pdev->dev, sizeof(*geddev), GFP_KERNEL);
0147 if (!geddev)
0148 return -ENOMEM;
0149
0150 geddev->dev = &pdev->dev;
0151 INIT_LIST_HEAD(&geddev->event_list);
0152 acpi_ret = acpi_walk_resources(ACPI_HANDLE(&pdev->dev), "_CRS",
0153 acpi_ged_request_interrupt, geddev);
0154 if (ACPI_FAILURE(acpi_ret)) {
0155 dev_err(&pdev->dev, "unable to parse the _CRS record\n");
0156 return -EINVAL;
0157 }
0158 platform_set_drvdata(pdev, geddev);
0159
0160 return 0;
0161 }
0162
0163 static void ged_shutdown(struct platform_device *pdev)
0164 {
0165 struct acpi_ged_device *geddev = platform_get_drvdata(pdev);
0166 struct acpi_ged_event *event, *next;
0167
0168 list_for_each_entry_safe(event, next, &geddev->event_list, node) {
0169 free_irq(event->irq, event);
0170 list_del(&event->node);
0171 dev_dbg(geddev->dev, "GED releasing GSI %u @ IRQ %u\n",
0172 event->gsi, event->irq);
0173 }
0174 }
0175
0176 static int ged_remove(struct platform_device *pdev)
0177 {
0178 ged_shutdown(pdev);
0179 return 0;
0180 }
0181
0182 static const struct acpi_device_id ged_acpi_ids[] = {
0183 {"ACPI0013"},
0184 {},
0185 };
0186
0187 static struct platform_driver ged_driver = {
0188 .probe = ged_probe,
0189 .remove = ged_remove,
0190 .shutdown = ged_shutdown,
0191 .driver = {
0192 .name = MODULE_NAME,
0193 .acpi_match_table = ACPI_PTR(ged_acpi_ids),
0194 },
0195 };
0196 builtin_platform_driver(ged_driver);