Skip to content

Commit

Permalink
mfd: watchdog: iTCO_wdt: Expose watchdog properties using platform data
Browse files Browse the repository at this point in the history
Intel Sunrisepoint (Skylake PCH) has the iTCO watchdog accessible across
the SMBus, unlike previous generations of PCH/ICH where it was on the
LPC bus. Because it's on the SMBus, it doesn't make sense to pass around
a 'struct lpc_ich_info', and leaking the type of bus into the iTCO
watchdog driver is kind of backwards anyway.

This change introduces a new 'struct itco_wdt_platform_data' for use
inside the iTCO watchdog driver and by the upcoming Intel Sunrisepoint
code, which neatly avoids having to include lpc_ich headers in the i801
i2c driver.

This change is overdue because lpc_ich_info has already found its way
into other TCO watchdog users, notably the intel_pmc_ipc driver where
the watchdog actually isn't on the LPC bus as far as I can see.

A simple translation layer is provided for converting from the existing
'struct lpc_ich_info' inside the lpc_ich mfd driver.

Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Acked-by: Darren Hart <dvhart@linux.intel.com> [drivers/x86 refactoring]
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
  • Loading branch information
Matt Fleming authored and Lee Jones committed Aug 11, 2015
1 parent bc0195a commit 420b54d
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 20 deletions.
32 changes: 29 additions & 3 deletions drivers/mfd/lpc_ich.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include <linux/pci.h>
#include <linux/mfd/core.h>
#include <linux/mfd/lpc_ich.h>
#include <linux/platform_data/itco_wdt.h>

#define ACPIBASE 0x40
#define ACPIBASE_GPE_OFF 0x28
Expand Down Expand Up @@ -835,9 +836,31 @@ static void lpc_ich_enable_pmc_space(struct pci_dev *dev)
priv->actrl_pbase_save = reg_save;
}

static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell)
static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev)
{
struct itco_wdt_platform_data *pdata;
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
struct lpc_ich_info *info;
struct mfd_cell *cell = &lpc_ich_cells[LPC_WDT];

pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;

info = &lpc_chipset_info[priv->chipset];

pdata->version = info->iTCO_version;
strlcpy(pdata->name, info->name, sizeof(pdata->name));

cell->platform_data = pdata;
cell->pdata_size = sizeof(*pdata);
return 0;
}

static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev)
{
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
struct mfd_cell *cell = &lpc_ich_cells[LPC_GPIO];

cell->platform_data = &lpc_chipset_info[priv->chipset];
cell->pdata_size = sizeof(struct lpc_ich_info);
Expand Down Expand Up @@ -933,7 +956,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
lpc_chipset_info[priv->chipset].use_gpio = ret;
lpc_ich_enable_gpio_space(dev);

lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_GPIO]);
lpc_ich_finalize_gpio_cell(dev);
ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
&lpc_ich_cells[LPC_GPIO], 1, NULL, 0, NULL);

Expand Down Expand Up @@ -1007,7 +1030,10 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
res->end = base_addr + ACPIBASE_PMC_END;
}

lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]);
ret = lpc_ich_finalize_wdt_cell(dev);
if (ret)
goto wdt_done;

ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
&lpc_ich_cells[LPC_WDT], 1, NULL, 0, NULL);

Expand Down
9 changes: 4 additions & 5 deletions drivers/platform/x86/intel_pmc_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include <linux/suspend.h>
#include <linux/acpi.h>
#include <asm/intel_pmc_ipc.h>
#include <linux/mfd/lpc_ich.h>
#include <linux/platform_data/itco_wdt.h>

/*
* IPC registers
Expand Down Expand Up @@ -460,9 +460,9 @@ static struct resource tco_res[] = {
},
};

static struct lpc_ich_info tco_info = {
static struct itco_wdt_platform_data tco_info = {
.name = "Apollo Lake SoC",
.iTCO_version = 3,
.version = 3,
};

static int ipc_create_punit_device(void)
Expand Down Expand Up @@ -539,8 +539,7 @@ static int ipc_create_tco_device(void)
goto err;
}

ret = platform_device_add_data(pdev, &tco_info,
sizeof(struct lpc_ich_info));
ret = platform_device_add_data(pdev, &tco_info, sizeof(tco_info));
if (ret) {
dev_err(ipcdev.dev, "Failed to add tco platform data\n");
goto err;
Expand Down
11 changes: 5 additions & 6 deletions drivers/watchdog/iTCO_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@
#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
#include <linux/io.h> /* For inb/outb/... */
#include <linux/mfd/core.h>
#include <linux/mfd/lpc_ich.h>
#include <linux/platform_data/itco_wdt.h>

#include "iTCO_vendor.h"

Expand Down Expand Up @@ -418,9 +417,9 @@ static int iTCO_wdt_probe(struct platform_device *dev)
{
int ret = -ENODEV;
unsigned long val32;
struct lpc_ich_info *ich_info = dev_get_platdata(&dev->dev);
struct itco_wdt_platform_data *pdata = dev_get_platdata(&dev->dev);

if (!ich_info)
if (!pdata)
goto out;

spin_lock_init(&iTCO_wdt_private.io_lock);
Expand All @@ -435,7 +434,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
if (!iTCO_wdt_private.smi_res)
goto out;

iTCO_wdt_private.iTCO_version = ich_info->iTCO_version;
iTCO_wdt_private.iTCO_version = pdata->version;
iTCO_wdt_private.dev = dev;
iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent);

Expand Down Expand Up @@ -501,7 +500,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
}

pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n",
ich_info->name, ich_info->iTCO_version, (u64)TCOBASE);
pdata->name, pdata->version, (u64)TCOBASE);

/* Clear out the (probably old) status */
if (iTCO_wdt_private.iTCO_version == 3) {
Expand Down
6 changes: 0 additions & 6 deletions include/linux/mfd/lpc_ich.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@
#ifndef LPC_ICH_H
#define LPC_ICH_H

/* Watchdog resources */
#define ICH_RES_IO_TCO 0
#define ICH_RES_IO_SMI 1
#define ICH_RES_MEM_OFF 2
#define ICH_RES_MEM_GCS_PMC 0

/* GPIO resources */
#define ICH_RES_GPIO 0
#define ICH_RES_GPE0 1
Expand Down
19 changes: 19 additions & 0 deletions include/linux/platform_data/itco_wdt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Platform data for the Intel TCO Watchdog
*/

#ifndef _ITCO_WDT_H_
#define _ITCO_WDT_H_

/* Watchdog resources */
#define ICH_RES_IO_TCO 0
#define ICH_RES_IO_SMI 1
#define ICH_RES_MEM_OFF 2
#define ICH_RES_MEM_GCS_PMC 0

struct itco_wdt_platform_data {
char name[32];
unsigned int version;
};

#endif /* _ITCO_WDT_H_ */

0 comments on commit 420b54d

Please sign in to comment.