aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-ml-ioh.c
diff options
context:
space:
mode:
authorTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>2011-08-05 00:04:21 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-10-05 13:57:04 -0400
commit54be566317b6aece2389a95bb19ea209af9359be (patch)
treec8b89ac9809473fe2f39068e41f89a4f89fecc0b /drivers/gpio/gpio-ml-ioh.c
parent45d198c4cf3a9a751b734eb32426b6de4631ef2e (diff)
gpio-ml-ioh: 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/gpio-ml-ioh.c')
-rw-r--r--drivers/gpio/gpio-ml-ioh.c209
1 files changed, 206 insertions, 3 deletions
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 655e55c55e02..4fab37bf564d 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -18,6 +18,17 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/pci.h> 19#include <linux/pci.h>
20#include <linux/gpio.h> 20#include <linux/gpio.h>
21#include <linux/interrupt.h>
22#include <linux/irq.h>
23
24#define IOH_EDGE_FALLING 0
25#define IOH_EDGE_RISING BIT(0)
26#define IOH_LEVEL_L BIT(1)
27#define IOH_LEVEL_H (BIT(0) | BIT(1))
28#define IOH_EDGE_BOTH BIT(2)
29#define IOH_IM_MASK (BIT(0) | BIT(1) | BIT(2))
30
31#define IOH_IRQ_BASE 0
21 32
22#define PCI_VENDOR_ID_ROHM 0x10DB 33#define PCI_VENDOR_ID_ROHM 0x10DB
23 34
@@ -46,12 +57,20 @@ struct ioh_regs {
46 57
47/** 58/**
48 * struct ioh_gpio_reg_data - The register store data. 59 * struct ioh_gpio_reg_data - The register store data.
60 * @ien_reg To store contents of interrupt enable register.
61 * @imask_reg: To store contents of interrupt mask regist
49 * @po_reg: To store contents of PO register. 62 * @po_reg: To store contents of PO register.
50 * @pm_reg: To store contents of PM register. 63 * @pm_reg: To store contents of PM register.
64 * @im0_reg: To store contents of interrupt mode regist0
65 * @im1_reg: To store contents of interrupt mode regist1
51 */ 66 */
52struct ioh_gpio_reg_data { 67struct ioh_gpio_reg_data {
68 u32 ien_reg;
69 u32 imask_reg;
53 u32 po_reg; 70 u32 po_reg;
54 u32 pm_reg; 71 u32 pm_reg;
72 u32 im0_reg;
73 u32 im1_reg;
55}; 74};
56 75
57/** 76/**
@@ -63,6 +82,9 @@ struct ioh_gpio_reg_data {
63 * @ioh_gpio_reg: Memory mapped Register data is saved here 82 * @ioh_gpio_reg: Memory mapped Register data is saved here
64 * when suspend. 83 * when suspend.
65 * @ch: Indicate GPIO channel 84 * @ch: Indicate GPIO channel
85 * @irq_base: Save base of IRQ number for interrupt
86 * @spinlock: Used for register access protection in
87 * interrupt context ioh_irq_type and PM;
66 */ 88 */
67struct ioh_gpio { 89struct ioh_gpio {
68 void __iomem *base; 90 void __iomem *base;
@@ -72,6 +94,8 @@ struct ioh_gpio {
72 struct ioh_gpio_reg_data ioh_gpio_reg; 94 struct ioh_gpio_reg_data ioh_gpio_reg;
73 struct mutex lock; 95 struct mutex lock;
74 int ch; 96 int ch;
97 int irq_base;
98 spinlock_t spinlock;
75}; 99};
76 100
77static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12}; 101static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
@@ -147,6 +171,10 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
147{ 171{
148 chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po); 172 chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
149 chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm); 173 chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
174 chip->ioh_gpio_reg.ien_reg = ioread32(&chip->reg->regs[chip->ch].ien);
175 chip->ioh_gpio_reg.imask_reg = ioread32(&chip->reg->regs[chip->ch].imask);
176 chip->ioh_gpio_reg.im0_reg = ioread32(&chip->reg->regs[chip->ch].im_0);
177 chip->ioh_gpio_reg.im1_reg = ioread32(&chip->reg->regs[chip->ch].im_1);
150} 178}
151 179
152/* 180/*
@@ -154,13 +182,21 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
154 */ 182 */
155static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) 183static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
156{ 184{
157 /* to store contents of PO register */
158 iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po); 185 iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
159 /* to store contents of PM register */
160 iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm); 186 iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
187 iowrite32(chip->ioh_gpio_reg.ien_reg, &chip->reg->regs[chip->ch].ien);
188 iowrite32(chip->ioh_gpio_reg.imask_reg, &chip->reg->regs[chip->ch].imask);
189 iowrite32(chip->ioh_gpio_reg.im0_reg, &chip->reg->regs[chip->ch].im_0);
190 iowrite32(chip->ioh_gpio_reg.im1_reg, &chip->reg->regs[chip->ch].im_1);
161} 191}
162#endif 192#endif
163 193
194static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
195{
196 struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
197 return chip->irq_base + offset;
198}
199
164static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) 200static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
165{ 201{
166 struct gpio_chip *gpio = &chip->gpio; 202 struct gpio_chip *gpio = &chip->gpio;
@@ -175,16 +211,148 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
175 gpio->base = -1; 211 gpio->base = -1;
176 gpio->ngpio = num_port; 212 gpio->ngpio = num_port;
177 gpio->can_sleep = 0; 213 gpio->can_sleep = 0;
214 gpio->to_irq = ioh_gpio_to_irq;
215}
216
217static int ioh_irq_type(struct irq_data *d, unsigned int type)
218{
219 u32 im;
220 u32 *im_reg;
221 u32 ien;
222 u32 im_pos;
223 int ch;
224 unsigned long flags;
225 u32 val;
226 int irq = d->irq;
227 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
228 struct ioh_gpio *chip = gc->private;
229
230 ch = irq - chip->irq_base;
231 if (irq <= chip->irq_base + 7) {
232 im_reg = &chip->reg->regs[chip->ch].im_0;
233 im_pos = ch;
234 } else {
235 im_reg = &chip->reg->regs[chip->ch].im_1;
236 im_pos = ch - 8;
237 }
238 dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n",
239 __func__, irq, type, ch, im_pos, type);
240
241 spin_lock_irqsave(&chip->spinlock, flags);
242
243 switch (type) {
244 case IRQ_TYPE_EDGE_RISING:
245 val = IOH_EDGE_RISING;
246 break;
247 case IRQ_TYPE_EDGE_FALLING:
248 val = IOH_EDGE_FALLING;
249 break;
250 case IRQ_TYPE_EDGE_BOTH:
251 val = IOH_EDGE_BOTH;
252 break;
253 case IRQ_TYPE_LEVEL_HIGH:
254 val = IOH_LEVEL_H;
255 break;
256 case IRQ_TYPE_LEVEL_LOW:
257 val = IOH_LEVEL_L;
258 break;
259 case IRQ_TYPE_PROBE:
260 goto end;
261 default:
262 dev_warn(chip->dev, "%s: unknown type(%dd)",
263 __func__, type);
264 goto end;
265 }
266
267 /* Set interrupt mode */
268 im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4));
269 iowrite32(im | (val << (im_pos * 4)), im_reg);
270
271 /* iclr */
272 iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr);
273
274 /* IMASKCLR */
275 iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr);
276
277 /* Enable interrupt */
278 ien = ioread32(&chip->reg->regs[chip->ch].ien);
279 iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien);
280end:
281 spin_unlock_irqrestore(&chip->spinlock, flags);
282
283 return 0;
284}
285
286static void ioh_irq_unmask(struct irq_data *d)
287{
288 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
289 struct ioh_gpio *chip = gc->private;
290
291 iowrite32(1 << (d->irq - chip->irq_base),
292 &chip->reg->regs[chip->ch].imaskclr);
293}
294
295static void ioh_irq_mask(struct irq_data *d)
296{
297 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
298 struct ioh_gpio *chip = gc->private;
299
300 iowrite32(1 << (d->irq - chip->irq_base),
301 &chip->reg->regs[chip->ch].imask);
302}
303
304static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
305{
306 struct ioh_gpio *chip = dev_id;
307 u32 reg_val;
308 int i, j;
309 int ret = IRQ_NONE;
310
311 for (i = 0; i < 8; i++) {
312 reg_val = ioread32(&chip->reg->regs[i].istatus);
313 for (j = 0; j < num_ports[i]; j++) {
314 if (reg_val & BIT(j)) {
315 dev_dbg(chip->dev,
316 "%s:[%d]:irq=%d status=0x%x\n",
317 __func__, j, irq, reg_val);
318 iowrite32(BIT(j),
319 &chip->reg->regs[chip->ch].iclr);
320 generic_handle_irq(chip->irq_base + j);
321 ret = IRQ_HANDLED;
322 }
323 }
324 }
325 return ret;
326}
327
328static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
329 unsigned int irq_start, unsigned int num)
330{
331 struct irq_chip_generic *gc;
332 struct irq_chip_type *ct;
333
334 gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base,
335 handle_simple_irq);
336 gc->private = chip;
337 ct = gc->chip_types;
338
339 ct->chip.irq_mask = ioh_irq_mask;
340 ct->chip.irq_unmask = ioh_irq_unmask;
341 ct->chip.irq_set_type = ioh_irq_type;
342
343 irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
344 IRQ_NOREQUEST | IRQ_NOPROBE, 0);
178} 345}
179 346
180static int __devinit ioh_gpio_probe(struct pci_dev *pdev, 347static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
181 const struct pci_device_id *id) 348 const struct pci_device_id *id)
182{ 349{
183 int ret; 350 int ret;
184 int i; 351 int i, j;
185 struct ioh_gpio *chip; 352 struct ioh_gpio *chip;
186 void __iomem *base; 353 void __iomem *base;
187 void __iomem *chip_save; 354 void __iomem *chip_save;
355 int irq_base;
188 356
189 ret = pci_enable_device(pdev); 357 ret = pci_enable_device(pdev);
190 if (ret) { 358 if (ret) {
@@ -228,10 +396,41 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
228 } 396 }
229 397
230 chip = chip_save; 398 chip = chip_save;
399 for (j = 0; j < 8; j++, chip++) {
400 irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
401 GFP_KERNEL);
402 if (irq_base < 0) {
403 dev_warn(&pdev->dev,
404 "ml_ioh_gpio: Failed to get IRQ base num\n");
405 chip->irq_base = -1;
406 goto err_irq_alloc_descs;
407 }
408 chip->irq_base = irq_base;
409 ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
410 }
411
412 chip = chip_save;
413 ret = request_irq(pdev->irq, ioh_gpio_handler,
414 IRQF_SHARED, KBUILD_MODNAME, chip);
415 if (ret != 0) {
416 dev_err(&pdev->dev,
417 "%s request_irq failed\n", __func__);
418 goto err_request_irq;
419 }
420
231 pci_set_drvdata(pdev, chip); 421 pci_set_drvdata(pdev, chip);
232 422
233 return 0; 423 return 0;
234 424
425err_request_irq:
426 chip = chip_save;
427err_irq_alloc_descs:
428 while (--j >= 0) {
429 chip--;
430 irq_free_descs(chip->irq_base, num_ports[j]);
431 }
432
433 chip = chip_save;
235err_gpiochip_add: 434err_gpiochip_add:
236 while (--i >= 0) { 435 while (--i >= 0) {
237 chip--; 436 chip--;
@@ -264,7 +463,11 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
264 void __iomem *chip_save; 463 void __iomem *chip_save;
265 464
266 chip_save = chip; 465 chip_save = chip;
466
467 free_irq(pdev->irq, chip);
468
267 for (i = 0; i < 8; i++, chip++) { 469 for (i = 0; i < 8; i++, chip++) {
470 irq_free_descs(chip->irq_base, num_ports[i]);
268 err = gpiochip_remove(&chip->gpio); 471 err = gpiochip_remove(&chip->gpio);
269 if (err) 472 if (err)
270 dev_err(&pdev->dev, "Failed gpiochip_remove\n"); 473 dev_err(&pdev->dev, "Failed gpiochip_remove\n");