Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 420b54de authored by Matt Fleming's avatar Matt Fleming Committed by Lee Jones
Browse files

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: default avatarMatt Fleming <matt.fleming@intel.com>
Acked-by: Darren Hart <dvhart@linux.intel.com> [drivers/x86 refactoring]
Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent bc0195aa
Loading
Loading
Loading
Loading
+29 −3
Original line number Diff line number Diff line
@@ -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
@@ -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);
@@ -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);

@@ -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);

+4 −5
Original line number Diff line number Diff line
@@ -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
@@ -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)
@@ -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;
+5 −6
Original line number Diff line number Diff line
@@ -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"

@@ -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);
@@ -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);

@@ -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) {
+0 −6
Original line number Diff line number Diff line
@@ -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
+19 −0
Original line number Diff line number Diff line
/*
 * 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_ */