diff options
author | David Cohen <david.a.cohen@linux.intel.com> | 2013-10-04 13:01:40 -0700 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-10-11 16:30:39 +0200 |
commit | d56d6b3d7d693581d346b05d089f842b48b7ec0a (patch) | |
tree | d7536e22a4338833eb52cc31a6cc9fbffa8a31df | |
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>
-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 @@ #include <linux/pm_runtime.h> #include <linux/irqdomain.h> +#define LNW_IRQ_TYPE_EDGE (1 << 0) +#define LNW_IRQ_TYPE_LEVEL (1 << 1) + /* * Langwell chip has 64 pins and thus there are 2 32bit registers to control * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit @@ -62,6 +65,16 @@ enum GPIO_REG { GAFR, /* alt function */ }; +/* langwell gpio driver data */ +struct lnw_gpio_ddata { + u16 ngpio; /* number of gpio pins */ + u32 gplr_offset; /* offset of first GPLR register from base */ + u32 flis_base; /* base address of FLIS registers */ + u32 flis_len; /* length of FLIS registers */ + u32 (*get_flis_offset)(int gpio); + u32 chip_irq_type; /* chip interrupt type */ +}; + struct lnw_gpio { struct gpio_chip chip; void __iomem *reg_base; @@ -227,13 +240,71 @@ static struct irq_chip lnw_irqchip = { .irq_set_type = lnw_irq_type, }; -static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb), .driver_data = 96 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), .driver_data = 96 }, - { 0, } +static const struct lnw_gpio_ddata gpio_lincroft = { + .ngpio = 64, +}; + +static const struct lnw_gpio_ddata gpio_penwell_aon = { + .ngpio = 96, + .chip_irq_type = LNW_IRQ_TYPE_EDGE, +}; + +static const struct lnw_gpio_ddata gpio_penwell_core = { + .ngpio = 96, + .chip_irq_type = LNW_IRQ_TYPE_EDGE, +}; + +static const struct lnw_gpio_ddata gpio_cloverview_aon = { + .ngpio = 96, + .chip_irq_type = LNW_IRQ_TYPE_EDGE | LNW_IRQ_TYPE_LEVEL, +}; + +static const struct lnw_gpio_ddata gpio_cloverview_core = { + .ngpio = 96, + .chip_irq_type = LNW_IRQ_TYPE_EDGE, +}; + +static const struct lnw_gpio_ddata gpio_tangier = { + .ngpio = 192, + .gplr_offset = 4, + .flis_base = 0xff0c0000, + .flis_len = 0x8000, + .get_flis_offset = NULL, + .chip_irq_type = LNW_IRQ_TYPE_EDGE, +}; + +static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { + { + /* Lincroft */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), + .driver_data = (kernel_ulong_t)&gpio_lincroft, + }, + { + /* Penwell AON */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), + .driver_data = (kernel_ulong_t)&gpio_penwell_aon, + }, + { + /* Penwell Core */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), + .driver_data = (kernel_ulong_t)&gpio_penwell_core, + }, + { + /* Cloverview Aon */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb), + .driver_data = (kernel_ulong_t)&gpio_cloverview_aon, + }, + { + /* Cloverview Core */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), + .driver_data = (kernel_ulong_t)&gpio_cloverview_core, + }, + { + /* Tangier */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199), + .driver_data = (kernel_ulong_t)&gpio_tangier, + }, + { 0 } }; MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); @@ -316,7 +387,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev, u32 gpio_base; u32 irq_base; int retval; - int ngpio = id->driver_data; + struct lnw_gpio_ddata *ddata = (struct lnw_gpio_ddata *)id->driver_data; retval = pcim_enable_device(pdev); if (retval) @@ -351,14 +422,14 @@ static int lnw_gpio_probe(struct pci_dev *pdev, lnw->chip.set = lnw_gpio_set; lnw->chip.to_irq = lnw_gpio_to_irq; lnw->chip.base = gpio_base; - lnw->chip.ngpio = ngpio; + lnw->chip.ngpio = ddata->ngpio; lnw->chip.can_sleep = 0; lnw->pdev = pdev; spin_lock_init(&lnw->lock); - lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base, - &lnw_gpio_irq_ops, lnw); + lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio, + irq_base, &lnw_gpio_irq_ops, lnw); if (!lnw->domain) return -ENOMEM; |