diff options
author | David Cohen <david.a.cohen@linux.intel.com> | 2013-10-04 16:01:40 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-10-11 10:30:39 -0400 |
commit | d56d6b3d7d693581d346b05d089f842b48b7ec0a (patch) | |
tree | d7536e22a4338833eb52cc31a6cc9fbffa8a31df /drivers/gpio | |
parent | 70b5341138dcb931df318afb51e8fb5310f9f095 (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.c | 93 |
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 */ | ||
69 | struct 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 | |||
65 | struct lnw_gpio { | 78 | struct 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 | ||
230 | static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ | 243 | static 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 }, | 247 | static 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 | |||
252 | static const struct lnw_gpio_ddata gpio_penwell_core = { | ||
253 | .ngpio = 96, | ||
254 | .chip_irq_type = LNW_IRQ_TYPE_EDGE, | ||
255 | }; | ||
256 | |||
257 | static 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 | |||
262 | static const struct lnw_gpio_ddata gpio_cloverview_core = { | ||
263 | .ngpio = 96, | ||
264 | .chip_irq_type = LNW_IRQ_TYPE_EDGE, | ||
265 | }; | ||
266 | |||
267 | static 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 | |||
276 | static 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 | }; |
238 | MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); | 309 | MODULE_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 | ||