diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-07 10:24:18 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-07 10:24:18 -0700 |
commit | e5744abb2fa3629aa5a94e21ca1eae32ff2fe00b (patch) | |
tree | ef90c96390256b073f5255d224aecb2fc1f6ee84 /drivers/mfd/lpc_ich.c | |
parent | c29aa153ef0469cddf0146d41ce6494bd76be78b (diff) | |
parent | 2d28ca731b9bb6262f7711241628c7844b0cf7dc (diff) |
Merge tag 'mfd-for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"Changes to existing drivers:
- Use of managed resources - omap, twl4030, ti_am335x_tscadc
- Advanced error handling - omap
- Rework clk management - omap
- Device Tree (re-)work - tc3589x, pm8921, da9055, sec
- IRC management overhaul and !BROKEN - pm8921
- Convert to regmap - ssbi, pm8921
- Use simple power-management ops - ucb1x00
- Include file clean-up - adp5520, cs5535, janz, lpc_ich,
- lpc_sch, max14577, mcp-sa11x0, pcf50633-adc, rc5t583,
rdc321x-southbridge, retu, smsc-ece1099, ti-ssp, ti_am335x_tscadc,
tps65912, vexpress-config, wm8350, ywm8350
- Various bug fixes across the subsystem
- NULL/invalid pointer dereference prevention
- Resource leak mitigation,
- Variable used initialised
- Staticise various containers
- Enforce return value checks
New drivers/supported devices:
- Add support for s2mps14 and s2mpa01 to sec
- Add support for da9063 (v5) to da9063
- Add support for atom-c2000 to gpio-ich
- Add support for come-{mbt10,cbt6,chl6} to kempld
- Add support for da9053 to da9052
- Add support for itco-wdt (v3) and baytrail to lpc_ich
- Add new drivers for tps65218, rtsx_usb, bcm590xx
(Re-)moved drivers:
- twl4030 ==> drivers/iio
- ti-ssp ==> /dev/null"
* tag 'mfd-for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (103 commits)
mfd: wm5110: Correct default for HEADPHONE_DETECT_1
mfd: arizona: Correct small errors in the DT binding documentation
mfd: arizona: Mark DSP clocking register as volatile
mfd: devicetree: bindings: Add pm8xxx RTC description
mfd: kempld-core: Fix potential hang-up during boot
mfd: sec-core: Fix uninitialized 'regmap_rtc' on S2MPA01
mfd: tps65910: Fix regmap_irq_chip_data leak on mfd_add_devices fail
mfd: tps65910: Fix possible invalid pointer dereference on regmap_add_irq_chip fail
mfd: sec-core: Fix I2C dummy device resource leak on probe failure
mfd: sec-core: Add of_compatible strings for clock MFD cells
mfd: Remove obsolete ti-ssp driver
Documentation: mfd: s2mps11: Describe S5M8767 and S2MPS14 clocks
mfd: bcm590xx: Fix type argument for module device table
mfd: lpc_ich: Add support for Intel Bay Trail SoC
mfd: lpc_ich: Add support for NM10 GPIO
mfd: lpc_ich: Change Avoton to iTCO v3
watchdog: iTCO_wdt: Add support for v3 silicon
mfd: lpc_ich: Add support for iTCO v3
mfd: lpc_ich: Remove lpc_ich_cfg struct use
mfd: lpc_ich: Only configure watchdog or GPIO when present
...
Diffstat (limited to 'drivers/mfd/lpc_ich.c')
-rw-r--r-- | drivers/mfd/lpc_ich.c | 151 |
1 files changed, 108 insertions, 43 deletions
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index be93fa261de..3f10ea3f45d 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -58,7 +58,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/errno.h> @@ -72,9 +71,11 @@ #define ACPIBASE_GPE_END 0x2f #define ACPIBASE_SMI_OFF 0x30 #define ACPIBASE_SMI_END 0x33 +#define ACPIBASE_PMC_OFF 0x08 +#define ACPIBASE_PMC_END 0x0c #define ACPIBASE_TCO_OFF 0x60 #define ACPIBASE_TCO_END 0x7f -#define ACPICTRL 0x44 +#define ACPICTRL_PMCBASE 0x44 #define ACPIBASE_GCS_OFF 0x3410 #define ACPIBASE_GCS_END 0x3414 @@ -90,16 +91,17 @@ #define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) #define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) -struct lpc_ich_cfg { - int base; - int ctrl; - int save; -}; - struct lpc_ich_priv { int chipset; - struct lpc_ich_cfg acpi; - struct lpc_ich_cfg gpio; + + int abase; /* ACPI base */ + int actrl_pbase; /* ACPI control or PMC base */ + int gbase; /* GPIO base */ + int gctrl; /* GPIO control */ + + int abase_save; /* Cached ACPI base value */ + int actrl_pbase_save; /* Cached ACPI control or PMC base value */ + int gctrl_save; /* Cached GPIO control value */ }; static struct resource wdt_ich_res[] = { @@ -111,7 +113,7 @@ static struct resource wdt_ich_res[] = { { .flags = IORESOURCE_IO, }, - /* GCS */ + /* GCS or PMC */ { .flags = IORESOURCE_MEM, }, @@ -211,6 +213,7 @@ enum lpc_chipsets { LPC_LPT_LP, /* Lynx Point-LP */ LPC_WBG, /* Wellsburg */ LPC_AVN, /* Avoton SoC */ + LPC_BAYTRAIL, /* Bay Trail SoC */ LPC_COLETO, /* Coleto Creek */ LPC_WPT_LP, /* Wildcat Point-LP */ }; @@ -303,6 +306,7 @@ static struct lpc_ich_info lpc_chipset_info[] = { [LPC_NM10] = { .name = "NM10", .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, }, [LPC_ICH8] = { .name = "ICH8 or ICH8R", @@ -499,7 +503,12 @@ static struct lpc_ich_info lpc_chipset_info[] = { }, [LPC_AVN] = { .name = "Avoton SoC", - .iTCO_version = 1, + .iTCO_version = 3, + .gpio_version = AVOTON_GPIO, + }, + [LPC_BAYTRAIL] = { + .name = "Bay Trail SoC", + .iTCO_version = 3, }, [LPC_COLETO] = { .name = "Coleto Creek", @@ -726,6 +735,7 @@ static const struct pci_device_id lpc_ich_ids[] = { { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN}, { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL}, { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO}, { PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP}, { PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP}, @@ -742,14 +752,20 @@ static void lpc_ich_restore_config_space(struct pci_dev *dev) { struct lpc_ich_priv *priv = pci_get_drvdata(dev); - if (priv->acpi.save >= 0) { - pci_write_config_byte(dev, priv->acpi.ctrl, priv->acpi.save); - priv->acpi.save = -1; + if (priv->abase_save >= 0) { + pci_write_config_byte(dev, priv->abase, priv->abase_save); + priv->abase_save = -1; + } + + if (priv->actrl_pbase_save >= 0) { + pci_write_config_byte(dev, priv->actrl_pbase, + priv->actrl_pbase_save); + priv->actrl_pbase_save = -1; } - if (priv->gpio.save >= 0) { - pci_write_config_byte(dev, priv->gpio.ctrl, priv->gpio.save); - priv->gpio.save = -1; + if (priv->gctrl_save >= 0) { + pci_write_config_byte(dev, priv->gctrl, priv->gctrl_save); + priv->gctrl_save = -1; } } @@ -758,9 +774,26 @@ static void lpc_ich_enable_acpi_space(struct pci_dev *dev) struct lpc_ich_priv *priv = pci_get_drvdata(dev); u8 reg_save; - pci_read_config_byte(dev, priv->acpi.ctrl, ®_save); - pci_write_config_byte(dev, priv->acpi.ctrl, reg_save | 0x10); - priv->acpi.save = reg_save; + switch (lpc_chipset_info[priv->chipset].iTCO_version) { + case 3: + /* + * Some chipsets (eg Avoton) enable the ACPI space in the + * ACPI BASE register. + */ + pci_read_config_byte(dev, priv->abase, ®_save); + pci_write_config_byte(dev, priv->abase, reg_save | 0x2); + priv->abase_save = reg_save; + break; + default: + /* + * Most chipsets enable the ACPI space in the ACPI control + * register. + */ + pci_read_config_byte(dev, priv->actrl_pbase, ®_save); + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x80); + priv->actrl_pbase_save = reg_save; + break; + } } static void lpc_ich_enable_gpio_space(struct pci_dev *dev) @@ -768,9 +801,20 @@ static void lpc_ich_enable_gpio_space(struct pci_dev *dev) struct lpc_ich_priv *priv = pci_get_drvdata(dev); u8 reg_save; - pci_read_config_byte(dev, priv->gpio.ctrl, ®_save); - pci_write_config_byte(dev, priv->gpio.ctrl, reg_save | 0x10); - priv->gpio.save = reg_save; + pci_read_config_byte(dev, priv->gctrl, ®_save); + pci_write_config_byte(dev, priv->gctrl, reg_save | 0x10); + priv->gctrl_save = reg_save; +} + +static void lpc_ich_enable_pmc_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + pci_read_config_byte(dev, priv->actrl_pbase, ®_save); + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x2); + + priv->actrl_pbase_save = reg_save; } static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell) @@ -815,7 +859,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev) struct resource *res; /* Setup power management base register */ - pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg); + pci_read_config_dword(dev, priv->abase, &base_addr_cfg); base_addr = base_addr_cfg & 0x0000ff80; if (!base_addr) { dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); @@ -841,7 +885,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev) gpe0_done: /* Setup GPIO base register */ - pci_read_config_dword(dev, priv->gpio.base, &base_addr_cfg); + pci_read_config_dword(dev, priv->gbase, &base_addr_cfg); base_addr = base_addr_cfg & 0x0000ff80; if (!base_addr) { dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n"); @@ -891,7 +935,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev) struct resource *res; /* Setup power management base register */ - pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg); + pci_read_config_dword(dev, priv->abase, &base_addr_cfg); base_addr = base_addr_cfg & 0x0000ff80; if (!base_addr) { dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); @@ -910,14 +954,20 @@ static int lpc_ich_init_wdt(struct pci_dev *dev) lpc_ich_enable_acpi_space(dev); /* + * iTCO v2: * Get the Memory-Mapped GCS register. To get access to it * we have to read RCBA from PCI Config space 0xf0 and use * it as base. GCS = RCBA + ICH6_GCS(0x3410). + * + * iTCO v3: + * Get the Power Management Configuration register. To get access + * to it we have to read the PMC BASE from config space and address + * the register at offset 0x8. */ if (lpc_chipset_info[priv->chipset].iTCO_version == 1) { /* Don't register iomem for TCO ver 1 */ lpc_ich_cells[LPC_WDT].num_resources--; - } else { + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) { pci_read_config_dword(dev, RCBABASE, &base_addr_cfg); base_addr = base_addr_cfg & 0xffffc000; if (!(base_addr_cfg & 1)) { @@ -926,9 +976,17 @@ static int lpc_ich_init_wdt(struct pci_dev *dev) ret = -ENODEV; goto wdt_done; } - res = wdt_mem_res(ICH_RES_MEM_GCS); + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC); res->start = base_addr + ACPIBASE_GCS_OFF; res->end = base_addr + ACPIBASE_GCS_END; + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 3) { + lpc_ich_enable_pmc_space(dev); + pci_read_config_dword(dev, ACPICTRL_PMCBASE, &base_addr_cfg); + base_addr = base_addr_cfg & 0xfffffe00; + + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC); + res->start = base_addr + ACPIBASE_PMC_OFF; + res->end = base_addr + ACPIBASE_PMC_END; } lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]); @@ -952,28 +1010,35 @@ static int lpc_ich_probe(struct pci_dev *dev, return -ENOMEM; priv->chipset = id->driver_data; - priv->acpi.save = -1; - priv->acpi.base = ACPIBASE; - priv->acpi.ctrl = ACPICTRL; - priv->gpio.save = -1; + priv->actrl_pbase_save = -1; + priv->abase_save = -1; + + priv->abase = ACPIBASE; + priv->actrl_pbase = ACPICTRL_PMCBASE; + + priv->gctrl_save = -1; if (priv->chipset <= LPC_ICH5) { - priv->gpio.base = GPIOBASE_ICH0; - priv->gpio.ctrl = GPIOCTRL_ICH0; + priv->gbase = GPIOBASE_ICH0; + priv->gctrl = GPIOCTRL_ICH0; } else { - priv->gpio.base = GPIOBASE_ICH6; - priv->gpio.ctrl = GPIOCTRL_ICH6; + priv->gbase = GPIOBASE_ICH6; + priv->gctrl = GPIOCTRL_ICH6; } pci_set_drvdata(dev, priv); - ret = lpc_ich_init_wdt(dev); - if (!ret) - cell_added = true; + if (lpc_chipset_info[priv->chipset].iTCO_version) { + ret = lpc_ich_init_wdt(dev); + if (!ret) + cell_added = true; + } - ret = lpc_ich_init_gpio(dev); - if (!ret) - cell_added = true; + if (lpc_chipset_info[priv->chipset].gpio_version) { + ret = lpc_ich_init_gpio(dev); + if (!ret) + cell_added = true; + } /* * We only care if at least one or none of the cells registered |