aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>2011-07-20 20:19:59 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-10-05 13:59:17 -0400
commit38eb18a6f92da886fc1af509d25e8f7a49e23d9a (patch)
tree9aef6a3da385b91f0b690b3646257249da6d30a5 /drivers/gpio
parente98bed7f0fa847492db8316db4605f2681f39868 (diff)
gpio-pch: Support interrupt function
Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig1
-rw-r--r--drivers/gpio/gpio-pch.c187
2 files changed, 188 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 04499c19e986..de5fea60b385 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -388,6 +388,7 @@ config GPIO_LANGWELL
388config GPIO_PCH 388config GPIO_PCH
389 tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO" 389 tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
390 depends on PCI && X86 390 depends on PCI && X86
391 select GENERIC_IRQ_CHIP
391 help 392 help
392 This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff 393 This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
393 which is an IOH(Input/Output Hub) for x86 embedded processor. 394 which is an IOH(Input/Output Hub) for x86 embedded processor.
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 7f773afeb340..46b5209878f6 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -17,6 +17,17 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/pci.h> 18#include <linux/pci.h>
19#include <linux/gpio.h> 19#include <linux/gpio.h>
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22
23#define PCH_EDGE_FALLING 0
24#define PCH_EDGE_RISING BIT(0)
25#define PCH_LEVEL_L BIT(1)
26#define PCH_LEVEL_H (BIT(0) | BIT(1))
27#define PCH_EDGE_BOTH BIT(2)
28#define PCH_IM_MASK (BIT(0) | BIT(1) | BIT(2))
29
30#define PCH_IRQ_BASE 24
20 31
21struct pch_regs { 32struct pch_regs {
22 u32 ien; 33 u32 ien;
@@ -50,6 +61,8 @@ static int gpio_pins[] = {
50 61
51/** 62/**
52 * struct pch_gpio_reg_data - The register store data. 63 * struct pch_gpio_reg_data - The register store data.
64 * @ien_reg: To store contents of IEN register.
65 * @imask_reg: To store contents of IMASK register.
53 * @po_reg: To store contents of PO register. 66 * @po_reg: To store contents of PO register.
54 * @pm_reg: To store contents of PM register. 67 * @pm_reg: To store contents of PM register.
55 * @im0_reg: To store contents of IM0 register. 68 * @im0_reg: To store contents of IM0 register.
@@ -58,6 +71,8 @@ static int gpio_pins[] = {
58 * (Only ML7223 Bus-n) 71 * (Only ML7223 Bus-n)
59 */ 72 */
60struct pch_gpio_reg_data { 73struct pch_gpio_reg_data {
74 u32 ien_reg;
75 u32 imask_reg;
61 u32 po_reg; 76 u32 po_reg;
62 u32 pm_reg; 77 u32 pm_reg;
63 u32 im0_reg; 78 u32 im0_reg;
@@ -73,6 +88,8 @@ struct pch_gpio_reg_data {
73 * @gpio: Data for GPIO infrastructure. 88 * @gpio: Data for GPIO infrastructure.
74 * @pch_gpio_reg: Memory mapped Register data is saved here 89 * @pch_gpio_reg: Memory mapped Register data is saved here
75 * when suspend. 90 * when suspend.
91 * @lock: Used for register access protection
92 * @irq_base: Save base of IRQ number for interrupt
76 * @ioh: IOH ID 93 * @ioh: IOH ID
77 * @spinlock: Used for register access protection in 94 * @spinlock: Used for register access protection in
78 * interrupt context pch_irq_mask, 95 * interrupt context pch_irq_mask,
@@ -85,6 +102,7 @@ struct pch_gpio {
85 struct gpio_chip gpio; 102 struct gpio_chip gpio;
86 struct pch_gpio_reg_data pch_gpio_reg; 103 struct pch_gpio_reg_data pch_gpio_reg;
87 struct mutex lock; 104 struct mutex lock;
105 int irq_base;
88 enum pch_type_t ioh; 106 enum pch_type_t ioh;
89 spinlock_t spinlock; 107 spinlock_t spinlock;
90}; 108};
@@ -155,6 +173,8 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
155 */ 173 */
156static void pch_gpio_save_reg_conf(struct pch_gpio *chip) 174static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
157{ 175{
176 chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
177 chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
158 chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po); 178 chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
159 chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm); 179 chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
160 chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0); 180 chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
@@ -170,6 +190,8 @@ static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
170 */ 190 */
171static void pch_gpio_restore_reg_conf(struct pch_gpio *chip) 191static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
172{ 192{
193 iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
194 iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
173 /* to store contents of PO register */ 195 /* to store contents of PO register */
174 iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po); 196 iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
175 /* to store contents of PM register */ 197 /* to store contents of PM register */
@@ -182,6 +204,12 @@ static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
182 &chip->reg->gpio_use_sel); 204 &chip->reg->gpio_use_sel);
183} 205}
184 206
207static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
208{
209 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
210 return chip->irq_base + offset;
211}
212
185static void pch_gpio_setup(struct pch_gpio *chip) 213static void pch_gpio_setup(struct pch_gpio *chip)
186{ 214{
187 struct gpio_chip *gpio = &chip->gpio; 215 struct gpio_chip *gpio = &chip->gpio;
@@ -196,6 +224,130 @@ static void pch_gpio_setup(struct pch_gpio *chip)
196 gpio->base = -1; 224 gpio->base = -1;
197 gpio->ngpio = gpio_pins[chip->ioh]; 225 gpio->ngpio = gpio_pins[chip->ioh];
198 gpio->can_sleep = 0; 226 gpio->can_sleep = 0;
227 gpio->to_irq = pch_gpio_to_irq;
228}
229
230static int pch_irq_type(struct irq_data *d, unsigned int type)
231{
232 u32 im;
233 u32 *im_reg;
234 u32 ien;
235 u32 im_pos;
236 int ch;
237 unsigned long flags;
238 u32 val;
239 int irq = d->irq;
240 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
241 struct pch_gpio *chip = gc->private;
242
243 ch = irq - chip->irq_base;
244 if (irq <= chip->irq_base + 7) {
245 im_reg = &chip->reg->im0;
246 im_pos = ch;
247 } else {
248 im_reg = &chip->reg->im1;
249 im_pos = ch - 8;
250 }
251 dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n",
252 __func__, irq, type, ch, im_pos);
253
254 spin_lock_irqsave(&chip->spinlock, flags);
255
256 switch (type) {
257 case IRQ_TYPE_EDGE_RISING:
258 val = PCH_EDGE_RISING;
259 break;
260 case IRQ_TYPE_EDGE_FALLING:
261 val = PCH_EDGE_FALLING;
262 break;
263 case IRQ_TYPE_EDGE_BOTH:
264 val = PCH_EDGE_BOTH;
265 break;
266 case IRQ_TYPE_LEVEL_HIGH:
267 val = PCH_LEVEL_H;
268 break;
269 case IRQ_TYPE_LEVEL_LOW:
270 val = PCH_LEVEL_L;
271 break;
272 case IRQ_TYPE_PROBE:
273 goto end;
274 default:
275 dev_warn(chip->dev, "%s: unknown type(%dd)",
276 __func__, type);
277 goto end;
278 }
279
280 /* Set interrupt mode */
281 im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
282 iowrite32(im | (val << (im_pos * 4)), im_reg);
283
284 /* iclr */
285 iowrite32(BIT(ch), &chip->reg->iclr);
286
287 /* IMASKCLR */
288 iowrite32(BIT(ch), &chip->reg->imaskclr);
289
290 /* Enable interrupt */
291 ien = ioread32(&chip->reg->ien);
292 iowrite32(ien | BIT(ch), &chip->reg->ien);
293end:
294 spin_unlock_irqrestore(&chip->spinlock, flags);
295
296 return 0;
297}
298
299static void pch_irq_unmask(struct irq_data *d)
300{
301 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
302 struct pch_gpio *chip = gc->private;
303
304 iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr);
305}
306
307static void pch_irq_mask(struct irq_data *d)
308{
309 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
310 struct pch_gpio *chip = gc->private;
311
312 iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask);
313}
314
315static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
316{
317 struct pch_gpio *chip = dev_id;
318 u32 reg_val = ioread32(&chip->reg->istatus);
319 int i;
320 int ret = IRQ_NONE;
321
322 for (i = 0; i < gpio_pins[chip->ioh]; i++) {
323 if (reg_val & BIT(i)) {
324 dev_dbg(chip->dev, "%s:[%d]:irq=%d status=0x%x\n",
325 __func__, i, irq, reg_val);
326 iowrite32(BIT(i), &chip->reg->iclr);
327 generic_handle_irq(chip->irq_base + i);
328 ret = IRQ_HANDLED;
329 }
330 }
331 return ret;
332}
333
334static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
335 unsigned int irq_start, unsigned int num)
336{
337 struct irq_chip_generic *gc;
338 struct irq_chip_type *ct;
339
340 gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base,
341 handle_simple_irq);
342 gc->private = chip;
343 ct = gc->chip_types;
344
345 ct->chip.irq_mask = pch_irq_mask;
346 ct->chip.irq_unmask = pch_irq_unmask;
347 ct->chip.irq_set_type = pch_irq_type;
348
349 irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
350 IRQ_NOREQUEST | IRQ_NOPROBE, 0);
199} 351}
200 352
201static int __devinit pch_gpio_probe(struct pci_dev *pdev, 353static int __devinit pch_gpio_probe(struct pci_dev *pdev,
@@ -203,6 +355,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
203{ 355{
204 s32 ret; 356 s32 ret;
205 struct pch_gpio *chip; 357 struct pch_gpio *chip;
358 int irq_base;
206 359
207 chip = kzalloc(sizeof(*chip), GFP_KERNEL); 360 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
208 if (chip == NULL) 361 if (chip == NULL)
@@ -245,8 +398,36 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
245 goto err_gpiochip_add; 398 goto err_gpiochip_add;
246 } 399 }
247 400
401 irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], GFP_KERNEL);
402 if (irq_base < 0) {
403 dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
404 chip->irq_base = -1;
405 goto end;
406 }
407 chip->irq_base = irq_base;
408
409 ret = request_irq(pdev->irq, pch_gpio_handler,
410 IRQF_SHARED, KBUILD_MODNAME, chip);
411 if (ret != 0) {
412 dev_err(&pdev->dev,
413 "%s request_irq failed\n", __func__);
414 goto err_request_irq;
415 }
416
417 pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
418
419 /* Initialize interrupt ien register */
420 iowrite32(0, &chip->reg->ien);
421end:
248 return 0; 422 return 0;
249 423
424err_request_irq:
425 irq_free_descs(irq_base, gpio_pins[chip->ioh]);
426
427 ret = gpiochip_remove(&chip->gpio);
428 if (ret)
429 dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
430
250err_gpiochip_add: 431err_gpiochip_add:
251 pci_iounmap(pdev, chip->base); 432 pci_iounmap(pdev, chip->base);
252 433
@@ -267,6 +448,12 @@ static void __devexit pch_gpio_remove(struct pci_dev *pdev)
267 int err; 448 int err;
268 struct pch_gpio *chip = pci_get_drvdata(pdev); 449 struct pch_gpio *chip = pci_get_drvdata(pdev);
269 450
451 if (chip->irq_base != -1) {
452 free_irq(pdev->irq, chip);
453
454 irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
455 }
456
270 err = gpiochip_remove(&chip->gpio); 457 err = gpiochip_remove(&chip->gpio);
271 if (err) 458 if (err)
272 dev_err(&pdev->dev, "Failed gpiochip_remove\n"); 459 dev_err(&pdev->dev, "Failed gpiochip_remove\n");