Commit eb71d4dec4a5e010e34b9d7afdb5af41884c388e

Authored by Peter Tyser
Committed by Lee Jones
1 parent 429b941abd

mfd: lpc_ich: Add support for iTCO v3

Some newer Atom CPUs, eg Avoton and Bay Trail, use slightly different
register layouts for the iTCO than the current v1 and v2 iTCO.
Differences from previous iTCO versions include:
- The ACPI space is enabled in the "ACPI base address" register instead
  of the "ACPI control register"

- The "no reboot" functionality is set in the "Power Management
  Configuration" register instead of the "General Control and Status"
  (GCS) register or PCI configuration space.

- The "ACPI Control Register" is not present on v3.  The "Power
  Management Configuration Base Address" register resides at the same
  address is Avoton/Bay Trail.

To differentiate these newer chipsets create a new v3 iTCO version and
update the MFD driver to support them.

Signed-off-by: Peter Tyser <ptyser@xes-inc.com>
Tested-by: Rajat Jain <rajatjain@juniper.net>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

Showing 2 changed files with 71 additions and 18 deletions Side-by-side Diff

drivers/mfd/lpc_ich.c
... ... @@ -71,9 +71,11 @@
71 71 #define ACPIBASE_GPE_END 0x2f
72 72 #define ACPIBASE_SMI_OFF 0x30
73 73 #define ACPIBASE_SMI_END 0x33
  74 +#define ACPIBASE_PMC_OFF 0x08
  75 +#define ACPIBASE_PMC_END 0x0c
74 76 #define ACPIBASE_TCO_OFF 0x60
75 77 #define ACPIBASE_TCO_END 0x7f
76   -#define ACPICTRL 0x44
  78 +#define ACPICTRL_PMCBASE 0x44
77 79  
78 80 #define ACPIBASE_GCS_OFF 0x3410
79 81 #define ACPIBASE_GCS_END 0x3414
80 82  
... ... @@ -93,11 +95,12 @@
93 95 int chipset;
94 96  
95 97 int abase; /* ACPI base */
96   - int actrl; /* ACPI control or PMC base */
  98 + int actrl_pbase; /* ACPI control or PMC base */
97 99 int gbase; /* GPIO base */
98 100 int gctrl; /* GPIO control */
99 101  
100   - int actrl_save; /* Cached ACPI control base value */
  102 + int abase_save; /* Cached ACPI base value */
  103 + int actrl_pbase_save; /* Cached ACPI control or PMC base value */
101 104 int gctrl_save; /* Cached GPIO control value */
102 105 };
103 106  
... ... @@ -110,7 +113,7 @@
110 113 {
111 114 .flags = IORESOURCE_IO,
112 115 },
113   - /* GCS */
  116 + /* GCS or PMC */
114 117 {
115 118 .flags = IORESOURCE_MEM,
116 119 },
117 120  
... ... @@ -742,11 +745,17 @@
742 745 {
743 746 struct lpc_ich_priv *priv = pci_get_drvdata(dev);
744 747  
745   - if (priv->actrl_save >= 0) {
746   - pci_write_config_byte(dev, priv->actrl, priv->actrl_save);
747   - priv->actrl_save = -1;
  748 + if (priv->abase_save >= 0) {
  749 + pci_write_config_byte(dev, priv->abase, priv->abase_save);
  750 + priv->abase_save = -1;
748 751 }
749 752  
  753 + if (priv->actrl_pbase_save >= 0) {
  754 + pci_write_config_byte(dev, priv->actrl_pbase,
  755 + priv->actrl_pbase_save);
  756 + priv->actrl_pbase_save = -1;
  757 + }
  758 +
750 759 if (priv->gctrl_save >= 0) {
751 760 pci_write_config_byte(dev, priv->gctrl, priv->gctrl_save);
752 761 priv->gctrl_save = -1;
... ... @@ -758,9 +767,26 @@
758 767 struct lpc_ich_priv *priv = pci_get_drvdata(dev);
759 768 u8 reg_save;
760 769  
761   - pci_read_config_byte(dev, priv->actrl, &reg_save);
762   - pci_write_config_byte(dev, priv->actrl, reg_save | 0x80);
763   - priv->actrl_save = reg_save;
  770 + switch (lpc_chipset_info[priv->chipset].iTCO_version) {
  771 + case 3:
  772 + /*
  773 + * Some chipsets (eg Avoton) enable the ACPI space in the
  774 + * ACPI BASE register.
  775 + */
  776 + pci_read_config_byte(dev, priv->abase, &reg_save);
  777 + pci_write_config_byte(dev, priv->abase, reg_save | 0x2);
  778 + priv->abase_save = reg_save;
  779 + break;
  780 + default:
  781 + /*
  782 + * Most chipsets enable the ACPI space in the ACPI control
  783 + * register.
  784 + */
  785 + pci_read_config_byte(dev, priv->actrl_pbase, &reg_save);
  786 + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x80);
  787 + priv->actrl_pbase_save = reg_save;
  788 + break;
  789 + }
764 790 }
765 791  
766 792 static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
... ... @@ -773,6 +799,17 @@
773 799 priv->gctrl_save = reg_save;
774 800 }
775 801  
  802 +static void lpc_ich_enable_pmc_space(struct pci_dev *dev)
  803 +{
  804 + struct lpc_ich_priv *priv = pci_get_drvdata(dev);
  805 + u8 reg_save;
  806 +
  807 + pci_read_config_byte(dev, priv->actrl_pbase, &reg_save);
  808 + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x2);
  809 +
  810 + priv->actrl_pbase_save = reg_save;
  811 +}
  812 +
