#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
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;
.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);
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)
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;