Commit | Line | Data |
---|---|---|
8f710b5f | 1 | // SPDX-License-Identifier: GPL-2.0 |
25cf2507 MN |
2 | /* |
3 | * Intel Medfield MSIC GPIO driver> | |
4 | * Copyright (c) 2011, Intel Corporation. | |
5 | * | |
6 | * Author: Mathias Nyman <mathias.nyman@linux.intel.com> | |
7 | * Based on intel_pmic_gpio.c | |
25cf2507 MN |
8 | */ |
9 | ||
99ef32ad | 10 | #include <linux/gpio/driver.h> |
2456c8b8 AS |
11 | #include <linux/init.h> |
12 | #include <linux/interrupt.h> | |
13 | #include <linux/kernel.h> | |
25cf2507 | 14 | #include <linux/mfd/intel_msic.h> |
2456c8b8 AS |
15 | #include <linux/platform_device.h> |
16 | #include <linux/slab.h> | |
25cf2507 MN |
17 | |
18 | /* the offset for the mapping of global gpio pin to irq */ | |
19 | #define MSIC_GPIO_IRQ_OFFSET 0x100 | |
20 | ||
21 | #define MSIC_GPIO_DIR_IN 0 | |
22 | #define MSIC_GPIO_DIR_OUT BIT(5) | |
23 | #define MSIC_GPIO_TRIG_FALL BIT(1) | |
24 | #define MSIC_GPIO_TRIG_RISE BIT(2) | |
25 | ||
26 | /* masks for msic gpio output GPIOxxxxCTLO registers */ | |
27 | #define MSIC_GPIO_DIR_MASK BIT(5) | |
28 | #define MSIC_GPIO_DRV_MASK BIT(4) | |
29 | #define MSIC_GPIO_REN_MASK BIT(3) | |
30 | #define MSIC_GPIO_RVAL_MASK (BIT(2) | BIT(1)) | |
31 | #define MSIC_GPIO_DOUT_MASK BIT(0) | |
32 | ||
33 | /* masks for msic gpio input GPIOxxxxCTLI registers */ | |
34 | #define MSIC_GPIO_GLBYP_MASK BIT(5) | |
35 | #define MSIC_GPIO_DBNC_MASK (BIT(4) | BIT(3)) | |
36 | #define MSIC_GPIO_INTCNT_MASK (BIT(2) | BIT(1)) | |
37 | #define MSIC_GPIO_DIN_MASK BIT(0) | |
38 | ||
39 | #define MSIC_NUM_GPIO 24 | |
40 | ||
41 | struct msic_gpio { | |
42 | struct platform_device *pdev; | |
43 | struct mutex buslock; | |
44 | struct gpio_chip chip; | |
45 | int irq; | |
46 | unsigned irq_base; | |
47 | unsigned long trig_change_mask; | |
48 | unsigned trig_type; | |
49 | }; | |
50 | ||
51 | /* | |
52 | * MSIC has 24 gpios, 16 low voltage (1.2-1.8v) and 8 high voltage (3v). | |
53 | * Both the high and low voltage gpios are divided in two banks. | |
54 | * GPIOs are numbered with GPIO0LV0 as gpio_base in the following order: | |
55 | * GPIO0LV0..GPIO0LV7: low voltage, bank 0, gpio_base | |
56 | * GPIO1LV0..GPIO1LV7: low voltage, bank 1, gpio_base + 8 | |
57 | * GPIO0HV0..GPIO0HV3: high voltage, bank 0, gpio_base + 16 | |
58 | * GPIO1HV0..GPIO1HV3: high voltage, bank 1, gpio_base + 20 | |
59 | */ | |
60 | ||
61 | static int msic_gpio_to_ireg(unsigned offset) | |
62 | { | |
63 | if (offset >= MSIC_NUM_GPIO) | |
64 | return -EINVAL; | |
65 | ||
66 | if (offset < 8) | |
67 | return INTEL_MSIC_GPIO0LV0CTLI - offset; | |
68 | if (offset < 16) | |
69 | return INTEL_MSIC_GPIO1LV0CTLI - offset + 8; | |
70 | if (offset < 20) | |
71 | return INTEL_MSIC_GPIO0HV0CTLI - offset + 16; | |
72 | ||
73 | return INTEL_MSIC_GPIO1HV0CTLI - offset + 20; | |
74 | } | |
75 | ||
76 | static int msic_gpio_to_oreg(unsigned offset) | |
77 | { | |
78 | if (offset >= MSIC_NUM_GPIO) | |
79 | return -EINVAL; | |
80 | ||
81 | if (offset < 8) | |
82 | return INTEL_MSIC_GPIO0LV0CTLO - offset; | |
83 | if (offset < 16) | |
84 | return INTEL_MSIC_GPIO1LV0CTLO - offset + 8; | |
85 | if (offset < 20) | |
86 | return INTEL_MSIC_GPIO0HV0CTLO - offset + 16; | |
87 | ||
f7da0bdb | 88 | return INTEL_MSIC_GPIO1HV0CTLO - offset + 20; |
25cf2507 MN |
89 | } |
90 | ||
91 | static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | |
92 | { | |
93 | int reg; | |
94 | ||
95 | reg = msic_gpio_to_oreg(offset); | |
96 | if (reg < 0) | |
97 | return reg; | |
98 | ||
99 | return intel_msic_reg_update(reg, MSIC_GPIO_DIR_IN, MSIC_GPIO_DIR_MASK); | |
100 | } | |
101 | ||
102 | static int msic_gpio_direction_output(struct gpio_chip *chip, | |
103 | unsigned offset, int value) | |
104 | { | |
105 | int reg; | |
106 | unsigned mask; | |
107 | ||
108 | value = (!!value) | MSIC_GPIO_DIR_OUT; | |
109 | mask = MSIC_GPIO_DIR_MASK | MSIC_GPIO_DOUT_MASK; | |
110 | ||
111 | reg = msic_gpio_to_oreg(offset); | |
112 | if (reg < 0) | |
113 | return reg; | |
114 | ||
115 | return intel_msic_reg_update(reg, value, mask); | |
116 | } | |
117 | ||
118 | static int msic_gpio_get(struct gpio_chip *chip, unsigned offset) | |
119 | { | |
120 | u8 r; | |
121 | int ret; | |
122 | int reg; | |
123 | ||
124 | reg = msic_gpio_to_ireg(offset); | |
125 | if (reg < 0) | |
126 | return reg; | |
127 | ||
128 | ret = intel_msic_reg_read(reg, &r); | |
129 | if (ret < 0) | |
130 | return ret; | |
131 | ||
db30aaef | 132 | return !!(r & MSIC_GPIO_DIN_MASK); |
25cf2507 MN |
133 | } |
134 | ||
135 | static void msic_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |
136 | { | |
137 | int reg; | |
138 | ||
139 | reg = msic_gpio_to_oreg(offset); | |
140 | if (reg < 0) | |
141 | return; | |
142 | ||
143 | intel_msic_reg_update(reg, !!value , MSIC_GPIO_DOUT_MASK); | |
144 | } | |
145 | ||
146 | /* | |
147 | * This is called from genirq with mg->buslock locked and | |
148 | * irq_desc->lock held. We can not access the scu bus here, so we | |
149 | * store the change and update in the bus_sync_unlock() function below | |
150 | */ | |
151 | static int msic_irq_type(struct irq_data *data, unsigned type) | |
152 | { | |
153 | struct msic_gpio *mg = irq_data_get_irq_chip_data(data); | |
154 | u32 gpio = data->irq - mg->irq_base; | |
155 | ||
156 | if (gpio >= mg->chip.ngpio) | |
157 | return -EINVAL; | |
158 | ||
159 | /* mark for which gpio the trigger changed, protected by buslock */ | |
160 | mg->trig_change_mask |= (1 << gpio); | |
161 | mg->trig_type = type; | |
162 | ||
163 | return 0; | |
164 | } | |
165 | ||
166 | static int msic_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |
167 | { | |
a772a26d | 168 | struct msic_gpio *mg = gpiochip_get_data(chip); |
25cf2507 MN |
169 | return mg->irq_base + offset; |
170 | } | |
171 | ||
172 | static void msic_bus_lock(struct irq_data *data) | |
173 | { | |
174 | struct msic_gpio *mg = irq_data_get_irq_chip_data(data); | |
175 | mutex_lock(&mg->buslock); | |
176 | } | |
177 | ||
178 | static void msic_bus_sync_unlock(struct irq_data *data) | |
179 | { | |
180 | struct msic_gpio *mg = irq_data_get_irq_chip_data(data); | |
181 | int offset; | |
182 | int reg; | |
183 | u8 trig = 0; | |
184 | ||
185 | /* We can only get one change at a time as the buslock covers the | |
186 | entire transaction. The irq_desc->lock is dropped before we are | |
187 | called but that is fine */ | |
188 | if (mg->trig_change_mask) { | |
189 | offset = __ffs(mg->trig_change_mask); | |
190 | ||
191 | reg = msic_gpio_to_ireg(offset); | |
192 | if (reg < 0) | |
193 | goto out; | |
194 | ||
195 | if (mg->trig_type & IRQ_TYPE_EDGE_RISING) | |
196 | trig |= MSIC_GPIO_TRIG_RISE; | |
197 | if (mg->trig_type & IRQ_TYPE_EDGE_FALLING) | |
198 | trig |= MSIC_GPIO_TRIG_FALL; | |
199 | ||
200 | intel_msic_reg_update(reg, trig, MSIC_GPIO_INTCNT_MASK); | |
201 | mg->trig_change_mask = 0; | |
202 | } | |
203 | out: | |
204 | mutex_unlock(&mg->buslock); | |
205 | } | |
206 | ||
207 | /* Firmware does all the masking and unmasking for us, no masking here. */ | |
208 | static void msic_irq_unmask(struct irq_data *data) { } | |
209 | ||
210 | static void msic_irq_mask(struct irq_data *data) { } | |
211 | ||
212 | static struct irq_chip msic_irqchip = { | |
213 | .name = "MSIC-GPIO", | |
214 | .irq_mask = msic_irq_mask, | |
215 | .irq_unmask = msic_irq_unmask, | |
216 | .irq_set_type = msic_irq_type, | |
217 | .irq_bus_lock = msic_bus_lock, | |
218 | .irq_bus_sync_unlock = msic_bus_sync_unlock, | |
219 | }; | |
220 | ||
bd0b9ac4 | 221 | static void msic_gpio_irq_handler(struct irq_desc *desc) |
25cf2507 MN |
222 | { |
223 | struct irq_data *data = irq_desc_get_irq_data(desc); | |
224 | struct msic_gpio *mg = irq_data_get_irq_handler_data(data); | |
225 | struct irq_chip *chip = irq_data_get_irq_chip(data); | |
226 | struct intel_msic *msic = pdev_to_intel_msic(mg->pdev); | |
11475754 | 227 | unsigned long pending; |
25cf2507 MN |
228 | int i; |
229 | int bitnr; | |
230 | u8 pin; | |
25cf2507 MN |
231 | |
232 | for (i = 0; i < (mg->chip.ngpio / BITS_PER_BYTE); i++) { | |
233 | intel_msic_irq_read(msic, INTEL_MSIC_GPIO0LVIRQ + i, &pin); | |
234 | pending = pin; | |
235 | ||
11475754 AS |
236 | for_each_set_bit(bitnr, &pending, BITS_PER_BYTE) |
237 | generic_handle_irq(mg->irq_base + i * BITS_PER_BYTE + bitnr); | |
25cf2507 MN |
238 | } |
239 | chip->irq_eoi(data); | |
240 | } | |
241 | ||
3836309d | 242 | static int platform_msic_gpio_probe(struct platform_device *pdev) |
25cf2507 MN |
243 | { |
244 | struct device *dev = &pdev->dev; | |
e56aee18 | 245 | struct intel_msic_gpio_pdata *pdata = dev_get_platdata(dev); |
25cf2507 MN |
246 | struct msic_gpio *mg; |
247 | int irq = platform_get_irq(pdev, 0); | |
248 | int retval; | |
249 | int i; | |
250 | ||
251 | if (irq < 0) { | |
ca1f3ae3 GS |
252 | dev_err(dev, "no IRQ line: %d\n", irq); |
253 | return irq; | |
25cf2507 MN |
254 | } |
255 | ||
256 | if (!pdata || !pdata->gpio_base) { | |
257 | dev_err(dev, "incorrect or missing platform data\n"); | |
258 | return -EINVAL; | |
259 | } | |
260 | ||
261 | mg = kzalloc(sizeof(*mg), GFP_KERNEL); | |
262 | if (!mg) | |
263 | return -ENOMEM; | |
264 | ||
265 | dev_set_drvdata(dev, mg); | |
266 | ||
267 | mg->pdev = pdev; | |
268 | mg->irq = irq; | |
269 | mg->irq_base = pdata->gpio_base + MSIC_GPIO_IRQ_OFFSET; | |
270 | mg->chip.label = "msic_gpio"; | |
271 | mg->chip.direction_input = msic_gpio_direction_input; | |
272 | mg->chip.direction_output = msic_gpio_direction_output; | |
273 | mg->chip.get = msic_gpio_get; | |
274 | mg->chip.set = msic_gpio_set; | |
275 | mg->chip.to_irq = msic_gpio_to_irq; | |
276 | mg->chip.base = pdata->gpio_base; | |
277 | mg->chip.ngpio = MSIC_NUM_GPIO; | |
9fb1f39e | 278 | mg->chip.can_sleep = true; |
58383c78 | 279 | mg->chip.parent = dev; |
25cf2507 MN |
280 | |
281 | mutex_init(&mg->buslock); | |
282 | ||
a772a26d | 283 | retval = gpiochip_add_data(&mg->chip, mg); |
25cf2507 MN |
284 | if (retval) { |
285 | dev_err(dev, "Adding MSIC gpio chip failed\n"); | |
286 | goto err; | |
287 | } | |
288 | ||
289 | for (i = 0; i < mg->chip.ngpio; i++) { | |
290 | irq_set_chip_data(i + mg->irq_base, mg); | |
e5428a68 LW |
291 | irq_set_chip_and_handler(i + mg->irq_base, |
292 | &msic_irqchip, | |
293 | handle_simple_irq); | |
25cf2507 | 294 | } |
3fb250ed | 295 | irq_set_chained_handler_and_data(mg->irq, msic_gpio_irq_handler, mg); |
25cf2507 MN |
296 | |
297 | return 0; | |
298 | err: | |
299 | kfree(mg); | |
300 | return retval; | |
301 | } | |
302 | ||
303 | static struct platform_driver platform_msic_gpio_driver = { | |
304 | .driver = { | |
305 | .name = "msic_gpio", | |
25cf2507 MN |
306 | }, |
307 | .probe = platform_msic_gpio_probe, | |
308 | }; | |
309 | ||
310 | static int __init platform_msic_gpio_init(void) | |
311 | { | |
312 | return platform_driver_register(&platform_msic_gpio_driver); | |
313 | } | |
25cf2507 | 314 | subsys_initcall(platform_msic_gpio_init); |