summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/lpc_ich.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/lpc_ich.c')
-rw-r--r--drivers/mfd/lpc_ich.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 092ad4b44b6d..a22544fe5319 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -49,6 +49,7 @@
* document number TBD : DH89xxCC
* document number TBD : Panther Point
* document number TBD : Lynx Point
+ * document number TBD : Lynx Point-LP
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -192,6 +193,7 @@ enum lpc_chipsets {
LPC_DH89XXCC, /* DH89xxCC */
LPC_PPT, /* Panther Point */
LPC_LPT, /* Lynx Point */
+ LPC_LPT_LP, /* Lynx Point-LP */
};
struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
@@ -468,6 +470,10 @@ struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
.name = "Lynx Point",
.iTCO_version = 2,
},
+ [LPC_LPT_LP] = {
+ .name = "Lynx Point_LP",
+ .iTCO_version = 2,
+ },
};
/*
@@ -641,6 +647,14 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
{ PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT},
{ PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT},
{ PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT},
+ { PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP},
+ { PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP},
+ { PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP},
+ { PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP},
+ { PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP},
+ { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP},
+ { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP},
+ { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
@@ -683,6 +697,30 @@ static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
cell->pdata_size = sizeof(struct lpc_ich_info);
}
+/*
+ * We don't check for resource conflict globally. There are 2 or 3 independent
+ * GPIO groups and it's enough to have access to one of these to instantiate
+ * the device.
+ */
+static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
+{
+ int ret;
+ u8 use_gpio = 0;
+
+ if (resource_size(res) >= 0x50 &&
+ !acpi_check_region(res->start + 0x40, 0x10, "LPC ICH GPIO3"))
+ use_gpio |= 1 << 2;
+
+ if (!acpi_check_region(res->start + 0x30, 0x10, "LPC ICH GPIO2"))
+ use_gpio |= 1 << 1;
+
+ ret = acpi_check_region(res->start + 0x00, 0x30, "LPC ICH GPIO1");
+ if (!ret)
+ use_gpio |= 1 << 0;
+
+ return use_gpio ? use_gpio : ret;
+}
+
static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
const struct pci_device_id *id)
{
@@ -740,12 +778,13 @@ gpe0_done:
break;
}
- ret = acpi_check_resource_conflict(res);
- if (ret) {
+ ret = lpc_ich_check_conflict_gpio(res);
+ if (ret < 0) {
/* this isn't necessarily fatal for the GPIO */
acpi_conflict = true;
goto gpio_done;
}
+ lpc_chipset_info[id->driver_data].use_gpio = ret;
lpc_ich_enable_gpio_space(dev);
lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);