mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 13:53:33 +00:00
mfd: watchdog: iTCO_wdt: Expose watchdog properties using platform data
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>
This commit is contained in:
parent
bc0195aad0
commit
420b54de25
5 changed files with 57 additions and 20 deletions
|
@ -66,6 +66,7 @@
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/mfd/core.h>
|
#include <linux/mfd/core.h>
|
||||||
#include <linux/mfd/lpc_ich.h>
|
#include <linux/mfd/lpc_ich.h>
|
||||||
|
#include <linux/platform_data/itco_wdt.h>
|
||||||
|
|
||||||
#define ACPIBASE 0x40
|
#define ACPIBASE 0x40
|
||||||
#define ACPIBASE_GPE_OFF 0x28
|
#define ACPIBASE_GPE_OFF 0x28
|
||||||
|
@ -835,9 +836,31 @@ static void lpc_ich_enable_pmc_space(struct pci_dev *dev)
|
||||||
priv->actrl_pbase_save = reg_save;
|
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 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->platform_data = &lpc_chipset_info[priv->chipset];
|
||||||
cell->pdata_size = sizeof(struct lpc_ich_info);
|
cell->pdata_size = sizeof(struct lpc_ich_info);
|
||||||
|
@ -933,7 +956,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
|
||||||
lpc_chipset_info[priv->chipset].use_gpio = ret;
|
lpc_chipset_info[priv->chipset].use_gpio = ret;
|
||||||
lpc_ich_enable_gpio_space(dev);
|
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,
|
ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
|
||||||
&lpc_ich_cells[LPC_GPIO], 1, NULL, 0, NULL);
|
&lpc_ich_cells[LPC_GPIO], 1, NULL, 0, NULL);
|
||||||
|
|
||||||
|
@ -1007,7 +1030,10 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
|
||||||
res->end = base_addr + ACPIBASE_PMC_END;
|
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,
|
ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
|
||||||
&lpc_ich_cells[LPC_WDT], 1, NULL, 0, NULL);
|
&lpc_ich_cells[LPC_WDT], 1, NULL, 0, NULL);
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <asm/intel_pmc_ipc.h>
|
#include <asm/intel_pmc_ipc.h>
|
||||||
#include <linux/mfd/lpc_ich.h>
|
#include <linux/platform_data/itco_wdt.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IPC registers
|
* IPC registers
|
||||||
|
@ -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",
|
.name = "Apollo Lake SoC",
|
||||||
.iTCO_version = 3,
|
.version = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ipc_create_punit_device(void)
|
static int ipc_create_punit_device(void)
|
||||||
|
@ -539,8 +539,7 @@ static int ipc_create_tco_device(void)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = platform_device_add_data(pdev, &tco_info,
|
ret = platform_device_add_data(pdev, &tco_info, sizeof(tco_info));
|
||||||
sizeof(struct lpc_ich_info));
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(ipcdev.dev, "Failed to add tco platform data\n");
|
dev_err(ipcdev.dev, "Failed to add tco platform data\n");
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -66,8 +66,7 @@
|
||||||
#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
|
#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
|
||||||
#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
|
#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
|
||||||
#include <linux/io.h> /* For inb/outb/... */
|
#include <linux/io.h> /* For inb/outb/... */
|
||||||
#include <linux/mfd/core.h>
|
#include <linux/platform_data/itco_wdt.h>
|
||||||
#include <linux/mfd/lpc_ich.h>
|
|
||||||
|
|
||||||
#include "iTCO_vendor.h"
|
#include "iTCO_vendor.h"
|
||||||
|
|
||||||
|
@ -418,9 +417,9 @@ static int iTCO_wdt_probe(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
unsigned long val32;
|
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;
|
goto out;
|
||||||
|
|
||||||
spin_lock_init(&iTCO_wdt_private.io_lock);
|
spin_lock_init(&iTCO_wdt_private.io_lock);
|
||||||
|
@ -435,7 +434,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
|
||||||
if (!iTCO_wdt_private.smi_res)
|
if (!iTCO_wdt_private.smi_res)
|
||||||
goto out;
|
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.dev = dev;
|
||||||
iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent);
|
iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent);
|
||||||
|
|
||||||
|
@ -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",
|
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 */
|
/* Clear out the (probably old) status */
|
||||||
if (iTCO_wdt_private.iTCO_version == 3) {
|
if (iTCO_wdt_private.iTCO_version == 3) {
|
||||||
|
|
|
@ -20,12 +20,6 @@
|
||||||
#ifndef LPC_ICH_H
|
#ifndef LPC_ICH_H
|
||||||
#define 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 */
|
/* GPIO resources */
|
||||||
#define ICH_RES_GPIO 0
|
#define ICH_RES_GPIO 0
|
||||||
#define ICH_RES_GPE0 1
|
#define ICH_RES_GPE0 1
|
||||||
|
|
19
include/linux/platform_data/itco_wdt.h
Normal file
19
include/linux/platform_data/itco_wdt.h
Normal file
|
@ -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_ */
|
Loading…
Reference in a new issue