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
  ...
This commit is contained in:
Linus Torvalds
2014-04-07 10:24:18 -07:00
92 changed files with 3960 additions and 1590 deletions

View File

@@ -48,7 +48,7 @@
/* Module and version information */
#define DRV_NAME "iTCO_wdt"
#define DRV_VERSION "1.10"
#define DRV_VERSION "1.11"
/* Includes */
#include <linux/module.h> /* For module specific items */
@@ -92,9 +92,12 @@ static struct { /* this is private data for the iTCO_wdt device */
unsigned int iTCO_version;
struct resource *tco_res;
struct resource *smi_res;
struct resource *gcs_res;
/* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
unsigned long __iomem *gcs;
/*
* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2),
* or memory-mapped PMC register bit 4 (TCO version 3).
*/
struct resource *gcs_pmc_res;
unsigned long __iomem *gcs_pmc;
/* the lock for io operations */
spinlock_t io_lock;
struct platform_device *dev;
@@ -125,11 +128,19 @@ MODULE_PARM_DESC(turn_SMI_watchdog_clear_off,
* Some TCO specific functions
*/
static inline unsigned int seconds_to_ticks(int seconds)
/*
* The iTCO v1 and v2's internal timer is stored as ticks which decrement
* every 0.6 seconds. v3's internal timer is stored as seconds (some
* datasheets incorrectly state 0.6 seconds).
*/
static inline unsigned int seconds_to_ticks(int secs)
{
/* the internal timer is stored as ticks which decrement
* every 0.6 seconds */
return (seconds * 10) / 6;
return iTCO_wdt_private.iTCO_version == 3 ? secs : (secs * 10) / 6;
}
static inline unsigned int ticks_to_seconds(int ticks)
{
return iTCO_wdt_private.iTCO_version == 3 ? ticks : (ticks * 6) / 10;
}
static void iTCO_wdt_set_NO_REBOOT_bit(void)
@@ -137,10 +148,14 @@ static void iTCO_wdt_set_NO_REBOOT_bit(void)
u32 val32;
/* Set the NO_REBOOT bit: this disables reboots */
if (iTCO_wdt_private.iTCO_version == 2) {
val32 = readl(iTCO_wdt_private.gcs);
if (iTCO_wdt_private.iTCO_version == 3) {
val32 = readl(iTCO_wdt_private.gcs_pmc);
val32 |= 0x00000010;
writel(val32, iTCO_wdt_private.gcs_pmc);
} else if (iTCO_wdt_private.iTCO_version == 2) {
val32 = readl(iTCO_wdt_private.gcs_pmc);
val32 |= 0x00000020;
writel(val32, iTCO_wdt_private.gcs);
writel(val32, iTCO_wdt_private.gcs_pmc);
} else if (iTCO_wdt_private.iTCO_version == 1) {
pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
val32 |= 0x00000002;
@@ -154,12 +169,20 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void)
u32 val32;
/* Unset the NO_REBOOT bit: this enables reboots */
if (iTCO_wdt_private.iTCO_version == 2) {
val32 = readl(iTCO_wdt_private.gcs);
val32 &= 0xffffffdf;
writel(val32, iTCO_wdt_private.gcs);
if (iTCO_wdt_private.iTCO_version == 3) {
val32 = readl(iTCO_wdt_private.gcs_pmc);
val32 &= 0xffffffef;
writel(val32, iTCO_wdt_private.gcs_pmc);
val32 = readl(iTCO_wdt_private.gcs);
val32 = readl(iTCO_wdt_private.gcs_pmc);
if (val32 & 0x00000010)
ret = -EIO;
} else if (iTCO_wdt_private.iTCO_version == 2) {
val32 = readl(iTCO_wdt_private.gcs_pmc);
val32 &= 0xffffffdf;
writel(val32, iTCO_wdt_private.gcs_pmc);
val32 = readl(iTCO_wdt_private.gcs_pmc);
if (val32 & 0x00000020)
ret = -EIO;
} else if (iTCO_wdt_private.iTCO_version == 1) {
@@ -192,7 +215,7 @@ static int iTCO_wdt_start(struct watchdog_device *wd_dev)
/* Force the timer to its reload value by writing to the TCO_RLD
register */
if (iTCO_wdt_private.iTCO_version == 2)
if (iTCO_wdt_private.iTCO_version >= 2)
outw(0x01, TCO_RLD);
else if (iTCO_wdt_private.iTCO_version == 1)
outb(0x01, TCO_RLD);
@@ -240,9 +263,9 @@ static int iTCO_wdt_ping(struct watchdog_device *wd_dev)
iTCO_vendor_pre_keepalive(iTCO_wdt_private.smi_res, wd_dev->timeout);
/* Reload the timer by writing to the TCO Timer Counter register */
if (iTCO_wdt_private.iTCO_version == 2)
if (iTCO_wdt_private.iTCO_version >= 2) {
outw(0x01, TCO_RLD);
else if (iTCO_wdt_private.iTCO_version == 1) {
} else if (iTCO_wdt_private.iTCO_version == 1) {
/* Reset the timeout status bit so that the timer
* needs to count down twice again before rebooting */
outw(0x0008, TCO1_STS); /* write 1 to clear bit */
@@ -270,14 +293,14 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t)
/* "Values of 0h-3h are ignored and should not be attempted" */
if (tmrval < 0x04)
return -EINVAL;
if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
if (((iTCO_wdt_private.iTCO_version >= 2) && (tmrval > 0x3ff)) ||
((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
return -EINVAL;
iTCO_vendor_pre_set_heartbeat(tmrval);
/* Write new heartbeat to watchdog */
if (iTCO_wdt_private.iTCO_version == 2) {
if (iTCO_wdt_private.iTCO_version >= 2) {
spin_lock(&iTCO_wdt_private.io_lock);
val16 = inw(TCOv2_TMR);
val16 &= 0xfc00;
@@ -312,13 +335,13 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
unsigned int time_left = 0;
/* read the TCO Timer */
if (iTCO_wdt_private.iTCO_version == 2) {
if (iTCO_wdt_private.iTCO_version >= 2) {
spin_lock(&iTCO_wdt_private.io_lock);
val16 = inw(TCO_RLD);
val16 &= 0x3ff;
spin_unlock(&iTCO_wdt_private.io_lock);
time_left = (val16 * 6) / 10;
time_left = ticks_to_seconds(val16);
} else if (iTCO_wdt_private.iTCO_version == 1) {
spin_lock(&iTCO_wdt_private.io_lock);
val8 = inb(TCO_RLD);
@@ -327,7 +350,7 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
val8 += (inb(TCOv1_TMR) & 0x3f);
spin_unlock(&iTCO_wdt_private.io_lock);
time_left = (val8 * 6) / 10;
time_left = ticks_to_seconds(val8);
}
return time_left;
}
@@ -376,16 +399,16 @@ static void iTCO_wdt_cleanup(void)
resource_size(iTCO_wdt_private.tco_res));
release_region(iTCO_wdt_private.smi_res->start,
resource_size(iTCO_wdt_private.smi_res));
if (iTCO_wdt_private.iTCO_version == 2) {
iounmap(iTCO_wdt_private.gcs);
release_mem_region(iTCO_wdt_private.gcs_res->start,
resource_size(iTCO_wdt_private.gcs_res));
if (iTCO_wdt_private.iTCO_version >= 2) {
iounmap(iTCO_wdt_private.gcs_pmc);
release_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
resource_size(iTCO_wdt_private.gcs_pmc_res));
}
iTCO_wdt_private.tco_res = NULL;
iTCO_wdt_private.smi_res = NULL;
iTCO_wdt_private.gcs_res = NULL;
iTCO_wdt_private.gcs = NULL;
iTCO_wdt_private.gcs_pmc_res = NULL;
iTCO_wdt_private.gcs_pmc = NULL;
}
static int iTCO_wdt_probe(struct platform_device *dev)
@@ -414,27 +437,27 @@ static int iTCO_wdt_probe(struct platform_device *dev)
iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent);
/*
* Get the Memory-Mapped GCS register, we need it for the
* NO_REBOOT flag (TCO v2).
* Get the Memory-Mapped GCS or PMC register, we need it for the
* NO_REBOOT flag (TCO v2 and v3).
*/
if (iTCO_wdt_private.iTCO_version == 2) {
iTCO_wdt_private.gcs_res = platform_get_resource(dev,
if (iTCO_wdt_private.iTCO_version >= 2) {
iTCO_wdt_private.gcs_pmc_res = platform_get_resource(dev,
IORESOURCE_MEM,
ICH_RES_MEM_GCS);
ICH_RES_MEM_GCS_PMC);
if (!iTCO_wdt_private.gcs_res)
if (!iTCO_wdt_private.gcs_pmc_res)
goto out;
if (!request_mem_region(iTCO_wdt_private.gcs_res->start,
resource_size(iTCO_wdt_private.gcs_res), dev->name)) {
if (!request_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
resource_size(iTCO_wdt_private.gcs_pmc_res), dev->name)) {
ret = -EBUSY;
goto out;
}
iTCO_wdt_private.gcs = ioremap(iTCO_wdt_private.gcs_res->start,
resource_size(iTCO_wdt_private.gcs_res));
if (!iTCO_wdt_private.gcs) {
iTCO_wdt_private.gcs_pmc = ioremap(iTCO_wdt_private.gcs_pmc_res->start,
resource_size(iTCO_wdt_private.gcs_pmc_res));
if (!iTCO_wdt_private.gcs_pmc) {
ret = -EIO;
goto unreg_gcs;
goto unreg_gcs_pmc;
}
}
@@ -442,7 +465,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
goto unmap_gcs;
goto unmap_gcs_pmc;
}
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
@@ -454,7 +477,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
pr_err("I/O address 0x%04llx already in use, device disabled\n",
(u64)SMI_EN);
ret = -EBUSY;
goto unmap_gcs;
goto unmap_gcs_pmc;
}
if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) {
/*
@@ -478,9 +501,13 @@ static int iTCO_wdt_probe(struct platform_device *dev)
ich_info->name, ich_info->iTCO_version, (u64)TCOBASE);
/* Clear out the (probably old) status */
outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
if (iTCO_wdt_private.iTCO_version == 3) {
outl(0x20008, TCO1_STS);
} else {
outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
}
iTCO_wdt_watchdog_dev.bootstatus = 0;
iTCO_wdt_watchdog_dev.timeout = WATCHDOG_TIMEOUT;
@@ -515,18 +542,18 @@ unreg_tco:
unreg_smi:
release_region(iTCO_wdt_private.smi_res->start,
resource_size(iTCO_wdt_private.smi_res));
unmap_gcs:
if (iTCO_wdt_private.iTCO_version == 2)
iounmap(iTCO_wdt_private.gcs);
unreg_gcs:
if (iTCO_wdt_private.iTCO_version == 2)
release_mem_region(iTCO_wdt_private.gcs_res->start,
resource_size(iTCO_wdt_private.gcs_res));
unmap_gcs_pmc:
if (iTCO_wdt_private.iTCO_version >= 2)
iounmap(iTCO_wdt_private.gcs_pmc);
unreg_gcs_pmc:
if (iTCO_wdt_private.iTCO_version >= 2)
release_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
resource_size(iTCO_wdt_private.gcs_pmc_res));
out:
iTCO_wdt_private.tco_res = NULL;
iTCO_wdt_private.smi_res = NULL;
iTCO_wdt_private.gcs_res = NULL;
iTCO_wdt_private.gcs = NULL;
iTCO_wdt_private.gcs_pmc_res = NULL;
iTCO_wdt_private.gcs_pmc = NULL;
return ret;
}