forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/platform/x86/intel_int0002_vgpio.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * Intel INT0002 "Virtual GPIO" driver
34 *
....@@ -8,10 +9,6 @@
89 * Copyright (c) 2014, Intel Corporation.
910 *
1011 * Author: Dyut Kumar Sil <dyut.k.sil@intel.com>
11
- *
12
- * This program is free software; you can redistribute it and/or modify
13
- * it under the terms of the GNU General Public License version 2 as
14
- * published by the Free Software Foundation.
1512 *
1613 * Some peripherals on Bay Trail and Cherry Trail platforms signal a Power
1714 * Management Event (PME) to the Power Management Controller (PMC) to wakeup
....@@ -54,16 +51,10 @@
5451 #define GPE0A_STS_PORT 0x420
5552 #define GPE0A_EN_PORT 0x428
5653
57
-#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
58
-
59
-static const struct x86_cpu_id int0002_cpu_ids[] = {
60
-/*
61
- * Limit ourselves to Cherry Trail for now, until testing shows we
62
- * need to handle the INT0002 device on Baytrail too.
63
- * ICPU(INTEL_FAM6_ATOM_SILVERMONT), * Valleyview, Bay Trail *
64
- */
65
- ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */
66
- {}
54
+struct int0002_data {
55
+ struct gpio_chip chip;
56
+ int parent_irq;
57
+ int wake_enable_count;
6758 };
6859
6960 /*
....@@ -110,6 +101,23 @@
110101 outl(gpe_en_reg, GPE0A_EN_PORT);
111102 }
112103
104
+static int int0002_irq_set_wake(struct irq_data *data, unsigned int on)
105
+{
106
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
107
+ struct int0002_data *int0002 = container_of(chip, struct int0002_data, chip);
108
+
109
+ /*
110
+ * Applying of the wakeup flag to our parent IRQ is delayed till system
111
+ * suspend, because we only want to do this when using s2idle.
112
+ */
113
+ if (on)
114
+ int0002->wake_enable_count++;
115
+ else
116
+ int0002->wake_enable_count--;
117
+
118
+ return 0;
119
+}
120
+
113121 static irqreturn_t int0002_irq(int irq, void *data)
114122 {
115123 struct gpio_chip *chip = data;
....@@ -122,9 +130,17 @@
122130 generic_handle_irq(irq_find_mapping(chip->irq.domain,
123131 GPE0A_PME_B0_VIRT_GPIO_PIN));
124132
125
- pm_system_wakeup();
133
+ pm_wakeup_hard_event(chip->parent);
126134
127135 return IRQ_HANDLED;
136
+}
137
+
138
+static bool int0002_check_wake(void *data)
139
+{
140
+ u32 gpe_sts_reg;
141
+
142
+ gpe_sts_reg = inl(GPE0A_STS_PORT);
143
+ return (gpe_sts_reg & GPE0A_PME_B0_STS_BIT);
128144 }
129145
130146 static struct irq_chip int0002_irqchip = {
....@@ -132,12 +148,28 @@
132148 .irq_ack = int0002_irq_ack,
133149 .irq_mask = int0002_irq_mask,
134150 .irq_unmask = int0002_irq_unmask,
151
+ .irq_set_wake = int0002_irq_set_wake,
135152 };
153
+
154
+static const struct x86_cpu_id int0002_cpu_ids[] = {
155
+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, NULL),
156
+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL),
157
+ {}
158
+};
159
+
160
+static void int0002_init_irq_valid_mask(struct gpio_chip *chip,
161
+ unsigned long *valid_mask,
162
+ unsigned int ngpios)
163
+{
164
+ bitmap_clear(valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
165
+}
136166
137167 static int int0002_probe(struct platform_device *pdev)
138168 {
139169 struct device *dev = &pdev->dev;
140170 const struct x86_cpu_id *cpu_id;
171
+ struct int0002_data *int0002;
172
+ struct gpio_irq_chip *girq;
141173 struct gpio_chip *chip;
142174 int irq, ret;
143175
....@@ -147,15 +179,16 @@
147179 return -ENODEV;
148180
149181 irq = platform_get_irq(pdev, 0);
150
- if (irq < 0) {
151
- dev_err(dev, "Error getting IRQ: %d\n", irq);
182
+ if (irq < 0)
152183 return irq;
153
- }
154184
155
- chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
156
- if (!chip)
185
+ int0002 = devm_kzalloc(dev, sizeof(*int0002), GFP_KERNEL);
186
+ if (!int0002)
157187 return -ENOMEM;
158188
189
+ int0002->parent_irq = irq;
190
+
191
+ chip = &int0002->chip;
159192 chip->label = DRV_NAME;
160193 chip->parent = dev;
161194 chip->owner = THIS_MODULE;
....@@ -165,19 +198,13 @@
165198 chip->direction_output = int0002_gpio_direction_output;
166199 chip->base = -1;
167200 chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1;
168
- chip->irq.need_valid_mask = true;
169
-
170
- ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL);
171
- if (ret) {
172
- dev_err(dev, "Error adding gpio chip: %d\n", ret);
173
- return ret;
174
- }
175
-
176
- bitmap_clear(chip->irq.valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
201
+ chip->irq.init_valid_mask = int0002_init_irq_valid_mask;
177202
178203 /*
179
- * We manually request the irq here instead of passing a flow-handler
204
+ * We directly request the irq here instead of passing a flow-handler
180205 * to gpiochip_set_chained_irqchip, because the irq is shared.
206
+ * FIXME: augment this if we managed to pull handling of shared
207
+ * IRQs into gpiolib.
181208 */
182209 ret = devm_request_irq(dev, irq, int0002_irq,
183210 IRQF_SHARED, "INT0002", chip);
....@@ -186,17 +213,63 @@
186213 return ret;
187214 }
188215
189
- ret = gpiochip_irqchip_add(chip, &int0002_irqchip, 0, handle_edge_irq,
190
- IRQ_TYPE_NONE);
216
+ girq = &chip->irq;
217
+ girq->chip = &int0002_irqchip;
218
+ /* This let us handle the parent IRQ in the driver */
219
+ girq->parent_handler = NULL;
220
+ girq->num_parents = 0;
221
+ girq->parents = NULL;
222
+ girq->default_type = IRQ_TYPE_NONE;
223
+ girq->handler = handle_edge_irq;
224
+
225
+ ret = devm_gpiochip_add_data(dev, chip, NULL);
191226 if (ret) {
192
- dev_err(dev, "Error adding irqchip: %d\n", ret);
227
+ dev_err(dev, "Error adding gpio chip: %d\n", ret);
193228 return ret;
194229 }
195230
196
- gpiochip_set_chained_irqchip(chip, &int0002_irqchip, irq, NULL);
231
+ acpi_register_wakeup_handler(irq, int0002_check_wake, NULL);
232
+ device_init_wakeup(dev, true);
233
+ dev_set_drvdata(dev, int0002);
234
+ return 0;
235
+}
236
+
237
+static int int0002_remove(struct platform_device *pdev)
238
+{
239
+ device_init_wakeup(&pdev->dev, false);
240
+ acpi_unregister_wakeup_handler(int0002_check_wake, NULL);
241
+ return 0;
242
+}
243
+
244
+static int int0002_suspend(struct device *dev)
245
+{
246
+ struct int0002_data *int0002 = dev_get_drvdata(dev);
247
+
248
+ /*
249
+ * The INT0002 parent IRQ is often shared with the ACPI GPE IRQ, don't
250
+ * muck with it when firmware based suspend is used, otherwise we may
251
+ * cause spurious wakeups from firmware managed suspend.
252
+ */
253
+ if (!pm_suspend_via_firmware() && int0002->wake_enable_count)
254
+ enable_irq_wake(int0002->parent_irq);
197255
198256 return 0;
199257 }
258
+
259
+static int int0002_resume(struct device *dev)
260
+{
261
+ struct int0002_data *int0002 = dev_get_drvdata(dev);
262
+
263
+ if (!pm_suspend_via_firmware() && int0002->wake_enable_count)
264
+ disable_irq_wake(int0002->parent_irq);
265
+
266
+ return 0;
267
+}
268
+
269
+static const struct dev_pm_ops int0002_pm_ops = {
270
+ .suspend = int0002_suspend,
271
+ .resume = int0002_resume,
272
+};
200273
201274 static const struct acpi_device_id int0002_acpi_ids[] = {
202275 { "INT0002", 0 },
....@@ -208,12 +281,14 @@
208281 .driver = {
209282 .name = DRV_NAME,
210283 .acpi_match_table = int0002_acpi_ids,
284
+ .pm = &int0002_pm_ops,
211285 },
212286 .probe = int0002_probe,
287
+ .remove = int0002_remove,
213288 };
214289
215290 module_platform_driver(int0002_driver);
216291
217292 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
218293 MODULE_DESCRIPTION("Intel INT0002 Virtual GPIO driver");
219
-MODULE_LICENSE("GPL");
294
+MODULE_LICENSE("GPL v2");