1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * GPIO interface for Intel Poulsbo SCH |
4 | * |
5 | * Copyright (c) 2010 CompuLab Ltd |
6 | * Author: Denis Turischev <denis@compulab.co.il> |
7 | */ |
8 | |
9 | #include <linux/acpi.h> |
10 | #include <linux/bitops.h> |
11 | #include <linux/errno.h> |
12 | #include <linux/gpio/driver.h> |
13 | #include <linux/io.h> |
14 | #include <linux/irq.h> |
15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> |
17 | #include <linux/pci_ids.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/types.h> |
20 | |
21 | #define GEN 0x00 |
22 | #define GIO 0x04 |
23 | #define GLV 0x08 |
24 | #define GTPE 0x0c |
25 | #define GTNE 0x10 |
26 | #define GGPE 0x14 |
27 | #define GSMI 0x18 |
28 | #define GTS 0x1c |
29 | |
30 | #define CORE_BANK_OFFSET 0x00 |
31 | #define RESUME_BANK_OFFSET 0x20 |
32 | |
33 | /* |
34 | * iLB datasheet describes GPE0BLK registers, in particular GPE0E.GPIO bit. |
35 | * Document Number: 328195-001 |
36 | */ |
37 | #define GPE0E_GPIO 14 |
38 | |
39 | struct sch_gpio { |
40 | struct gpio_chip chip; |
41 | spinlock_t lock; |
42 | unsigned short iobase; |
43 | unsigned short resume_base; |
44 | |
45 | /* GPE handling */ |
46 | u32 gpe; |
47 | acpi_gpe_handler gpe_handler; |
48 | }; |
49 | |
50 | static unsigned int sch_gpio_offset(struct sch_gpio *sch, unsigned int gpio, |
51 | unsigned int reg) |
52 | { |
53 | unsigned int base = CORE_BANK_OFFSET; |
54 | |
55 | if (gpio >= sch->resume_base) { |
56 | gpio -= sch->resume_base; |
57 | base = RESUME_BANK_OFFSET; |
58 | } |
59 | |
60 | return base + reg + gpio / 8; |
61 | } |
62 | |
63 | static unsigned int sch_gpio_bit(struct sch_gpio *sch, unsigned int gpio) |
64 | { |
65 | if (gpio >= sch->resume_base) |
66 | gpio -= sch->resume_base; |
67 | return gpio % 8; |
68 | } |
69 | |
70 | static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned int gpio, unsigned int reg) |
71 | { |
72 | unsigned short offset, bit; |
73 | u8 reg_val; |
74 | |
75 | offset = sch_gpio_offset(sch, gpio, reg); |
76 | bit = sch_gpio_bit(sch, gpio); |
77 | |
78 | reg_val = !!(inb(port: sch->iobase + offset) & BIT(bit)); |
79 | |
80 | return reg_val; |
81 | } |
82 | |
83 | static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned int gpio, unsigned int reg, |
84 | int val) |
85 | { |
86 | unsigned short offset, bit; |
87 | u8 reg_val; |
88 | |
89 | offset = sch_gpio_offset(sch, gpio, reg); |
90 | bit = sch_gpio_bit(sch, gpio); |
91 | |
92 | reg_val = inb(port: sch->iobase + offset); |
93 | |
94 | if (val) |
95 | outb(value: reg_val | BIT(bit), port: sch->iobase + offset); |
96 | else |
97 | outb(value: (reg_val & ~BIT(bit)), port: sch->iobase + offset); |
98 | } |
99 | |
100 | static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num) |
101 | { |
102 | struct sch_gpio *sch = gpiochip_get_data(gc); |
103 | unsigned long flags; |
104 | |
105 | spin_lock_irqsave(&sch->lock, flags); |
106 | sch_gpio_reg_set(sch, gpio: gpio_num, GIO, val: 1); |
107 | spin_unlock_irqrestore(lock: &sch->lock, flags); |
108 | return 0; |
109 | } |
110 | |
111 | static int sch_gpio_get(struct gpio_chip *gc, unsigned int gpio_num) |
112 | { |
113 | struct sch_gpio *sch = gpiochip_get_data(gc); |
114 | |
115 | return sch_gpio_reg_get(sch, gpio: gpio_num, GLV); |
116 | } |
117 | |
118 | static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val) |
119 | { |
120 | struct sch_gpio *sch = gpiochip_get_data(gc); |
121 | unsigned long flags; |
122 | |
123 | spin_lock_irqsave(&sch->lock, flags); |
124 | sch_gpio_reg_set(sch, gpio: gpio_num, GLV, val); |
125 | spin_unlock_irqrestore(lock: &sch->lock, flags); |
126 | } |
127 | |
128 | static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num, |
129 | int val) |
130 | { |
131 | struct sch_gpio *sch = gpiochip_get_data(gc); |
132 | unsigned long flags; |
133 | |
134 | spin_lock_irqsave(&sch->lock, flags); |
135 | sch_gpio_reg_set(sch, gpio: gpio_num, GIO, val: 0); |
136 | spin_unlock_irqrestore(lock: &sch->lock, flags); |
137 | |
138 | /* |
139 | * according to the datasheet, writing to the level register has no |
140 | * effect when GPIO is programmed as input. |
141 | * Actually the level register is read-only when configured as input. |
142 | * Thus presetting the output level before switching to output is _NOT_ possible. |
143 | * Hence we set the level after configuring the GPIO as output. |
144 | * But we cannot prevent a short low pulse if direction is set to high |
145 | * and an external pull-up is connected. |
146 | */ |
147 | sch_gpio_set(gc, gpio_num, val); |
148 | return 0; |
149 | } |
150 | |
151 | static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio_num) |
152 | { |
153 | struct sch_gpio *sch = gpiochip_get_data(gc); |
154 | |
155 | if (sch_gpio_reg_get(sch, gpio: gpio_num, GIO)) |
156 | return GPIO_LINE_DIRECTION_IN; |
157 | |
158 | return GPIO_LINE_DIRECTION_OUT; |
159 | } |
160 | |
161 | static const struct gpio_chip sch_gpio_chip = { |
162 | .label = "sch_gpio" , |
163 | .owner = THIS_MODULE, |
164 | .direction_input = sch_gpio_direction_in, |
165 | .get = sch_gpio_get, |
166 | .direction_output = sch_gpio_direction_out, |
167 | .set = sch_gpio_set, |
168 | .get_direction = sch_gpio_get_direction, |
169 | }; |
170 | |
171 | static int sch_irq_type(struct irq_data *d, unsigned int type) |
172 | { |
173 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
174 | struct sch_gpio *sch = gpiochip_get_data(gc); |
175 | irq_hw_number_t gpio_num = irqd_to_hwirq(d); |
176 | unsigned long flags; |
177 | int rising, falling; |
178 | |
179 | switch (type & IRQ_TYPE_SENSE_MASK) { |
180 | case IRQ_TYPE_EDGE_RISING: |
181 | rising = 1; |
182 | falling = 0; |
183 | break; |
184 | case IRQ_TYPE_EDGE_FALLING: |
185 | rising = 0; |
186 | falling = 1; |
187 | break; |
188 | case IRQ_TYPE_EDGE_BOTH: |
189 | rising = 1; |
190 | falling = 1; |
191 | break; |
192 | default: |
193 | return -EINVAL; |
194 | } |
195 | |
196 | spin_lock_irqsave(&sch->lock, flags); |
197 | |
198 | sch_gpio_reg_set(sch, gpio: gpio_num, GTPE, val: rising); |
199 | sch_gpio_reg_set(sch, gpio: gpio_num, GTNE, val: falling); |
200 | |
201 | irq_set_handler_locked(data: d, handler: handle_edge_irq); |
202 | |
203 | spin_unlock_irqrestore(lock: &sch->lock, flags); |
204 | |
205 | return 0; |
206 | } |
207 | |
208 | static void sch_irq_ack(struct irq_data *d) |
209 | { |
210 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
211 | struct sch_gpio *sch = gpiochip_get_data(gc); |
212 | irq_hw_number_t gpio_num = irqd_to_hwirq(d); |
213 | unsigned long flags; |
214 | |
215 | spin_lock_irqsave(&sch->lock, flags); |
216 | sch_gpio_reg_set(sch, gpio: gpio_num, GTS, val: 1); |
217 | spin_unlock_irqrestore(lock: &sch->lock, flags); |
218 | } |
219 | |
220 | static void sch_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t gpio_num, int val) |
221 | { |
222 | struct sch_gpio *sch = gpiochip_get_data(gc); |
223 | unsigned long flags; |
224 | |
225 | spin_lock_irqsave(&sch->lock, flags); |
226 | sch_gpio_reg_set(sch, gpio: gpio_num, GGPE, val); |
227 | spin_unlock_irqrestore(lock: &sch->lock, flags); |
228 | } |
229 | |
230 | static void sch_irq_mask(struct irq_data *d) |
231 | { |
232 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
233 | irq_hw_number_t gpio_num = irqd_to_hwirq(d); |
234 | |
235 | sch_irq_mask_unmask(gc, gpio_num, val: 0); |
236 | gpiochip_disable_irq(gc, offset: gpio_num); |
237 | } |
238 | |
239 | static void sch_irq_unmask(struct irq_data *d) |
240 | { |
241 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
242 | irq_hw_number_t gpio_num = irqd_to_hwirq(d); |
243 | |
244 | gpiochip_enable_irq(gc, offset: gpio_num); |
245 | sch_irq_mask_unmask(gc, gpio_num, val: 1); |
246 | } |
247 | |
248 | static const struct irq_chip sch_irqchip = { |
249 | .name = "sch_gpio" , |
250 | .irq_ack = sch_irq_ack, |
251 | .irq_mask = sch_irq_mask, |
252 | .irq_unmask = sch_irq_unmask, |
253 | .irq_set_type = sch_irq_type, |
254 | .flags = IRQCHIP_IMMUTABLE, |
255 | GPIOCHIP_IRQ_RESOURCE_HELPERS, |
256 | }; |
257 | |
258 | static u32 sch_gpio_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context) |
259 | { |
260 | struct sch_gpio *sch = context; |
261 | struct gpio_chip *gc = &sch->chip; |
262 | unsigned long core_status, resume_status; |
263 | unsigned long pending; |
264 | unsigned long flags; |
265 | int offset; |
266 | u32 ret; |
267 | |
268 | spin_lock_irqsave(&sch->lock, flags); |
269 | |
270 | core_status = inl(port: sch->iobase + CORE_BANK_OFFSET + GTS); |
271 | resume_status = inl(port: sch->iobase + RESUME_BANK_OFFSET + GTS); |
272 | |
273 | spin_unlock_irqrestore(lock: &sch->lock, flags); |
274 | |
275 | pending = (resume_status << sch->resume_base) | core_status; |
276 | for_each_set_bit(offset, &pending, sch->chip.ngpio) |
277 | generic_handle_domain_irq(domain: gc->irq.domain, hwirq: offset); |
278 | |
279 | /* Set returning value depending on whether we handled an interrupt */ |
280 | ret = pending ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
281 | |
282 | /* Acknowledge GPE to ACPICA */ |
283 | ret |= ACPI_REENABLE_GPE; |
284 | |
285 | return ret; |
286 | } |
287 | |
288 | static void sch_gpio_remove_gpe_handler(void *data) |
289 | { |
290 | struct sch_gpio *sch = data; |
291 | |
292 | acpi_disable_gpe(NULL, gpe_number: sch->gpe); |
293 | acpi_remove_gpe_handler(NULL, gpe_number: sch->gpe, address: sch->gpe_handler); |
294 | } |
295 | |
296 | static int sch_gpio_install_gpe_handler(struct sch_gpio *sch) |
297 | { |
298 | struct device *dev = sch->chip.parent; |
299 | acpi_status status; |
300 | |
301 | status = acpi_install_gpe_handler(NULL, gpe_number: sch->gpe, ACPI_GPE_LEVEL_TRIGGERED, |
302 | address: sch->gpe_handler, context: sch); |
303 | if (ACPI_FAILURE(status)) { |
304 | dev_err(dev, "Failed to install GPE handler for %u: %s\n" , |
305 | sch->gpe, acpi_format_exception(status)); |
306 | return -ENODEV; |
307 | } |
308 | |
309 | status = acpi_enable_gpe(NULL, gpe_number: sch->gpe); |
310 | if (ACPI_FAILURE(status)) { |
311 | dev_err(dev, "Failed to enable GPE handler for %u: %s\n" , |
312 | sch->gpe, acpi_format_exception(status)); |
313 | acpi_remove_gpe_handler(NULL, gpe_number: sch->gpe, address: sch->gpe_handler); |
314 | return -ENODEV; |
315 | } |
316 | |
317 | return devm_add_action_or_reset(dev, sch_gpio_remove_gpe_handler, sch); |
318 | } |
319 | |
320 | static int sch_gpio_probe(struct platform_device *pdev) |
321 | { |
322 | struct gpio_irq_chip *girq; |
323 | struct sch_gpio *sch; |
324 | struct resource *res; |
325 | int ret; |
326 | |
327 | sch = devm_kzalloc(dev: &pdev->dev, size: sizeof(*sch), GFP_KERNEL); |
328 | if (!sch) |
329 | return -ENOMEM; |
330 | |
331 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
332 | if (!res) |
333 | return -EBUSY; |
334 | |
335 | if (!devm_request_region(&pdev->dev, res->start, resource_size(res), |
336 | pdev->name)) |
337 | return -EBUSY; |
338 | |
339 | spin_lock_init(&sch->lock); |
340 | sch->iobase = res->start; |
341 | sch->chip = sch_gpio_chip; |
342 | sch->chip.label = dev_name(dev: &pdev->dev); |
343 | sch->chip.parent = &pdev->dev; |
344 | |
345 | switch (pdev->id) { |
346 | case PCI_DEVICE_ID_INTEL_SCH_LPC: |
347 | sch->resume_base = 10; |
348 | sch->chip.ngpio = 14; |
349 | |
350 | /* |
351 | * GPIO[6:0] enabled by default |
352 | * GPIO7 is configured by the CMC as SLPIOVR |
353 | * Enable GPIO[9:8] core powered gpios explicitly |
354 | */ |
355 | sch_gpio_reg_set(sch, gpio: 8, GEN, val: 1); |
356 | sch_gpio_reg_set(sch, gpio: 9, GEN, val: 1); |
357 | /* |
358 | * SUS_GPIO[2:0] enabled by default |
359 | * Enable SUS_GPIO3 resume powered gpio explicitly |
360 | */ |
361 | sch_gpio_reg_set(sch, gpio: 13, GEN, val: 1); |
362 | break; |
363 | |
364 | case PCI_DEVICE_ID_INTEL_ITC_LPC: |
365 | sch->resume_base = 5; |
366 | sch->chip.ngpio = 14; |
367 | break; |
368 | |
369 | case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: |
370 | sch->resume_base = 21; |
371 | sch->chip.ngpio = 30; |
372 | break; |
373 | |
374 | case PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB: |
375 | sch->resume_base = 2; |
376 | sch->chip.ngpio = 8; |
377 | break; |
378 | |
379 | default: |
380 | return -ENODEV; |
381 | } |
382 | |
383 | girq = &sch->chip.irq; |
384 | gpio_irq_chip_set_chip(girq, chip: &sch_irqchip); |
385 | girq->num_parents = 0; |
386 | girq->parents = NULL; |
387 | girq->parent_handler = NULL; |
388 | girq->default_type = IRQ_TYPE_NONE; |
389 | girq->handler = handle_bad_irq; |
390 | |
391 | /* GPE setup is optional */ |
392 | sch->gpe = GPE0E_GPIO; |
393 | sch->gpe_handler = sch_gpio_gpe_handler; |
394 | |
395 | ret = sch_gpio_install_gpe_handler(sch); |
396 | if (ret) |
397 | dev_warn(&pdev->dev, "Can't setup GPE, no IRQ support\n" ); |
398 | |
399 | return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch); |
400 | } |
401 | |
402 | static struct platform_driver sch_gpio_driver = { |
403 | .driver = { |
404 | .name = "sch_gpio" , |
405 | }, |
406 | .probe = sch_gpio_probe, |
407 | }; |
408 | |
409 | module_platform_driver(sch_gpio_driver); |
410 | |
411 | MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>" ); |
412 | MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH" ); |
413 | MODULE_LICENSE("GPL v2" ); |
414 | MODULE_ALIAS("platform:sch_gpio" ); |
415 | |