// SPDX-License-Identifier: GPL-2.0-only
/*
* lpc_ich.c - LPC interface for Intel ICH
*
* LPC bridge function of the Intel ICH contains many other
* functional units, such as Interrupt controllers, Timers,
* Power Management, System Management, GPIO, RTC, and LPC
* Configuration Registers.
*
* This driver is derived from lpc_sch.
* Copyright (c) 2011 Extreme Engineering Solution, Inc.
* Author: Aaron Sierra <asierra@xes-inc.com>
*
* This driver supports the following I/O Controller hubs:
* (See the intel documentation on http://developer.intel.com.)
* document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO)
* document number 290687-002, 298242-027: 82801BA (ICH2)
* document number 290733-003, 290739-013: 82801CA (ICH3-S)
* document number 290716-001, 290718-007: 82801CAM (ICH3-M)
* document number 290744-001, 290745-025: 82801DB (ICH4)
* document number 252337-001, 252663-008: 82801DBM (ICH4-M)
* document number 273599-001, 273645-002: 82801E (C-ICH)
* document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R)
* document number 300641-004, 300884-013: 6300ESB
* document number 301473-002, 301474-026: 82801F (ICH6)
* document number 313082-001, 313075-006: 631xESB, 632xESB
* document number 307013-003, 307014-024: 82801G (ICH7)
* document number 322896-001, 322897-001: NM10
* document number 313056-003, 313057-017: 82801H (ICH8)
* document number 316972-004, 316973-012: 82801I (ICH9)
* document number 319973-002, 319974-002: 82801J (ICH10)
* document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
* document number 320066-003, 320257-008: EP80597 (IICH)
* document number 324645-001, 324646-001: Cougar Point (CPT)
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/acpi.h>
#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
#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_PMCBASE 0x44
#define ACPIBASE_GCS_OFF 0x3410
#define ACPIBASE_GCS_END 0x3414
#define SPIBASE_BYT 0x54
#define SPIBASE_BYT_SZ 512
#define SPIBASE_BYT_EN BIT(1)
#define SPIBASE_LPT 0x3800
#define SPIBASE_LPT_SZ 512
#define BCR 0xdc
#define BCR_WPD BIT(0)
#define SPIBASE_APL_SZ 4096
#define GPIOBASE_ICH0 0x58
#define GPIOCTRL_ICH0 0x5C
#define GPIOBASE_ICH6 0x48
#define GPIOCTRL_ICH6 0x4C
#define RCBABASE 0xf0
#define wdt_io_res(i) wdt_res(0, i)
#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_priv {
int chipset;
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[] = {
/* ACPI - TCO */
{
.flags = IORESOURCE_IO,
},
/* ACPI - SMI */
{
.flags = IORESOURCE_IO,
},
/* GCS or PMC */
{
.flags = IORESOURCE_MEM,
},
};
static struct resource gpio_ich_res[] = {
/* GPIO */
{
.flags = IORESOURCE_IO,
},
/* ACPI - GPE0 */
{
.flags = IORESOURCE_IO,
},
};
static struct resource intel_spi_res[] = {
{
.flags = IORESOURCE_MEM,
}
};
static struct mfd_cell lpc_ich_wdt_cell = {
.name = "iTCO_wdt",
.num_resources = ARRAY_SIZE(wdt_ich_res),
.resources = wdt_ich_res,
.ignore_resource_conflicts = true,
};
static struct mfd_cell lpc_ich_gpio_cell = {
.name = "gpio_ich",
.num_resources = ARRAY_SIZE(gpio_ich_res),
.resources = gpio_ich_res,
.ignore_resource_conflicts = true,
};
static struct mfd_cell lpc_ich_spi_cell = {
.name = "intel-spi",
.num_resources = ARRAY_SIZE(intel_spi_res),
.resources = intel_spi_res,
.ignore_resource_conflicts = true,
};
/* chipset related info */
enum lpc_chipsets {
LPC_ICH = 0, /* ICH */
LPC_ICH0, /* ICH0 */
LPC_ICH2, /* ICH2 */
LPC_ICH2M, /* ICH2-M */
LPC_ICH3, /* ICH3-S */
LPC_ICH3M, /* ICH3-M */
LPC_ICH4, /* ICH4 */
LPC_ICH4M, /* ICH4-M */
LPC_CICH, /* C-ICH */
LPC_ICH5, /* ICH5 & ICH5R */
LPC_6300ESB, /* 6300ESB */
LPC_ICH6, /* ICH6 & ICH6R */
LPC_ICH6M, /* ICH6-M */
LPC_ICH6W, /* ICH6W & ICH6RW */
LPC_631XESB, /* 631xESB/632xESB */
LPC_ICH7, /* ICH7 & ICH7R */
LPC_ICH7DH, /* ICH7DH */
LPC_ICH7M, /* ICH7-M & ICH7-U */
LPC_ICH7MDH, /* ICH7-M DH */
LPC_NM10, /* NM10 */
LPC_ICH8, /* ICH8 & ICH8R */
LPC_ICH8DH, /* ICH8DH */
LPC_ICH8DO, /* ICH8DO */
LPC_ICH8M, /* ICH8M */
LPC_ICH8ME, /* ICH8M-E */
LPC_ICH9, /* ICH9 */
LPC_ICH9R, /* ICH9R */
LPC_ICH9DH, /* ICH9DH */
LPC_ICH9DO, /* ICH9DO */
LPC_ICH9M, /* ICH9M */
LPC_ICH9ME, /* ICH9M-E */
LPC_ICH10, /* ICH10 */
LPC_ICH10R, /* ICH10R */
LPC_ICH10D, /* ICH10D */
LPC_ICH10DO, /* ICH10DO */
LPC_PCH,