diff options
Diffstat (limited to 'drivers/mfd/lpc_ich.c')
-rw-r--r-- | drivers/mfd/lpc_ich.c | 109 |
1 files changed, 76 insertions, 33 deletions
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index d9d930302e98..a0cfdf980748 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c | |||
@@ -75,8 +75,10 @@ | |||
75 | #define ACPIBASE_GCS_OFF 0x3410 | 75 | #define ACPIBASE_GCS_OFF 0x3410 |
76 | #define ACPIBASE_GCS_END 0x3414 | 76 | #define ACPIBASE_GCS_END 0x3414 |
77 | 77 | ||
78 | #define GPIOBASE 0x48 | 78 | #define GPIOBASE_ICH0 0x58 |
79 | #define GPIOCTRL 0x4C | 79 | #define GPIOCTRL_ICH0 0x5C |
80 | #define GPIOBASE_ICH6 0x48 | ||
81 | #define GPIOCTRL_ICH6 0x4C | ||
80 | 82 | ||
81 | #define RCBABASE 0xf0 | 83 | #define RCBABASE 0xf0 |
82 | 84 | ||
@@ -84,8 +86,17 @@ | |||
84 | #define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) | 86 | #define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) |
85 | #define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) | 87 | #define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) |
86 | 88 | ||
87 | static int lpc_ich_acpi_save = -1; | 89 | struct lpc_ich_cfg { |
88 | static int lpc_ich_gpio_save = -1; | 90 | int base; |
91 | int ctrl; | ||
92 | int save; | ||
93 | }; | ||
94 | |||
95 | struct lpc_ich_priv { | ||
96 | int chipset; | ||
97 | struct lpc_ich_cfg acpi; | ||
98 | struct lpc_ich_cfg gpio; | ||
99 | }; | ||
89 | 100 | ||
90 | static struct resource wdt_ich_res[] = { | 101 | static struct resource wdt_ich_res[] = { |
91 | /* ACPI - TCO */ | 102 | /* ACPI - TCO */ |
@@ -661,39 +672,44 @@ MODULE_DEVICE_TABLE(pci, lpc_ich_ids); | |||
661 | 672 | ||
662 | static void lpc_ich_restore_config_space(struct pci_dev *dev) | 673 | static void lpc_ich_restore_config_space(struct pci_dev *dev) |
663 | { | 674 | { |
664 | if (lpc_ich_acpi_save >= 0) { | 675 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); |
665 | pci_write_config_byte(dev, ACPICTRL, lpc_ich_acpi_save); | 676 | |
666 | lpc_ich_acpi_save = -1; | 677 | if (priv->acpi.save >= 0) { |
678 | pci_write_config_byte(dev, priv->acpi.ctrl, priv->acpi.save); | ||
679 | priv->acpi.save = -1; | ||
667 | } | 680 | } |
668 | 681 | ||
669 | if (lpc_ich_gpio_save >= 0) { | 682 | if (priv->gpio.save >= 0) { |
670 | pci_write_config_byte(dev, GPIOCTRL, lpc_ich_gpio_save); | 683 | pci_write_config_byte(dev, priv->gpio.ctrl, priv->gpio.save); |
671 | lpc_ich_gpio_save = -1; | 684 | priv->gpio.save = -1; |
672 | } | 685 | } |
673 | } | 686 | } |
674 | 687 | ||
675 | static void lpc_ich_enable_acpi_space(struct pci_dev *dev) | 688 | static void lpc_ich_enable_acpi_space(struct pci_dev *dev) |
676 | { | 689 | { |
690 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); | ||
677 | u8 reg_save; | 691 | u8 reg_save; |
678 | 692 | ||
679 | pci_read_config_byte(dev, ACPICTRL, ®_save); | 693 | pci_read_config_byte(dev, priv->acpi.ctrl, ®_save); |
680 | pci_write_config_byte(dev, ACPICTRL, reg_save | 0x10); | 694 | pci_write_config_byte(dev, priv->acpi.ctrl, reg_save | 0x10); |
681 | lpc_ich_acpi_save = reg_save; | 695 | priv->acpi.save = reg_save; |
682 | } | 696 | } |
683 | 697 | ||
684 | static void lpc_ich_enable_gpio_space(struct pci_dev *dev) | 698 | static void lpc_ich_enable_gpio_space(struct pci_dev *dev) |
685 | { | 699 | { |
700 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); | ||
686 | u8 reg_save; | 701 | u8 reg_save; |
687 | 702 | ||
688 | pci_read_config_byte(dev, GPIOCTRL, ®_save); | 703 | pci_read_config_byte(dev, priv->gpio.ctrl, ®_save); |
689 | pci_write_config_byte(dev, GPIOCTRL, reg_save | 0x10); | 704 | pci_write_config_byte(dev, priv->gpio.ctrl, reg_save | 0x10); |
690 | lpc_ich_gpio_save = reg_save; | 705 | priv->gpio.save = reg_save; |
691 | } | 706 | } |
692 | 707 | ||
693 | static void lpc_ich_finalize_cell(struct mfd_cell *cell, | 708 | static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell) |
694 | const struct pci_device_id *id) | ||
695 | { | 709 | { |
696 | cell->platform_data = &lpc_chipset_info[id->driver_data]; | 710 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); |
711 | |||
712 | cell->platform_data = &lpc_chipset_info[priv->chipset]; | ||
697 | cell->pdata_size = sizeof(struct lpc_ich_info); | 713 | cell->pdata_size = sizeof(struct lpc_ich_info); |
698 | } | 714 | } |
699 | 715 | ||
@@ -721,9 +737,9 @@ static int lpc_ich_check_conflict_gpio(struct resource *res) | |||
721 | return use_gpio ? use_gpio : ret; | 737 | return use_gpio ? use_gpio : ret; |
722 | } | 738 | } |
723 | 739 | ||
724 | static int lpc_ich_init_gpio(struct pci_dev *dev, | 740 | static int lpc_ich_init_gpio(struct pci_dev *dev) |
725 | const struct pci_device_id *id) | ||
726 | { | 741 | { |
742 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); | ||
727 | u32 base_addr_cfg; | 743 | u32 base_addr_cfg; |
728 | u32 base_addr; | 744 | u32 base_addr; |
729 | int ret; | 745 | int ret; |
@@ -731,7 +747,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev, | |||
731 | struct resource *res; | 747 | struct resource *res; |
732 | 748 | ||
733 | /* Setup power management base register */ | 749 | /* Setup power management base register */ |
734 | pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg); | 750 | pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg); |
735 | base_addr = base_addr_cfg & 0x0000ff80; | 751 | base_addr = base_addr_cfg & 0x0000ff80; |
736 | if (!base_addr) { | 752 | if (!base_addr) { |
737 | dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); | 753 | dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); |
@@ -757,7 +773,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev, | |||
757 | 773 | ||
758 | gpe0_done: | 774 | gpe0_done: |
759 | /* Setup GPIO base register */ | 775 | /* Setup GPIO base register */ |
760 | pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg); | 776 | pci_read_config_dword(dev, priv->gpio.base, &base_addr_cfg); |
761 | base_addr = base_addr_cfg & 0x0000ff80; | 777 | base_addr = base_addr_cfg & 0x0000ff80; |
762 | if (!base_addr) { | 778 | if (!base_addr) { |
763 | dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n"); | 779 | dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n"); |
@@ -768,7 +784,7 @@ gpe0_done: | |||
768 | /* Older devices provide fewer GPIO and have a smaller resource size. */ | 784 | /* Older devices provide fewer GPIO and have a smaller resource size. */ |
769 | res = &gpio_ich_res[ICH_RES_GPIO]; | 785 | res = &gpio_ich_res[ICH_RES_GPIO]; |
770 | res->start = base_addr; | 786 | res->start = base_addr; |
771 | switch (lpc_chipset_info[id->driver_data].gpio_version) { | 787 | switch (lpc_chipset_info[priv->chipset].gpio_version) { |
772 | case ICH_V5_GPIO: | 788 | case ICH_V5_GPIO: |
773 | case ICH_V10CORP_GPIO: | 789 | case ICH_V10CORP_GPIO: |
774 | res->end = res->start + 128 - 1; | 790 | res->end = res->start + 128 - 1; |
@@ -784,10 +800,10 @@ gpe0_done: | |||
784 | acpi_conflict = true; | 800 | acpi_conflict = true; |
785 | goto gpio_done; | 801 | goto gpio_done; |
786 | } | 802 | } |
787 | lpc_chipset_info[id->driver_data].use_gpio = ret; | 803 | lpc_chipset_info[priv->chipset].use_gpio = ret; |
788 | lpc_ich_enable_gpio_space(dev); | 804 | lpc_ich_enable_gpio_space(dev); |
789 | 805 | ||
790 | lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id); | 806 | lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_GPIO]); |
791 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], | 807 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], |
792 | 1, NULL, 0, NULL); | 808 | 1, NULL, 0, NULL); |
793 | 809 | ||
@@ -798,16 +814,16 @@ gpio_done: | |||
798 | return ret; | 814 | return ret; |
799 | } | 815 | } |
800 | 816 | ||
801 | static int lpc_ich_init_wdt(struct pci_dev *dev, | 817 | static int lpc_ich_init_wdt(struct pci_dev *dev) |
802 | const struct pci_device_id *id) | ||
803 | { | 818 | { |
819 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); | ||
804 | u32 base_addr_cfg; | 820 | u32 base_addr_cfg; |
805 | u32 base_addr; | 821 | u32 base_addr; |
806 | int ret; | 822 | int ret; |
807 | struct resource *res; | 823 | struct resource *res; |
808 | 824 | ||
809 | /* Setup power management base register */ | 825 | /* Setup power management base register */ |
810 | pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg); | 826 | pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg); |
811 | base_addr = base_addr_cfg & 0x0000ff80; | 827 | base_addr = base_addr_cfg & 0x0000ff80; |
812 | if (!base_addr) { | 828 | if (!base_addr) { |
813 | dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); | 829 | dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); |
@@ -830,7 +846,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev, | |||
830 | * we have to read RCBA from PCI Config space 0xf0 and use | 846 | * we have to read RCBA from PCI Config space 0xf0 and use |
831 | * it as base. GCS = RCBA + ICH6_GCS(0x3410). | 847 | * it as base. GCS = RCBA + ICH6_GCS(0x3410). |
832 | */ | 848 | */ |
833 | if (lpc_chipset_info[id->driver_data].iTCO_version == 1) { | 849 | if (lpc_chipset_info[priv->chipset].iTCO_version == 1) { |
834 | /* Don't register iomem for TCO ver 1 */ | 850 | /* Don't register iomem for TCO ver 1 */ |
835 | lpc_ich_cells[LPC_WDT].num_resources--; | 851 | lpc_ich_cells[LPC_WDT].num_resources--; |
836 | } else { | 852 | } else { |
@@ -847,7 +863,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev, | |||
847 | res->end = base_addr + ACPIBASE_GCS_END; | 863 | res->end = base_addr + ACPIBASE_GCS_END; |
848 | } | 864 | } |
849 | 865 | ||
850 | lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); | 866 | lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]); |
851 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], | 867 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], |
852 | 1, NULL, 0, NULL); | 868 | 1, NULL, 0, NULL); |
853 | 869 | ||
@@ -858,14 +874,35 @@ wdt_done: | |||
858 | static int lpc_ich_probe(struct pci_dev *dev, | 874 | static int lpc_ich_probe(struct pci_dev *dev, |
859 | const struct pci_device_id *id) | 875 | const struct pci_device_id *id) |
860 | { | 876 | { |
877 | struct lpc_ich_priv *priv; | ||
861 | int ret; | 878 | int ret; |
862 | bool cell_added = false; | 879 | bool cell_added = false; |
863 | 880 | ||
864 | ret = lpc_ich_init_wdt(dev, id); | 881 | priv = kmalloc(GFP_KERNEL, sizeof(struct lpc_ich_priv)); |
882 | if (!priv) | ||
883 | return -ENOMEM; | ||
884 | |||
885 | priv->chipset = id->driver_data; | ||
886 | priv->acpi.save = -1; | ||
887 | priv->acpi.base = ACPIBASE; | ||
888 | priv->acpi.ctrl = ACPICTRL; | ||
889 | |||
890 | priv->gpio.save = -1; | ||
891 | if (priv->chipset <= LPC_ICH5) { | ||
892 | priv->gpio.base = GPIOBASE_ICH0; | ||
893 | priv->gpio.ctrl = GPIOCTRL_ICH0; | ||
894 | } else { | ||
895 | priv->gpio.base = GPIOBASE_ICH6; | ||
896 | priv->gpio.ctrl = GPIOCTRL_ICH6; | ||
897 | } | ||
898 | |||
899 | pci_set_drvdata(dev, priv); | ||
900 | |||
901 | ret = lpc_ich_init_wdt(dev); | ||
865 | if (!ret) | 902 | if (!ret) |
866 | cell_added = true; | 903 | cell_added = true; |
867 | 904 | ||
868 | ret = lpc_ich_init_gpio(dev, id); | 905 | ret = lpc_ich_init_gpio(dev); |
869 | if (!ret) | 906 | if (!ret) |
870 | cell_added = true; | 907 | cell_added = true; |
871 | 908 | ||
@@ -876,6 +913,8 @@ static int lpc_ich_probe(struct pci_dev *dev, | |||
876 | if (!cell_added) { | 913 | if (!cell_added) { |
877 | dev_warn(&dev->dev, "No MFD cells added\n"); | 914 | dev_warn(&dev->dev, "No MFD cells added\n"); |
878 | lpc_ich_restore_config_space(dev); | 915 | lpc_ich_restore_config_space(dev); |
916 | pci_set_drvdata(dev, NULL); | ||
917 | kfree(priv); | ||
879 | return -ENODEV; | 918 | return -ENODEV; |
880 | } | 919 | } |
881 | 920 | ||
@@ -884,8 +923,12 @@ static int lpc_ich_probe(struct pci_dev *dev, | |||
884 | 923 | ||
885 | static void lpc_ich_remove(struct pci_dev *dev) | 924 | static void lpc_ich_remove(struct pci_dev *dev) |
886 | { | 925 | { |
926 | void *priv = pci_get_drvdata(dev); | ||
927 | |||
887 | mfd_remove_devices(&dev->dev); | 928 | mfd_remove_devices(&dev->dev); |
888 | lpc_ich_restore_config_space(dev); | 929 | lpc_ich_restore_config_space(dev); |
930 | pci_set_drvdata(dev, NULL); | ||
931 | kfree(priv); | ||
889 | } | 932 | } |
890 | 933 | ||
891 | static struct pci_driver lpc_ich_driver = { | 934 | static struct pci_driver lpc_ich_driver = { |