776 813 static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell)
777 814 {
778 815 struct lpc_ich_priv *priv = pci_get_drvdata(dev);
779 816  
780 817  
... ... @@ -910,14 +947,20 @@
910 947 lpc_ich_enable_acpi_space(dev);
911 948  
912 949 /*
  950 + * iTCO v2:
913 951 * Get the Memory-Mapped GCS register. To get access to it
914 952 * we have to read RCBA from PCI Config space 0xf0 and use
915 953 * it as base. GCS = RCBA + ICH6_GCS(0x3410).
  954 + *
  955 + * iTCO v3:
  956 + * Get the Power Management Configuration register. To get access
  957 + * to it we have to read the PMC BASE from config space and address
  958 + * the register at offset 0x8.
916 959 */
917 960 if (lpc_chipset_info[priv->chipset].iTCO_version == 1) {
918 961 /* Don't register iomem for TCO ver 1 */
919 962 lpc_ich_cells[LPC_WDT].num_resources--;
920   - } else {
  963 + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) {
921 964 pci_read_config_dword(dev, RCBABASE, &base_addr_cfg);
922 965 base_addr = base_addr_cfg & 0xffffc000;
923 966 if (!(base_addr_cfg & 1)) {
924 967  
... ... @@ -926,9 +969,17 @@
926 969 ret = -ENODEV;
927 970 goto wdt_done;
928 971 }
929   - res = wdt_mem_res(ICH_RES_MEM_GCS);
  972 + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC);
930 973 res->start = base_addr + ACPIBASE_GCS_OFF;
931 974 res->end = base_addr + ACPIBASE_GCS_END;
  975 + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 3) {
  976 + lpc_ich_enable_pmc_space(dev);
  977 + pci_read_config_dword(dev, ACPICTRL_PMCBASE, &base_addr_cfg);
  978 + base_addr = base_addr_cfg & 0xfffffe00;
  979 +
  980 + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC);
  981 + res->start = base_addr + ACPIBASE_PMC_OFF;
  982 + res->end = base_addr + ACPIBASE_PMC_END;
932 983 }
933 984  
934 985 lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]);
935 986  
... ... @@ -953,9 +1004,11 @@
953 1004  
954 1005 priv->chipset = id->driver_data;
955 1006  
956   - priv->actrl_save = -1;
  1007 + priv->actrl_pbase_save = -1;
  1008 + priv->abase_save = -1;
  1009 +
957 1010 priv->abase = ACPIBASE;
958   - priv->actrl = ACPICTRL;
  1011 + priv->actrl_pbase = ACPICTRL_PMCBASE;
959 1012  
960 1013 priv->gctrl_save = -1;
961 1014 if (priv->chipset <= LPC_ICH5) {
include/linux/mfd/lpc_ich.h
... ... @@ -21,10 +21,10 @@
21 21 #define LPC_ICH_H
22 22  
23 23 /* Watchdog resources */
24   -#define ICH_RES_IO_TCO 0
25   -#define ICH_RES_IO_SMI 1
26   -#define ICH_RES_MEM_OFF 2
27   -#define ICH_RES_MEM_GCS 0
  24 +#define ICH_RES_IO_TCO 0
  25 +#define ICH_RES_IO_SMI 1
  26 +#define ICH_RES_MEM_OFF 2
  27 +#define ICH_RES_MEM_GCS_PMC 0
28 28  
29 29 /* GPIO resources */
30 30 #define ICH_RES_GPIO 0