aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/lpc_ich.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2012-07-23 11:34:15 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-09-14 03:52:13 -0400
commit4f600ada70beeb1dfe08e11e871bf31015aa0a3d (patch)
tree7ab75ca987a49e661c6e33c052e59d56bc83a219 /drivers/mfd/lpc_ich.c
parentcdabc1c88a12e9fc2a49f2a54ce9be470398d8a9 (diff)
gpio: gpio-ich: Share ownership of GPIO groups
The ICH chips have their GPIO pins organized in 2 or 3 independent groups of 32 GPIO pins. It can happen that the ACPI BIOS wants to make use of pins in one group, preventing the OS to access these. This does not prevent the OS from accessing the other group(s). This is the case for example on my Asus Z8NA-D6 board. The ACPI BIOS wants to control GPIO 18 (group 1), while I (the OS) need to control GPIO 52 and 53 (group 2) for SMBus multiplexing. So instead of checking for ACPI resource conflict on the whole I/O range, check on a per-group basis, and consider it a success if at least one of the groups is available for the OS to use. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: Peter Tyser <ptyser@xes-inc.com> Cc: Aaron Sierra <asierra@xes-inc.com> Cc: Grant Likely <grant.likely@secretlab.ca> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/lpc_ich.c')
-rw-r--r--drivers/mfd/lpc_ich.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 092ad4b44b6d..d142622a3fb0 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -683,6 +683,30 @@ static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
683 cell->pdata_size = sizeof(struct lpc_ich_info); 683 cell->pdata_size = sizeof(struct lpc_ich_info);
684} 684}
685 685
686/*
687 * We don't check for resource conflict globally. There are 2 or 3 independent
688 * GPIO groups and it's enough to have access to one of these to instantiate
689 * the device.
690 */
691static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
692{
693 int ret;
694 u8 use_gpio = 0;
695
696 if (resource_size(res) >= 0x50 &&
697 !acpi_check_region(res->start + 0x40, 0x10, "LPC ICH GPIO3"))
698 use_gpio |= 1 << 2;
699
700 if (!acpi_check_region(res->start + 0x30, 0x10, "LPC ICH GPIO2"))
701 use_gpio |= 1 << 1;
702
703 ret = acpi_check_region(res->start + 0x00, 0x30, "LPC ICH GPIO1");
704 if (!ret)
705 use_gpio |= 1 << 0;
706
707 return use_gpio ? use_gpio : ret;
708}
709
686static int __devinit lpc_ich_init_gpio(struct pci_dev *dev, 710static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
687 const struct pci_device_id *id) 711 const struct pci_device_id *id)
688{ 712{
@@ -740,12 +764,13 @@ gpe0_done:
740 break; 764 break;
741 } 765 }
742 766
743 ret = acpi_check_resource_conflict(res); 767 ret = lpc_ich_check_conflict_gpio(res);
744 if (ret) { 768 if (ret < 0) {
745 /* this isn't necessarily fatal for the GPIO */ 769 /* this isn't necessarily fatal for the GPIO */
746 acpi_conflict = true; 770 acpi_conflict = true;
747 goto gpio_done; 771 goto gpio_done;
748 } 772 }
773 lpc_chipset_info[id->driver_data].use_gpio = ret;
749 lpc_ich_enable_gpio_space(dev); 774 lpc_ich_enable_gpio_space(dev);
750 775
751 lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id); 776 lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);