summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorDavid Cohen <david.a.cohen@linux.intel.com>2013-10-04 16:01:40 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-10-11 10:30:39 -0400
commitd56d6b3d7d693581d346b05d089f842b48b7ec0a (patch)
treed7536e22a4338833eb52cc31a6cc9fbffa8a31df /drivers/gpio
parent70b5341138dcb931df318afb51e8fb5310f9f095 (diff)
gpio: langwell: add Intel Merrifield support
This patch implements a better way to handle multiple SoC's and adds Intel Merrifield support to gpio-langwell. It was based on previous work from Ning Li <ning.li@intel.com> Signed-off-by: David Cohen <david.a.cohen@linux.intel.com> Signed-off-by: Fei Yang <fei.yang@intel.com> Signed-off-by: Ning Li <ning.li@intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-langwell.c93
1 files changed, 82 insertions, 11 deletions
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
index bfa1af1b519f..bf3b9597abd8 100644
--- a/drivers/gpio/gpio-langwell.c
+++ b/drivers/gpio/gpio-langwell.c
@@ -37,6 +37,9 @@
37#include <linux/pm_runtime.h> 37#include <linux/pm_runtime.h>
38#include <linux/irqdomain.h> 38#include <linux/irqdomain.h>
39 39
40#define LNW_IRQ_TYPE_EDGE (1 << 0)
41#define LNW_IRQ_TYPE_LEVEL (1 << 1)
42
40/* 43/*
41 * Langwell chip has 64 pins and thus there are 2 32bit registers to control 44 * Langwell chip has 64 pins and thus there are 2 32bit registers to control
42 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit 45 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
@@ -62,6 +65,16 @@ enum GPIO_REG {
62 GAFR, /* alt function */ 65 GAFR, /* alt function */
63}; 66};
64 67
68/* langwell gpio driver data */
69struct lnw_gpio_ddata {
70 u16 ngpio; /* number of gpio pins */
71 u32 gplr_offset; /* offset of first GPLR register from base */
72 u32 flis_base; /* base address of FLIS registers */
73 u32 flis_len; /* length of FLIS registers */
74 u32 (*get_flis_offset)(int gpio);
75 u32 chip_irq_type; /* chip interrupt type */
76};
77
65struct lnw_gpio { 78struct lnw_gpio {
66 struct gpio_chip chip; 79 struct gpio_chip chip;
67 void __iomem *reg_base; 80 void __iomem *reg_base;
@@ -227,13 +240,71 @@ static struct irq_chip lnw_irqchip = {
227 .irq_set_type = lnw_irq_type, 240 .irq_set_type = lnw_irq_type,
228}; 241};
229 242
230static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ 243static const struct lnw_gpio_ddata gpio_lincroft = {
231 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 }, 244 .ngpio = 64,
232 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 }, 245};
233 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 }, 246
234 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb), .driver_data = 96 }, 247static const struct lnw_gpio_ddata gpio_penwell_aon = {
235 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), .driver_data = 96 }, 248 .ngpio = 96,
236 { 0, } 249 .chip_irq_type = LNW_IRQ_TYPE_EDGE,
250};
251
252static const struct lnw_gpio_ddata gpio_penwell_core = {
253 .ngpio = 96,
254 .chip_irq_type = LNW_IRQ_TYPE_EDGE,
255};
256
257static const struct lnw_gpio_ddata gpio_cloverview_aon = {
258 .ngpio = 96,
259 .chip_irq_type = LNW_IRQ_TYPE_EDGE | LNW_IRQ_TYPE_LEVEL,
260};
261
262static const struct lnw_gpio_ddata gpio_cloverview_core = {
263 .ngpio = 96,
264 .chip_irq_type = LNW_IRQ_TYPE_EDGE,
265};
266
267static const struct lnw_gpio_ddata gpio_tangier = {
268 .ngpio = 192,
269 .gplr_offset = 4,
270 .flis_base = 0xff0c0000,
271 .flis_len = 0x8000,
272 .get_flis_offset = NULL,
273 .chip_irq_type = LNW_IRQ_TYPE_EDGE,
274};
275
276static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {
277 {
278 /* Lincroft */
279 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f),
280 .driver_data = (kernel_ulong_t)&gpio_lincroft,
281 },
282 {
283 /* Penwell AON */
284 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f),
285 .driver_data = (kernel_ulong_t)&gpio_penwell_aon,
286 },
287 {
288 /* Penwell Core */
289 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a),
290 .driver_data = (kernel_ulong_t)&gpio_penwell_core,
291 },
292 {
293 /* Cloverview Aon */
294 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb),
295 .driver_data = (kernel_ulong_t)&gpio_cloverview_aon,
296 },
297 {
298 /* Cloverview Core */
299 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
300 .driver_data = (kernel_ulong_t)&gpio_cloverview_core,
301 },
302 {
303 /* Tangier */
304 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199),
305 .driver_data = (kernel_ulong_t)&gpio_tangier,
306 },
307 { 0 }
237}; 308};
238MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); 309MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
239 310
@@ -316,7 +387,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
316 u32 gpio_base; 387 u32 gpio_base;
317 u32 irq_base; 388 u32 irq_base;
318 int retval; 389 int retval;
319 int ngpio = id->driver_data; 390 struct lnw_gpio_ddata *ddata = (struct lnw_gpio_ddata *)id->driver_data;
320 391
321 retval = pcim_enable_device(pdev); 392 retval = pcim_enable_device(pdev);
322 if (retval) 393 if (retval)
@@ -351,14 +422,14 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
351 lnw->chip.set = lnw_gpio_set; 422 lnw->chip.set = lnw_gpio_set;
352 lnw->chip.to_irq = lnw_gpio_to_irq; 423 lnw->chip.to_irq = lnw_gpio_to_irq;
353 lnw->chip.base = gpio_base; 424 lnw->chip.base = gpio_base;
354 lnw->chip.ngpio = ngpio; 425 lnw->chip.ngpio = ddata->ngpio;
355 lnw->chip.can_sleep = 0; 426 lnw->chip.can_sleep = 0;
356 lnw->pdev = pdev; 427 lnw->pdev = pdev;
357 428
358 spin_lock_init(&lnw->lock); 429 spin_lock_init(&lnw->lock);
359 430
360 lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base, 431 lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio,
361 &lnw_gpio_irq_ops, lnw); 432 irq_base, &lnw_gpio_irq_ops, lnw);
362 if (!lnw->domain) 433 if (!lnw->domain)
363 return -ENOMEM; 434 return -ENOMEM;
364 435