1 /* 2 * Generic Event Device for ACPI. 3 * 4 * Copyright (c) 2016, The Linux Foundation. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 and 8 * only version 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * Generic Event Device allows platforms to handle interrupts in ACPI 16 * ASL statements. It follows very similar to _EVT method approach 17 * from GPIO events. All interrupts are listed in _CRS and the handler 18 * is written in _EVT method. Here is an example. 19 * 20 * Device (GED0) 21 * { 22 * 23 * Name (_HID, "ACPI0013") 24 * Name (_UID, 0) 25 * Method (_CRS, 0x0, Serialized) 26 * { 27 * Name (RBUF, ResourceTemplate () 28 * { 29 * Interrupt(ResourceConsumer, Edge, ActiveHigh, Shared, , , ) 30 * {123} 31 * } 32 * }) 33 * 34 * Method (_EVT, 1) { 35 * if (Lequal(123, Arg0)) 36 * { 37 * } 38 * } 39 * } 40 * 41 */ 42 43 #include <linux/err.h> 44 #include <linux/init.h> 45 #include <linux/interrupt.h> 46 #include <linux/list.h> 47 #include <linux/platform_device.h> 48 #include <linux/acpi.h> 49 50 #define MODULE_NAME "acpi-ged" 51 52 struct acpi_ged_device { 53 struct device *dev; 54 struct list_head event_list; 55 }; 56 57 struct acpi_ged_event { 58 struct list_head node; 59 struct device *dev; 60 unsigned int gsi; 61 unsigned int irq; 62 acpi_handle handle; 63 }; 64 65 static irqreturn_t acpi_ged_irq_handler(int irq, void *data) 66 { 67 struct acpi_ged_event *event = data; 68 acpi_status acpi_ret; 69 70 acpi_ret = acpi_execute_simple_method(event->handle, NULL, event->gsi); 71 if (ACPI_FAILURE(acpi_ret)) 72 dev_err_once(event->dev, "IRQ method execution failed\n"); 73 74 return IRQ_HANDLED; 75 } 76 77 static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares, 78 void *context) 79 { 80 struct acpi_ged_event *event; 81 unsigned int irq; 82 unsigned int gsi; 83 unsigned int irqflags = IRQF_ONESHOT; 84 struct acpi_ged_device *geddev = context; 85 struct device *dev = geddev->dev; 86 acpi_handle handle = ACPI_HANDLE(dev); 87 acpi_handle evt_handle; 88 struct resource r; 89 struct acpi_resource_irq *p = &ares->data.irq; 90 struct acpi_resource_extended_irq *pext = &ares->data.extended_irq; 91 92 if (ares->type == ACPI_RESOURCE_TYPE_END_TAG) 93 return AE_OK; 94 95 if (!acpi_dev_resource_interrupt(ares, 0, &r)) { 96 dev_err(dev, "unable to parse IRQ resource\n"); 97 return AE_ERROR; 98 } 99 if (ares->type == ACPI_RESOURCE_TYPE_IRQ) 100 gsi = p->interrupts[0]; 101 else 102 gsi = pext->interrupts[0]; 103 104 irq = r.start; 105 106 if (ACPI_FAILURE(acpi_get_handle(handle, "_EVT", &evt_handle))) { 107 dev_err(dev, "cannot locate _EVT method\n"); 108 return AE_ERROR; 109 } 110 111 event = devm_kzalloc(dev, sizeof(*event), GFP_KERNEL); 112 if (!event) 113 return AE_ERROR; 114 115 event->gsi = gsi; 116 event->dev = dev; 117 event->irq = irq; 118 event->handle = evt_handle; 119 120 if (r.flags & IORESOURCE_IRQ_SHAREABLE) 121 irqflags |= IRQF_SHARED; 122 123 if (request_threaded_irq(irq, NULL, acpi_ged_irq_handler, 124 irqflags, "ACPI:Ged", event)) { 125 dev_err(dev, "failed to setup event handler for irq %u\n", irq); 126 return AE_ERROR; 127 } 128 129 dev_dbg(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq); 130 list_add_tail(&event->node, &geddev->event_list); 131 return AE_OK; 132 } 133 134 static int ged_probe(struct platform_device *pdev) 135 { 136 struct acpi_ged_device *geddev; 137 acpi_status acpi_ret; 138 139 geddev = devm_kzalloc(&pdev->dev, sizeof(*geddev), GFP_KERNEL); 140 if (!geddev) 141 return -ENOMEM; 142 143 geddev->dev = &pdev->dev; 144 INIT_LIST_HEAD(&geddev->event_list); 145 acpi_ret = acpi_walk_resources(ACPI_HANDLE(&pdev->dev), "_CRS", 146 acpi_ged_request_interrupt, geddev); 147 if (ACPI_FAILURE(acpi_ret)) { 148 dev_err(&pdev->dev, "unable to parse the _CRS record\n"); 149 return -EINVAL; 150 } 151 platform_set_drvdata(pdev, geddev); 152 153 return 0; 154 } 155 156 static void ged_shutdown(struct platform_device *pdev) 157 { 158 struct acpi_ged_device *geddev = platform_get_drvdata(pdev); 159 struct acpi_ged_event *event, *next; 160 161 list_for_each_entry_safe(event, next, &geddev->event_list, node) { 162 free_irq(event->irq, event); 163 list_del(&event->node); 164 dev_dbg(geddev->dev, "GED releasing GSI %u @ IRQ %u\n", 165 event->gsi, event->irq); 166 } 167 } 168 169 static int ged_remove(struct platform_device *pdev) 170 { 171 ged_shutdown(pdev); 172 return 0; 173 } 174 175 static const struct acpi_device_id ged_acpi_ids[] = { 176 {"ACPI0013"}, 177 {}, 178 }; 179 180 static struct platform_driver ged_driver = { 181 .probe = ged_probe, 182 .remove = ged_remove, 183 .shutdown = ged_shutdown, 184 .driver = { 185 .name = MODULE_NAME, 186 .acpi_match_table = ACPI_PTR(ged_acpi_ids), 187 }, 188 }; 189 builtin_platform_driver(ged_driver); 190