summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2021-02-03 13:25:28 +0300
committerHans de Goede <hdegoede@redhat.com>2021-02-03 13:25:28 +0300
commita40f530e77df61d8c91b24efbd357bda43bd3f14 (patch)
tree128ff6751d36dd117dbf8a36121889641bcfdde6 /drivers
parentfa707a580e77765b968925e4135f8d8c887eb38b (diff)
parenta507e5d90f3d6846a02d9c2c79e6f6395982db92 (diff)
downloadlinux-a40f530e77df61d8c91b24efbd357bda43bd3f14.tar.xz
Merge tag 'ib-drm-gpio-pdx86-rtc-wdt-v5.12-1' into for-next
ib-drm-gpio-pdx86-rtc-wdt for v5.12-1 First part of Intel MID outdated platforms removal. The following is an automated git shortlog grouped by driver: drm/gma500: - Get rid of duplicate NULL checks - Convert to use new SCU IPC API gpio: - msic: Remove driver for deprecated platform - intel-mid: Remove driver for deprecated platform intel_mid_powerbtn: - Remove driver for deprecated platform intel_mid_thermal: - Remove driver for deprecated platform intel_scu_wdt: - Get rid of custom x86 model comparison - Drop SCU notification - Move driver from arch/x86 rtc: - mrst: Remove driver for deprecated platform watchdog: - intel-mid_wdt: Postpone IRQ handler registration till SCU is ready - intel_scu_watchdog: Remove driver for deprecated platform
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig14
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/TODO2
-rw-r--r--drivers/gpio/gpio-intel-mid.c414
-rw-r--r--drivers/gpio/gpio-msic.c314
-rw-r--r--drivers/gpu/drm/gma500/Kconfig1
-rw-r--r--drivers/gpu/drm/gma500/mdfld_device.c2
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_output.c2
-rw-r--r--drivers/gpu/drm/gma500/mdfld_output.c8
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_device.c3
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h3
-rw-r--r--drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c30
-rw-r--r--drivers/platform/x86/Kconfig8
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/intel_scu_wdt.c75
-rw-r--r--drivers/rtc/Kconfig12
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-mrst.c521
-rw-r--r--drivers/watchdog/Kconfig9
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/intel-mid_wdt.c8
-rw-r--r--drivers/watchdog/intel_scu_watchdog.c533
-rw-r--r--drivers/watchdog/intel_scu_watchdog.h50
23 files changed, 112 insertions, 1901 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c70f46e80a3b..a6987ff28d7c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1249,13 +1249,6 @@ config GPIO_MAX77650
GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor.
These chips have a single pin that can be configured as GPIO.
-config GPIO_MSIC
- bool "Intel MSIC mixed signal gpio support"
- depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC
- help
- Enable support for GPIO on intel MSIC controllers found in
- intel MID devices
-
config GPIO_PALMAS
bool "TI PALMAS series PMICs GPIO"
depends on MFD_PALMAS
@@ -1451,13 +1444,6 @@ config GPIO_BT8XX
If unsure, say N.
-config GPIO_INTEL_MID
- bool "Intel MID GPIO support"
- depends on X86_INTEL_MID
- select GPIOLIB_IRQCHIP
- help
- Say Y here to support Intel MID GPIO.
-
config GPIO_MERRIFIELD
tristate "Intel Merrifield GPIO support"
depends on X86_INTEL_MID
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 35e3b6026665..a2106d667fb3 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -67,7 +67,6 @@ obj-$(CONFIG_GPIO_HISI) += gpio-hisi.o
obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
-obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO
index 0229fa79499e..b8b1473a5b1e 100644
--- a/drivers/gpio/TODO
+++ b/drivers/gpio/TODO
@@ -101,7 +101,7 @@ for a few GPIOs. Those should stay where they are.
At the same time it makes sense to get rid of code duplication in existing or
new coming drivers. For example, gpio-ml-ioh should be incorporated into
-gpio-pch. In similar way gpio-intel-mid into gpio-pxa.
+gpio-pch.
Generic MMIO GPIO
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
deleted file mode 100644
index 86a10c808ef6..000000000000
--- a/drivers/gpio/gpio-intel-mid.c
+++ /dev/null
@@ -1,414 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Intel MID GPIO driver
- *
- * Copyright (c) 2008-2014,2016 Intel Corporation.
- */
-
-/* Supports:
- * Moorestown platform Langwell chip.
- * Medfield platform Penwell chip.
- * Clovertrail platform Cloverview chip.
- */
-
-#include <linux/delay.h>
-#include <linux/gpio/driver.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/stddef.h>
-
-#define INTEL_MID_IRQ_TYPE_EDGE (1 << 0)
-#define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1)
-
-/*
- * Langwell chip has 64 pins and thus there are 2 32bit registers to control
- * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
- * registers to control them, so we only define the order here instead of a
- * structure, to get a bit offset for a pin (use GPDR as an example):
- *
- * nreg = ngpio / 32;
- * reg = offset / 32;
- * bit = offset % 32;
- * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
- *
- * so the bit of reg_addr is to control pin offset's GPDR feature
-*/
-
-enum GPIO_REG {
- GPLR = 0, /* pin level read-only */
- GPDR, /* pin direction */
- GPSR, /* pin set */
- GPCR, /* pin clear */
- GRER, /* rising edge detect */
- GFER, /* falling edge detect */
- GEDR, /* edge detect result */
- GAFR, /* alt function */
-};
-
-/* intel_mid gpio driver data */
-struct intel_mid_gpio_ddata {
- u16 ngpio; /* number of gpio pins */
- u32 chip_irq_type; /* chip interrupt type */
-};
-
-struct intel_mid_gpio {
- struct gpio_chip chip;
- void __iomem *reg_base;
- spinlock_t lock;
- struct pci_dev *pdev;
-};
-
-static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
- enum GPIO_REG reg_type)
-{
- struct intel_mid_gpio *priv = gpiochip_get_data(chip);
- unsigned nreg = chip->ngpio / 32;
- u8 reg = offset / 32;
-
- return priv->reg_base + reg_type * nreg * 4 + reg * 4;
-}
-
-static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
- enum GPIO_REG reg_type)
-{
- struct intel_mid_gpio *priv = gpiochip_get_data(chip);
- unsigned nreg = chip->ngpio / 32;
- u8 reg = offset / 16;
-
- return priv->reg_base + reg_type * nreg * 4 + reg * 4;
-}
-
-static int intel_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
- u32 value = readl(gafr);
- int shift = (offset % 16) << 1, af = (value >> shift) & 3;
-
- if (af) {
- value &= ~(3 << shift);
- writel(value, gafr);
- }
- return 0;
-}
-
-static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- void __iomem *gplr = gpio_reg(chip, offset, GPLR);
-
- return !!(readl(gplr) & BIT(offset % 32));
-}
-
-static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- void __iomem *gpsr, *gpcr;
-
- if (value) {
- gpsr = gpio_reg(chip, offset, GPSR);
- writel(BIT(offset % 32), gpsr);
- } else {
- gpcr = gpio_reg(chip, offset, GPCR);
- writel(BIT(offset % 32), gpcr);
- }
-}
-
-static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- struct intel_mid_gpio *priv = gpiochip_get_data(chip);
- void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
- u32 value;
- unsigned long flags;
-
- if (priv->pdev)
- pm_runtime_get(&priv->pdev->dev);
-
- spin_lock_irqsave(&priv->lock, flags);
- value = readl(gpdr);
- value &= ~BIT(offset % 32);
- writel(value, gpdr);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (priv->pdev)
- pm_runtime_put(&priv->pdev->dev);
-
- return 0;
-}
-
-static int intel_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- struct intel_mid_gpio *priv = gpiochip_get_data(chip);
- void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
- unsigned long flags;
-
- intel_gpio_set(chip, offset, value);
-
- if (priv->pdev)
- pm_runtime_get(&priv->pdev->dev);
-
- spin_lock_irqsave(&priv->lock, flags);
- value = readl(gpdr);
- value |= BIT(offset % 32);
- writel(value, gpdr);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (priv->pdev)
- pm_runtime_put(&priv->pdev->dev);
-
- return 0;
-}
-
-static int intel_mid_irq_type(struct irq_data *d, unsigned type)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct intel_mid_gpio *priv = gpiochip_get_data(gc);
- u32 gpio = irqd_to_hwirq(d);
- unsigned long flags;
- u32 value;
- void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER);
- void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER);
-
- if (gpio >= priv->chip.ngpio)
- return -EINVAL;
-
- if (priv->pdev)
- pm_runtime_get(&priv->pdev->dev);
-
- spin_lock_irqsave(&priv->lock, flags);
- if (type & IRQ_TYPE_EDGE_RISING)
- value = readl(grer) | BIT(gpio % 32);
- else
- value = readl(grer) & (~BIT(gpio % 32));
- writel(value, grer);
-
- if (type & IRQ_TYPE_EDGE_FALLING)
- value = readl(gfer) | BIT(gpio % 32);
- else
- value = readl(gfer) & (~BIT(gpio % 32));
- writel(value, gfer);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (priv->pdev)
- pm_runtime_put(&priv->pdev->dev);
-
- return 0;
-}
-
-static void intel_mid_irq_unmask(struct irq_data *d)
-{
-}
-
-static void intel_mid_irq_mask(struct irq_data *d)
-{
-}
-
-static struct irq_chip intel_mid_irqchip = {
- .name = "INTEL_MID-GPIO",
- .irq_mask = intel_mid_irq_mask,
- .irq_unmask = intel_mid_irq_unmask,
- .irq_set_type = intel_mid_irq_type,
-};
-
-static const struct intel_mid_gpio_ddata gpio_lincroft = {
- .ngpio = 64,
-};
-
-static const struct intel_mid_gpio_ddata gpio_penwell_aon = {
- .ngpio = 96,
- .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
-};
-
-static const struct intel_mid_gpio_ddata gpio_penwell_core = {
- .ngpio = 96,
- .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
-};
-
-static const struct intel_mid_gpio_ddata gpio_cloverview_aon = {
- .ngpio = 96,
- .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE | INTEL_MID_IRQ_TYPE_LEVEL,
-};
-
-static const struct intel_mid_gpio_ddata gpio_cloverview_core = {
- .ngpio = 96,
- .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
-};
-
-static const struct pci_device_id intel_gpio_ids[] = {
- {
- /* Lincroft */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f),
- .driver_data = (kernel_ulong_t)&gpio_lincroft,
- },
- {
- /* Penwell AON */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f),
- .driver_data = (kernel_ulong_t)&gpio_penwell_aon,
- },
- {
- /* Penwell Core */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a),
- .driver_data = (kernel_ulong_t)&gpio_penwell_core,
- },
- {
- /* Cloverview Aon */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb),
- .driver_data = (kernel_ulong_t)&gpio_cloverview_aon,
- },
- {
- /* Cloverview Core */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
- .driver_data = (kernel_ulong_t)&gpio_cloverview_core,
- },
- { }
-};
-
-static void intel_mid_irq_handler(struct irq_desc *desc)
-{
- struct gpio_chip *gc = irq_desc_get_handler_data(desc);
- struct intel_mid_gpio *priv = gpiochip_get_data(gc);
- struct irq_data *data = irq_desc_get_irq_data(desc);
- struct irq_chip *chip = irq_data_get_irq_chip(data);
- u32 base, gpio, mask;
- unsigned long pending;
- void __iomem *gedr;
-
- /* check GPIO controller to check which pin triggered the interrupt */
- for (base = 0; base < priv->chip.ngpio; base += 32) {
- gedr = gpio_reg(&priv->chip, base, GEDR);
- while ((pending = readl(gedr))) {
- gpio = __ffs(pending);
- mask = BIT(gpio);
- /* Clear before handling so we can't lose an edge */
- writel(mask, gedr);
- generic_handle_irq(irq_find_mapping(gc->irq.domain,
- base + gpio));
- }
- }
-
- chip->irq_eoi(data);
-}
-
-static int intel_mid_irq_init_hw(struct gpio_chip *chip)
-{
- struct intel_mid_gpio *priv = gpiochip_get_data(chip);
- void __iomem *reg;
- unsigned base;
-
- for (base = 0; base < priv->chip.ngpio; base += 32) {
- /* Clear the rising-edge detect register */
- reg = gpio_reg(&priv->chip, base, GRER);
- writel(0, reg);
- /* Clear the falling-edge detect register */
- reg = gpio_reg(&priv->chip, base, GFER);
- writel(0, reg);
- /* Clear the edge detect status register */
- reg = gpio_reg(&priv->chip, base, GEDR);
- writel(~0, reg);
- }
-
- return 0;
-}
-
-static int __maybe_unused intel_gpio_runtime_idle(struct device *dev)
-{
- int err = pm_schedule_suspend(dev, 500);
- return err ?: -EBUSY;
-}
-
-static const struct dev_pm_ops intel_gpio_pm_ops = {
- SET_RUNTIME_PM_OPS(NULL, NULL, intel_gpio_runtime_idle)
-};
-
-static int intel_gpio_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- void __iomem *base;
- struct intel_mid_gpio *priv;
- u32 gpio_base;
- u32 irq_base;
- int retval;
- struct gpio_irq_chip *girq;
- struct intel_mid_gpio_ddata *ddata =
- (struct intel_mid_gpio_ddata *)id->driver_data;
-
- retval = pcim_enable_device(pdev);
- if (retval)
- return retval;
-
- retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
- if (retval) {
- dev_err(&pdev->dev, "I/O memory mapping error\n");
- return retval;
- }
-
- base = pcim_iomap_table(pdev)[1];
-
- irq_base = readl(base);
- gpio_base = readl(sizeof(u32) + base);
-
- /* release the IO mapping, since we already get the info from bar1 */
- pcim_iounmap_regions(pdev, 1 << 1);
-
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->reg_base = pcim_iomap_table(pdev)[0];
- priv->chip.label = dev_name(&pdev->dev);
- priv->chip.parent = &pdev->dev;
- priv->chip.request = intel_gpio_request;
- priv->chip.direction_input = intel_gpio_direction_input;
- priv->chip.direction_output = intel_gpio_direction_output;
- priv->chip.get = intel_gpio_get;
- priv->chip.set = intel_gpio_set;
- priv->chip.base = gpio_base;
- priv->chip.ngpio = ddata->ngpio;
- priv->chip.can_sleep = false;
- priv->pdev = pdev;
-
- spin_lock_init(&priv->lock);
-
- girq = &priv->chip.irq;
- girq->chip = &intel_mid_irqchip;
- girq->init_hw = intel_mid_irq_init_hw;
- girq->parent_handler = intel_mid_irq_handler;
- girq->num_parents = 1;
- girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
- sizeof(*girq->parents),
- GFP_KERNEL);
- if (!girq->parents)
- return -ENOMEM;
- girq->parents[0] = pdev->irq;
- girq->first = irq_base;
- girq->default_type = IRQ_TYPE_NONE;
- girq->handler = handle_simple_irq;
-
- pci_set_drvdata(pdev, priv);
-
- retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
- if (retval) {
- dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
- return retval;
- }
-
- pm_runtime_put_noidle(&pdev->dev);
- pm_runtime_allow(&pdev->dev);
-
- return 0;
-}
-
-static struct pci_driver intel_gpio_driver = {
- .name = "intel_mid_gpio",
- .id_table = intel_gpio_ids,
- .probe = intel_gpio_probe,
- .driver = {
- .pm = &intel_gpio_pm_ops,
- },
-};
-
-builtin_pci_driver(intel_gpio_driver);
diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c
deleted file mode 100644
index 7e3c96e4ab2c..000000000000
--- a/drivers/gpio/gpio-msic.c
+++ /dev/null
@@ -1,314 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Intel Medfield MSIC GPIO driver>
- * Copyright (c) 2011, Intel Corporation.
- *
- * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
- * Based on intel_pmic_gpio.c
- */
-
-#include <linux/gpio/driver.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mfd/intel_msic.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/* the offset for the mapping of global gpio pin to irq */
-#define MSIC_GPIO_IRQ_OFFSET 0x100
-
-#define MSIC_GPIO_DIR_IN 0
-#define MSIC_GPIO_DIR_OUT BIT(5)
-#define MSIC_GPIO_TRIG_FALL BIT(1)
-#define MSIC_GPIO_TRIG_RISE BIT(2)
-
-/* masks for msic gpio output GPIOxxxxCTLO registers */
-#define MSIC_GPIO_DIR_MASK BIT(5)
-#define MSIC_GPIO_DRV_MASK BIT(4)
-#define MSIC_GPIO_REN_MASK BIT(3)
-#define MSIC_GPIO_RVAL_MASK (BIT(2) | BIT(1))
-#define MSIC_GPIO_DOUT_MASK BIT(0)
-
-/* masks for msic gpio input GPIOxxxxCTLI registers */
-#define MSIC_GPIO_GLBYP_MASK BIT(5)
-#define MSIC_GPIO_DBNC_MASK (BIT(4) | BIT(3))
-#define MSIC_GPIO_INTCNT_MASK (BIT(2) | BIT(1))
-#define MSIC_GPIO_DIN_MASK BIT(0)
-
-#define MSIC_NUM_GPIO 24
-
-struct msic_gpio {
- struct platform_device *pdev;
- struct mutex buslock;
- struct gpio_chip chip;
- int irq;
- unsigned irq_base;
- unsigned long trig_change_mask;
- unsigned trig_type;
-};
-
-/*
- * MSIC has 24 gpios, 16 low voltage (1.2-1.8v) and 8 high voltage (3v).
- * Both the high and low voltage gpios are divided in two banks.
- * GPIOs are numbered with GPIO0LV0 as gpio_base in the following order:
- * GPIO0LV0..GPIO0LV7: low voltage, bank 0, gpio_base
- * GPIO1LV0..GPIO1LV7: low voltage, bank 1, gpio_base + 8
- * GPIO0HV0..GPIO0HV3: high voltage, bank 0, gpio_base + 16
- * GPIO1HV0..GPIO1HV3: high voltage, bank 1, gpio_base + 20
- */
-
-static int msic_gpio_to_ireg(unsigned offset)
-{
- if (offset >= MSIC_NUM_GPIO)
- return -EINVAL;
-
- if (offset < 8)
- return INTEL_MSIC_GPIO0LV0CTLI - offset;
- if (offset < 16)
- return INTEL_MSIC_GPIO1LV0CTLI - offset + 8;
- if (offset < 20)
- return INTEL_MSIC_GPIO0HV0CTLI - offset + 16;
-
- return INTEL_MSIC_GPIO1HV0CTLI - offset + 20;
-}
-
-static int msic_gpio_to_oreg(unsigned offset)
-{
- if (offset >= MSIC_NUM_GPIO)
- return -EINVAL;
-
- if (offset < 8)
- return INTEL_MSIC_GPIO0LV0CTLO - offset;
- if (offset < 16)
- return INTEL_MSIC_GPIO1LV0CTLO - offset + 8;
- if (offset < 20)
- return INTEL_MSIC_GPIO0HV0CTLO - offset + 16;
-
- return INTEL_MSIC_GPIO1HV0CTLO - offset + 20;
-}
-
-static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- int reg;
-
- reg = msic_gpio_to_oreg(offset);
- if (reg < 0)
- return reg;
-
- return intel_msic_reg_update(reg, MSIC_GPIO_DIR_IN, MSIC_GPIO_DIR_MASK);
-}
-
-static int msic_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- int reg;
- unsigned mask;
-
- value = (!!value) | MSIC_GPIO_DIR_OUT;
- mask = MSIC_GPIO_DIR_MASK | MSIC_GPIO_DOUT_MASK;
-
- reg = msic_gpio_to_oreg(offset);
- if (reg < 0)
- return reg;
-
- return intel_msic_reg_update(reg, value, mask);
-}
-
-static int msic_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- u8 r;
- int ret;
- int reg;
-
- reg = msic_gpio_to_ireg(offset);
- if (reg < 0)
- return reg;
-
- ret = intel_msic_reg_read(reg, &r);
- if (ret < 0)
- return ret;
-
- return !!(r & MSIC_GPIO_DIN_MASK);
-}
-
-static void msic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- int reg;
-
- reg = msic_gpio_to_oreg(offset);
- if (reg < 0)
- return;
-
- intel_msic_reg_update(reg, !!value , MSIC_GPIO_DOUT_MASK);
-}
-
-/*
- * This is called from genirq with mg->buslock locked and
- * irq_desc->lock held. We can not access the scu bus here, so we
- * store the change and update in the bus_sync_unlock() function below
- */
-static int msic_irq_type(struct irq_data *data, unsigned type)
-{
- struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
- u32 gpio = data->irq - mg->irq_base;
-
- if (gpio >= mg->chip.ngpio)
- return -EINVAL;
-
- /* mark for which gpio the trigger changed, protected by buslock */
- mg->trig_change_mask |= (1 << gpio);
- mg->trig_type = type;
-
- return 0;
-}
-
-static int msic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct msic_gpio *mg = gpiochip_get_data(chip);
- return mg->irq_base + offset;
-}
-
-static void msic_bus_lock(struct irq_data *data)
-{
- struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
- mutex_lock(&mg->buslock);
-}
-
-static void msic_bus_sync_unlock(struct irq_data *data)
-{
- struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
- int offset;
- int reg;
- u8 trig = 0;
-
- /* We can only get one change at a time as the buslock covers the
- entire transaction. The irq_desc->lock is dropped before we are
- called but that is fine */
- if (mg->trig_change_mask) {
- offset = __ffs(mg->trig_change_mask);
-
- reg = msic_gpio_to_ireg(offset);
- if (reg < 0)
- goto out;
-
- if (mg->trig_type & IRQ_TYPE_EDGE_RISING)
- trig |= MSIC_GPIO_TRIG_RISE;
- if (mg->trig_type & IRQ_TYPE_EDGE_FALLING)
- trig |= MSIC_GPIO_TRIG_FALL;
-
- intel_msic_reg_update(reg, trig, MSIC_GPIO_INTCNT_MASK);
- mg->trig_change_mask = 0;
- }
-out:
- mutex_unlock(&mg->buslock);
-}
-
-/* Firmware does all the masking and unmasking for us, no masking here. */
-static void msic_irq_unmask(struct irq_data *data) { }
-
-static void msic_irq_mask(struct irq_data *data) { }
-
-static struct irq_chip msic_irqchip = {
- .name = "MSIC-GPIO",
- .irq_mask = msic_irq_mask,
- .irq_unmask = msic_irq_unmask,
- .irq_set_type = msic_irq_type,
- .irq_bus_lock = msic_bus_lock,
- .irq_bus_sync_unlock = msic_bus_sync_unlock,
-};
-
-static void msic_gpio_irq_handler(struct irq_desc *desc)
-{
- struct irq_data *data = irq_desc_get_irq_data(desc);
- struct msic_gpio *mg = irq_data_get_irq_handler_data(data);
- struct irq_chip *chip = irq_data_get_irq_chip(data);
- struct intel_msic *msic = pdev_to_intel_msic(mg->pdev);
- unsigned long pending;
- int i;
- int bitnr;
- u8 pin;
-
- for (i = 0; i < (mg->chip.ngpio / BITS_PER_BYTE); i++) {
- intel_msic_irq_read(msic, INTEL_MSIC_GPIO0LVIRQ + i, &pin);
- pending = pin;
-
- for_each_set_bit(bitnr, &pending, BITS_PER_BYTE)
- generic_handle_irq(mg->irq_base + i * BITS_PER_BYTE + bitnr);
- }
- chip->irq_eoi(data);
-}
-
-static int platform_msic_gpio_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct intel_msic_gpio_pdata *pdata = dev_get_platdata(dev);
- struct msic_gpio *mg;
- int irq = platform_get_irq(pdev, 0);
- int retval;
- int i;
-
- if (irq < 0) {
- dev_err(dev, "no IRQ line: %d\n", irq);
- return irq;
- }
-
- if (!pdata || !pdata->gpio_base) {
- dev_err(dev, "incorrect or missing platform data\n");
- return -EINVAL;
- }
-
- mg = kzalloc(sizeof(*mg), GFP_KERNEL);
- if (!mg)
- return -ENOMEM;
-
- dev_set_drvdata(dev, mg);
-
- mg->pdev = pdev;
- mg->irq = irq;
- mg->irq_base = pdata->gpio_base + MSIC_GPIO_IRQ_OFFSET;
- mg->chip.label = "msic_gpio";
- mg->chip.direction_input = msic_gpio_direction_input;
- mg->chip.direction_output = msic_gpio_direction_output;
- mg->chip.get = msic_gpio_get;
- mg->chip.set = msic_gpio_set;
- mg->chip.to_irq = msic_gpio_to_irq;
- mg->chip.base = pdata->gpio_base;
- mg->chip.ngpio = MSIC_NUM_GPIO;
- mg->chip.can_sleep = true;
- mg->chip.parent = dev;
-
- mutex_init(&mg->buslock);
-
- retval = gpiochip_add_data(&mg->chip, mg);
- if (retval) {
- dev_err(dev, "Adding MSIC gpio chip failed\n");
- goto err;
- }
-
- for (i = 0; i < mg->chip.ngpio; i++) {
- irq_set_chip_data(i + mg->irq_base, mg);
- irq_set_chip_and_handler(i + mg->irq_base,
- &msic_irqchip,
- handle_simple_irq);
- }
- irq_set_chained_handler_and_data(mg->irq, msic_gpio_irq_handler, mg);
-
- return 0;
-err:
- kfree(mg);
- return retval;
-}
-
-static struct platform_driver platform_msic_gpio_driver = {
- .driver = {
- .name = "msic_gpio",
- },
- .probe = platform_msic_gpio_probe,
-};
-
-static int __init platform_msic_gpio_init(void)
-{
- return platform_driver_register(&platform_msic_gpio_driver);
-}
-subsys_initcall(platform_msic_gpio_init);
diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig
index 0e23c93a1094..1ef2cda5b5c2 100644
--- a/drivers/gpu/drm/gma500/Kconfig
+++ b/drivers/gpu/drm/gma500/Kconfig
@@ -30,6 +30,7 @@ config DRM_GMA3600
config DRM_MEDFIELD
bool "Intel Medfield support (Experimental)"
depends on DRM_GMA500 && X86_INTEL_MID
+ select INTEL_SCU_IPC
help
Say yes to include support for the Intel Medfield platform.
diff --git a/drivers/gpu/drm/gma500/mdfld_device.c b/drivers/gpu/drm/gma500/mdfld_device.c
index b83d59b21de5..12193e591327 100644
--- a/drivers/gpu/drm/gma500/mdfld_device.c
+++ b/drivers/gpu/drm/gma500/mdfld_device.c
@@ -8,8 +8,6 @@
#include <linux/delay.h>
#include <linux/gpio/machine.h>
-#include <asm/intel_scu_ipc.h>
-
#include "mdfld_dsi_output.h"
#include "mdfld_output.h"
#include "mid_bios.h"
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 4aab76613bd9..38ec49b71499 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -30,8 +30,6 @@
#include <linux/pm_runtime.h>
#include <linux/gpio/consumer.h>
-#include <asm/intel_scu_ipc.h>
-
#include "mdfld_dsi_dpi.h"
#include "mdfld_dsi_output.h"
#include "mdfld_dsi_pkg_sender.h"
diff --git a/drivers/gpu/drm/gma500/mdfld_output.c b/drivers/gpu/drm/gma500/mdfld_output.c
index c95966bb0c96..518417f49be8 100644
--- a/drivers/gpu/drm/gma500/mdfld_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_output.c
@@ -25,6 +25,8 @@
* Scott Rowe <scott.m.rowe@intel.com>
*/
+#include <asm/intel_scu_ipc.h>
+
#include "mdfld_output.h"
#include "mdfld_dsi_dpi.h"
#include "mdfld_dsi_output.h"
@@ -58,11 +60,14 @@ static void mdfld_init_panel(struct drm_device *dev, int mipi_pipe,
}
}
-
int mdfld_output_init(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
+ dev_priv->scu = devm_intel_scu_ipc_dev_get(&dev->pdev->dev);
+ if (!dev_priv->scu)
+ return -EPROBE_DEFER;
+
/* FIXME: hardcoded for now */
dev_priv->mdfld_panel_id = TC35876X;
/* MIPI panel 1 */
@@ -71,4 +76,3 @@ int mdfld_output_init(struct drm_device *dev)
mdfld_init_panel(dev, 1, HDMI);
return 0;
}
-
diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c
index 8754290b0e23..0c1a66b20f27 100644
--- a/drivers/gpu/drm/gma500/oaktrail_device.c
+++ b/drivers/gpu/drm/gma500/oaktrail_device.c
@@ -10,9 +10,6 @@
#include <linux/dmi.h>
#include <linux/module.h>
-#include <asm/intel-mid.h>
-#include <asm/intel_scu_ipc.h>
-
#include <drm/drm.h>
#include "intel_bios.h"
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 5b7f7a312d53..938efdddc27c 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -428,6 +428,8 @@ struct psb_ops;
#define PSB_NUM_PIPE 3
+struct intel_scu_ipc_dev;
+
struct drm_psb_private {
struct drm_device *dev;
struct pci_dev *aux_pdev; /* Currently only used by mrst */
@@ -567,6 +569,7 @@ struct drm_psb_private {
* Used for modifying backlight from
* xrandr -- consider removing and using HAL instead
*/
+ struct intel_scu_ipc_dev *scu;
struct backlight_device *backlight_device;
struct drm_property *backlight_property;
bool backlight_enabled;
diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
index e5bdd99ad453..3dab94463656 100644
--- a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
+++ b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
@@ -444,6 +444,7 @@ static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
static void tc35876x_brightness_init(struct drm_device *dev)
{
+ struct drm_psb_private *dev_priv = dev->dev_private;
int ret;
u8 pwmctrl;
u16 clkdiv;
@@ -451,23 +452,23 @@ static void tc35876x_brightness_init(struct drm_device *dev)
/* Make sure the PWM reference is the 19.2 MHz system clock. Read first
* instead of setting directly to catch potential conflicts between PWM
* users. */
- ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
+ ret = intel_scu_ipc_dev_ioread8(dev_priv->scu, GPIOPWMCTRL, &pwmctrl);
if (ret || pwmctrl != 0x01) {
if (ret)
dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
else
dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
- ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
+ ret = intel_scu_ipc_dev_iowrite8(dev_priv->scu, GPIOPWMCTRL, 0x01);
if (ret)
dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
}
clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
- ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
+ ret = intel_scu_ipc_dev_iowrite8(dev_priv->scu, PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
if (!ret)
- ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
+ ret = intel_scu_ipc_dev_iowrite8(dev_priv->scu, PWM0CLKDIV0, clkdiv & 0xff);
if (ret)
dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
@@ -480,6 +481,7 @@ static void tc35876x_brightness_init(struct drm_device *dev)
void tc35876x_brightness_control(struct drm_device *dev, int level)
{
+ struct drm_psb_private *dev_priv = dev->dev_private;
int ret;
u8 duty_val;
u8 panel_duty_val;
@@ -495,7 +497,7 @@ void tc35876x_brightness_control(struct drm_device *dev, int level)
panel_duty_val = (2 * level - 100) * 0xA9 /
MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
- ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
+ ret = intel_scu_ipc_dev_iowrite8(dev_priv->scu, PWM0DUTYCYCLE, duty_val);
if (ret)
dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
__func__);
@@ -516,11 +518,9 @@ void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
- if (bridge_bl_enable)
- gpiod_set_value_cansleep(bridge_bl_enable, 0);
+ gpiod_set_value_cansleep(bridge_bl_enable, 0);
- if (backlight_voltage)
- gpiod_set_value_cansleep(backlight_voltage, 0);
+ gpiod_set_value_cansleep(backlight_voltage, 0);
}
void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
@@ -565,8 +565,7 @@ void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
"i2c write failed (%d)\n", ret);
}
- if (bridge_bl_enable)
- gpiod_set_value_cansleep(bridge_bl_enable, 1);
+ gpiod_set_value_cansleep(bridge_bl_enable, 1);
tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
}
@@ -640,20 +639,17 @@ static int tc35876x_bridge_probe(struct i2c_client *client,
bridge_reset = devm_gpiod_get_optional(&client->dev, "bridge-reset", GPIOD_OUT_LOW);
if (IS_ERR(bridge_reset))
return PTR_ERR(bridge_reset);
- if (bridge_reset)
- gpiod_set_consumer_name(bridge_reset, "tc35876x bridge reset");
+ gpiod_set_consumer_name(bridge_reset, "tc35876x bridge reset");
bridge_bl_enable = devm_gpiod_get_optional(&client->dev, "bl-en", GPIOD_OUT_LOW);
if (IS_ERR(bridge_bl_enable))
return PTR_ERR(bridge_bl_enable);
- if (bridge_bl_enable)
- gpiod_set_consumer_name(bridge_bl_enable, "tc35876x panel bl en");
+ gpiod_set_consumer_name(bridge_bl_enable, "tc35876x panel bl en");
backlight_voltage = devm_gpiod_get_optional(&client->dev, "vadd", GPIOD_OUT_LOW);
if (IS_ERR(backlight_voltage))
return PTR_ERR(backlight_voltage);
- if (backlight_voltage)
- gpiod_set_consumer_name(backlight_voltage, "tc35876x panel vadd");
+ gpiod_set_consumer_name(backlight_voltage, "tc35876x panel vadd");
tc35876x_client = client;
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 6909e4a0cfff..a6290c32cfda 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1425,6 +1425,14 @@ config INTEL_SCU_PLATFORM
and SCU (sometimes called PMC as well). The driver currently
supports Intel Elkhart Lake and compatible platforms.
+config INTEL_SCU_WDT
+ bool
+ default INTEL_SCU_PCI
+ depends on INTEL_MID_WATCHDOG
+ help
+ This is a specific platform code to instantiate watchdog device
+ on ACPI-based Intel MID platforms.
+
config INTEL_SCU_IPC_UTIL
tristate "Intel SCU IPC utility driver"
depends on INTEL_SCU
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 728ccc226a29..19306450d791 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -146,6 +146,7 @@ obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
obj-$(CONFIG_INTEL_SCU_PCI) += intel_scu_pcidrv.o
obj-$(CONFIG_INTEL_SCU_PLATFORM) += intel_scu_pltdrv.o
+obj-$(CONFIG_INTEL_SCU_WDT) += intel_scu_wdt.o
obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \
intel_telemetry_pltdrv.o \
diff --git a/drivers/platform/x86/intel_scu_wdt.c b/drivers/platform/x86/intel_scu_wdt.c
new file mode 100644
index 000000000000..85ee85ca2215
--- /dev/null
+++ b/drivers/platform/x86/intel_scu_wdt.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel Merrifield watchdog platform device library file
+ *
+ * (C) Copyright 2014 Intel Corporation
+ * Author: David Cohen <david.a.cohen@linux.intel.com>
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/intel-mid_wdt.h>
+
+#include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
+#include <asm/intel-mid.h>
+#include <asm/io_apic.h>
+#include <asm/hw_irq.h>
+
+#define TANGIER_EXT_TIMER0_MSI 12
+
+static struct platform_device wdt_dev = {
+ .name = "intel_mid_wdt",
+ .id = -1,
+};
+
+static int tangier_probe(struct platform_device *pdev)
+{
+ struct irq_alloc_info info;
+ struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
+ int gsi = TANGIER_EXT_TIMER0_MSI;
+ int irq;
+
+ if (!pdata)
+ return -EINVAL;
+
+ /* IOAPIC builds identity mapping between GSI and IRQ on MID */
+ ioapic_set_alloc_attr(&info, cpu_to_node(0), 1, 0);
+ irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info);
+ if (irq < 0) {
+ dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n", gsi);
+ return irq;
+ }
+
+ pdata->irq = irq;
+ return 0;
+}
+
+static struct intel_mid_wdt_pdata tangier_pdata = {
+ .probe = tangier_probe,
+};
+
+static const struct x86_cpu_id intel_mid_cpu_ids[] = {
+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &tangier_pdata),
+ {}
+};
+
+static int __init register_mid_wdt(void)
+{
+ const struct x86_cpu_id *id;
+
+ id = x86_match_cpu(intel_mid_cpu_ids);
+ if (!id)
+ return -ENODEV;
+
+ wdt_dev.dev.platform_data = (const struct intel_mid_wdt_pdata *)id->driver_data;
+ return platform_device_register(&wdt_dev);
+}
+arch_initcall(register_mid_wdt);
+
+static void __exit unregister_mid_wdt(void)
+{
+ platform_device_unregister(&wdt_dev);
+}
+__exitcall(unregister_mid_wdt);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 6123f9f4fbc9..2a402c10f8f1 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -973,18 +973,6 @@ config RTC_DRV_ALPHA
Direct support for the real-time clock found on every Alpha
system, specifically MC146818 compatibles. If in doubt, say Y.
-config RTC_DRV_VRTC
- tristate "Virtual RTC for Intel MID platforms"
- depends on X86_INTEL_MID
- default y if X86_INTEL_MID
-
- help
- Say "yes" here to get direct support for the real time clock
- found on Moorestown platforms. The VRTC is a emulated RTC that
- derives its clock source from a real RTC in the PMIC. The MC146818
- style programming interface is mostly conserved, but any
- updates are done via IPC calls to the system controller FW.
-
config RTC_DRV_DS1216
tristate "Dallas DS1216"
depends on SNI_RM
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index bb8f319b09fb..f8ac4f574522 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -174,7 +174,6 @@ obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o
obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
-obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
deleted file mode 100644
index 421b3b6071b6..000000000000
--- a/drivers/rtc/rtc-mrst.c
+++ /dev/null
@@ -1,521 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * rtc-mrst.c: Driver for Moorestown virtual RTC
- *
- * (C) Copyright 2009 Intel Corporation
- * Author: Jacob Pan (jacob.jun.pan@intel.com)
- * Feng Tang (feng.tang@intel.com)
- *
- * Note:
- * VRTC is emulated by system controller firmware, the real HW
- * RTC is located in the PMIC device. SCU FW shadows PMIC RTC
- * in a memory mapped IO space that is visible to the host IA
- * processor.
- *
- * This driver is based upon drivers/rtc/rtc-cmos.c
- */
-
-/*
- * Note:
- * * vRTC only supports binary mode and 24H mode
- * * vRTC only support PIE and AIE, no UIE, and its PIE only happens
- * at 23:59:59pm everyday, no support for adjustable frequency
- * * Alarm function is also limited to hr/min/sec.
- */
-
-#include <linux/mod_devicetable.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/kernel.h>
-#include <linux/mc146818rtc.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sfi.h>
-
-#include <asm/intel_scu_ipc.h>
-#include <asm/intel-mid.h>
-#include <asm/intel_mid_vrtc.h>
-
-struct mrst_rtc {
- struct rtc_device *rtc;
- struct device *dev;
- int irq;
-
- u8 enabled_wake;
- u8 suspend_ctrl;
-};
-
-static const char driver_name[] = "rtc_mrst";
-
-#define RTC_IRQMASK (RTC_PF | RTC_AF)
-
-static inline int is_intr(u8 rtc_intr)
-{
- if (!(rtc_intr & RTC_IRQF))
- return 0;
- return rtc_intr & RTC_IRQMASK;
-}
-
-static inline unsigned char vrtc_is_updating(void)
-{
- unsigned char uip;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return uip;
-}
-
-/*
- * rtc_time's year contains the increment over 1900, but vRTC's YEAR
- * register can't be programmed to value larger than 0x64, so vRTC
- * driver chose to use 1972 (1970 is UNIX time start point) as the base,
- * and does the translation at read/write time.
- *
- * Why not just use 1970 as the offset? it's because using 1972 will
- * make it consistent in leap year setting for both vrtc and low-level
- * physical rtc devices. Then why not use 1960 as the offset? If we use
- * 1960, for a device's first use, its YEAR register is 0 and the system
- * year will be parsed as 1960 which is not a valid UNIX time and will
- * cause many applications to fail mysteriously.
- */
-static int mrst_read_time(struct device *dev, struct rtc_time *time)
-{
- unsigned long flags;
-
- if (vrtc_is_updating())
- msleep(20);
-
- spin_lock_irqsave(&rtc_lock, flags);
- time->tm_sec = vrtc_cmos_read(RTC_SECONDS);
- time->tm_min = vrtc_cmos_read(RTC_MINUTES);
- time->tm_hour = vrtc_cmos_read(RTC_HOURS);
- time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
- time->tm_mon = vrtc_cmos_read(RTC_MONTH);
- time->tm_year = vrtc_cmos_read(RTC_YEAR);
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- /* Adjust for the 1972/1900 */
- time->tm_year += 72;
- time->tm_mon--;
- return 0;
-}
-
-static int mrst_set_time(struct device *dev, struct rtc_time *time)
-{
- int ret;
- unsigned long flags;
- unsigned char mon, day, hrs, min, sec;
- unsigned int yrs;
-
- yrs = time->tm_year;
- mon = time->tm_mon + 1; /* tm_mon starts at zero */
- day = time->tm_mday;
- hrs = time->tm_hour;
- min = time->tm_min;
- sec = time->tm_sec;
-
- if (yrs < 72 || yrs > 172)
- return -EINVAL;
- yrs -= 72;
-
- spin_lock_irqsave(&rtc_lock, flags);
-
- vrtc_cmos_write(yrs, RTC_YEAR);
- vrtc_cmos_write(mon, RTC_MONTH);
- vrtc_cmos_write(day, RTC_DAY_OF_MONTH);
- vrtc_cmos_write(hrs, RTC_HOURS);
- vrtc_cmos_write(min, RTC_MINUTES);
- vrtc_cmos_write(sec, RTC_SECONDS);
-
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME);
- return ret;
-}
-
-static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t)
-{
- struct mrst_rtc *mrst = dev_get_drvdata(dev);
- unsigned char rtc_control;
-
- if (mrst->irq <= 0)
- return -EIO;
-
- /* vRTC only supports binary mode */
- spin_lock_irq(&rtc_lock);
- t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM);
- t->time.tm_min = vrtc_cmos_read(RTC_MINUTES_ALARM);
- t->time.tm_hour = vrtc_cmos_read(RTC_HOURS_ALARM);
-
- rtc_control = vrtc_cmos_read(RTC_CONTROL);
- spin_unlock_irq(&rtc_lock);
-
- t->enabled = !!(rtc_control & RTC_AIE);
- t->pending = 0;
-
- return 0;
-}
-
-static void mrst_checkintr(struct mrst_rtc *mrst, unsigned char rtc_control)
-{
- unsigned char rtc_intr;
-
- /*
- * NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
- * allegedly some older rtcs need that to handle irqs properly
- */
- rtc_intr = vrtc_cmos_read(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(mrst->rtc, 1, rtc_intr);
-}
-
-static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask)
-{
- unsigned char rtc_control;
-
- /*
- * Flush any pending IRQ status, notably for update irqs,
- * before we enable new IRQs
- */
- rtc_control = vrtc_cmos_read(RTC_CONTROL);
- mrst_checkintr(mrst, rtc_control);
-
- rtc_control |= mask;
- vrtc_cmos_write(rtc_control, RTC_CONTROL);
-
- mrst_checkintr(mrst, rtc_control);
-}
-
-static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask)
-{
- unsigned char rtc_control;
-
- rtc_control = vrtc_cmos_read(RTC_CONTROL);
- rtc_control &= ~mask;
- vrtc_cmos_write(rtc_control, RTC_CONTROL);
- mrst_checkintr(mrst, rtc_control);
-}
-
-static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t)
-{
- struct mrst_rtc *mrst = dev_get_drvdata(dev);
- unsigned char hrs, min, sec;
- int ret = 0;
-
- if (!mrst->irq)
- return -EIO;
-
- hrs = t->time.tm_hour;
- min = t->time.tm_min;
- sec = t->time.tm_sec;
-
- spin_lock_irq(&rtc_lock);
- /* Next rtc irq must not be from previous alarm setting */
- mrst_irq_disable(mrst, RTC_AIE);
-
- /* Update alarm */
- vrtc_cmos_write(hrs, RTC_HOURS_ALARM);
- vrtc_cmos_write(min, RTC_MINUTES_ALARM);
- vrtc_cmos_write(sec, RTC_SECONDS_ALARM);
-
- spin_unlock_irq(&rtc_lock);
-
- ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM);
- if (ret)
- return ret;
-
- spin_lock_irq(&rtc_lock);
- if (t->enabled)
- mrst_irq_enable(mrst, RTC_AIE);
-
- spin_unlock_irq(&rtc_lock);
-
- return 0;
-}
-
-/* Currently, the vRTC doesn't support UIE ON/OFF */
-static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
-{
- struct mrst_rtc *mrst = dev_get_drvdata(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- if (enabled)
- mrst_irq_enable(mrst, RTC_AIE);
- else
- mrst_irq_disable(mrst, RTC_AIE);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return 0;
-}
-
-
-#if IS_ENABLED(CONFIG_RTC_INTF_PROC)
-
-static int mrst_procfs(struct device *dev, struct seq_file *seq)
-{
- unsigned char rtc_control;
-
- spin_lock_irq(&rtc_lock);
- rtc_control = vrtc_cmos_read(RTC_CONTROL);
- spin_unlock_irq(&rtc_lock);
-
- seq_printf(seq,
- "periodic_IRQ\t: %s\n"
- "alarm\t\t: %s\n"
- "BCD\t\t: no\n"
- "periodic_freq\t: daily (not adjustable)\n",
- (rtc_control & RTC_PIE) ? "on" : "off",
- (rtc_control & RTC_AIE) ? "on" : "off");
-
- return 0;
-}
-
-#else
-#define mrst_procfs NULL
-#endif
-
-static const struct rtc_class_ops mrst_rtc_ops = {
- .read_time = mrst_read_time,
- .set_time = mrst_set_time,
- .read_alarm = mrst_read_alarm,
- .set_alarm = mrst_set_alarm,
- .proc = mrst_procfs,
- .alarm_irq_enable = mrst_rtc_alarm_irq_enable,
-};
-
-static struct mrst_rtc mrst_rtc;
-
-/*
- * When vRTC IRQ is captured by SCU FW, FW will clear the AIE bit in
- * Reg B, so no need for this driver to clear it
- */
-static irqreturn_t mrst_rtc_irq(int irq, void *p)
-{
- u8 irqstat;
-
- spin_lock(&rtc_lock);
- /* This read will clear all IRQ flags inside Reg C */
- irqstat = vrtc_cmos_read(RTC_INTR_FLAGS);
- spin_unlock(&rtc_lock);
-
- irqstat &= RTC_IRQMASK | RTC_IRQF;
- if (is_intr(irqstat)) {
- rtc_update_irq(p, 1, irqstat);
- return IRQ_HANDLED;
- }
- return IRQ_NONE;
-}
-
-static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem,
- int rtc_irq)
-{
- int retval = 0;
- unsigned char rtc_control;
-
- /* There can be only one ... */
- if (mrst_rtc.dev)
- return -EBUSY;
-
- if (!iomem)
- return -ENODEV;
-
- iomem = devm_request_mem_region(dev, iomem->start, resource_size(iomem),
- driver_name);
- if (!iomem) {
- dev_dbg(dev, "i/o mem already in use.\n");
- return -EBUSY;
- }
-
- mrst_rtc.irq = rtc_irq;
- mrst_rtc.dev = dev;
- dev_set_drvdata(dev, &mrst_rtc);
-
- mrst_rtc.rtc = devm_rtc_allocate_device(dev);
- if (IS_ERR(mrst_rtc.rtc))
- return PTR_ERR(mrst_rtc.rtc);
-
- mrst_rtc.rtc->ops = &mrst_rtc_ops;
-
- rename_region(iomem, dev_name(&mrst_rtc.rtc->dev));
-
- spin_lock_irq(&rtc_lock);
- mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE);
- rtc_control = vrtc_cmos_read(RTC_CONTROL);
- spin_unlock_irq(&rtc_lock);
-
- if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))
- dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n");
-
- if (rtc_irq) {
- retval = devm_request_irq(dev, rtc_irq, mrst_rtc_irq,
- 0, dev_name(&mrst_rtc.rtc->dev),
- mrst_rtc.rtc);
- if (retval < 0) {
- dev_dbg(dev, "IRQ %d is already in use, err %d\n",
- rtc_irq, retval);
- goto cleanup0;
- }
- }
-
- retval = devm_rtc_register_device(mrst_rtc.rtc);
- if (retval)
- goto cleanup0;
-
- dev_dbg(dev, "initialised\n");
- return 0;
-
-cleanup0:
- mrst_rtc.dev = NULL;
- dev_err(dev, "rtc-mrst: unable to initialise\n");
- return retval;
-}
-
-static void rtc_mrst_do_shutdown(void)
-{
- spin_lock_irq(&rtc_lock);
- mrst_irq_disable(&mrst_rtc, RTC_IRQMASK);
- spin_unlock_irq(&rtc_lock);
-}
-
-static void rtc_mrst_do_remove(struct device *dev)
-{
- struct mrst_rtc *mrst = dev_get_drvdata(dev);
-
- rtc_mrst_do_shutdown();
-
- mrst->rtc = NULL;
- mrst->dev = NULL;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int mrst_suspend(struct device *dev)
-{
- struct mrst_rtc *mrst = dev_get_drvdata(dev);
- unsigned char tmp;
-
- /* Only the alarm might be a wakeup event source */
- spin_lock_irq(&rtc_lock);
- mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL);
- if (tmp & (RTC_PIE | RTC_AIE)) {
- unsigned char mask;
-
- if (device_may_wakeup(dev))
- mask = RTC_IRQMASK & ~RTC_AIE;
- else
- mask = RTC_IRQMASK;
- tmp &= ~mask;
- vrtc_cmos_write(tmp, RTC_CONTROL);
-
- mrst_checkintr(mrst, tmp);
- }
- spin_unlock_irq(&rtc_lock);
-
- if (tmp & RTC_AIE) {
- mrst->enabled_wake = 1;
- enable_irq_wake(mrst->irq);
- }
-
- dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n",
- (tmp & RTC_AIE) ? ", alarm may wake" : "",
- tmp);
-
- return 0;
-}
-
-/*
- * We want RTC alarms to wake us from the deep power saving state
- */
-static inline int mrst_poweroff(struct device *dev)
-{
- return mrst_suspend(dev);
-}
-
-static int mrst_resume(struct device *dev)
-{
- struct mrst_rtc *mrst = dev_get_drvdata(dev);
- unsigned char tmp = mrst->suspend_ctrl;
-
- /* Re-enable any irqs previously active */
- if (tmp & RTC_IRQMASK) {
- unsigned char mask;
-
- if (mrst->enabled_wake) {
- disable_irq_wake(mrst->irq);
- mrst->enabled_wake = 0;
- }
-
- spin_lock_irq(&rtc_lock);
- do {
- vrtc_cmos_write(tmp, RTC_CONTROL);
-
- mask = vrtc_cmos_read(RTC_INTR_FLAGS);
- mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
- if (!is_intr(mask))
- break;
-
- rtc_update_irq(mrst->rtc, 1, mask);
- tmp &= ~RTC_AIE;
- } while (mask & RTC_AIE);
- spin_unlock_irq(&rtc_lock);
- }
-
- dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp);
-
- return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(mrst_pm_ops, mrst_suspend, mrst_resume);
-#define MRST_PM_OPS (&mrst_pm_ops)
-
-#else
-#define MRST_PM_OPS NULL
-
-static inline int mrst_poweroff(struct device *dev)
-{
- return -ENOSYS;
-}
-
-#endif
-
-static int vrtc_mrst_platform_probe(struct platform_device *pdev)
-{
- return vrtc_mrst_do_probe(&pdev->dev,
- platform_get_resource(pdev, IORESOURCE_MEM, 0),
- platform_get_irq(pdev, 0));
-}
-
-static int vrtc_mrst_platform_remove(struct platform_device *pdev)
-{
- rtc_mrst_do_remove(&pdev->dev);
- return 0;
-}
-
-static void vrtc_mrst_platform_shutdown(struct platform_device *pdev)
-{
- if (system_state == SYSTEM_POWER_OFF && !mrst_poweroff(&pdev->dev))
- return;
-
- rtc_mrst_do_shutdown();
-}
-
-MODULE_ALIAS("platform:vrtc_mrst");
-
-static struct platform_driver vrtc_mrst_platform_driver = {
- .probe = vrtc_mrst_platform_probe,
- .remove = vrtc_mrst_platform_remove,
- .shutdown = vrtc_mrst_platform_shutdown,
- .driver = {
- .name = driver_name,
- .pm = MRST_PM_OPS,
- }
-};
-
-module_platform_driver(vrtc_mrst_platform_driver);
-
-MODULE_AUTHOR("Jacob Pan; Feng Tang");
-MODULE_DESCRIPTION("Driver for Moorestown virtual RTC");
-MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7ff941e71b79..6b9e93d8532b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1219,15 +1219,6 @@ config IE6XX_WDT
To compile this driver as a module, choose M here: the
module will be called ie6xx_wdt.
-config INTEL_SCU_WATCHDOG
- bool "Intel SCU Watchdog for Mobile Platforms"
- depends on X86_INTEL_MID
- help
- Hardware driver for the watchdog time built into the Intel SCU
- for Intel Mobile Platforms.
-
- To compile this driver as a module, choose M here.
-
config INTEL_MID_WATCHDOG
tristate "Intel MID Watchdog Timer"
depends on X86_INTEL_MID
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 5c74ee19d441..74f61e4105d8 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -140,7 +140,6 @@ obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
-obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o
obj-$(CONFIG_INTEL_MID_WATCHDOG) += intel-mid_wdt.o
obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o
obj-$(CONFIG_NI903X_WDT) += ni903x_wdt.o
diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c
index 1ae03b64ef8b..9b2173f765c8 100644
--- a/drivers/watchdog/intel-mid_wdt.c
+++ b/drivers/watchdog/intel-mid_wdt.c
@@ -154,6 +154,10 @@ static int mid_wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT);
watchdog_set_drvdata(wdt_dev, mid);
+ mid->scu = devm_intel_scu_ipc_dev_get(dev);
+ if (!mid->scu)
+ return -EPROBE_DEFER;
+
ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq,
IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog",
wdt_dev);
@@ -162,10 +166,6 @@ static int mid_wdt_probe(struct platform_device *pdev)
return ret;
}
- mid->scu = devm_intel_scu_ipc_dev_get(dev);
- if (!mid->scu)
- return -EPROBE_DEFER;
-
/*
* The firmware followed by U-Boot leaves the watchdog running
* with the default threshold which may vary. When we get here
diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c
deleted file mode 100644
index 804e35940983..000000000000
--- a/drivers/watchdog/intel_scu_watchdog.c
+++ /dev/null
@@ -1,533 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device
- * for Intel part #(s):
- * - AF82MP20 PCH
- *
- * Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/jiffies.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/sfi.h>
-#include <asm/irq.h>
-#include <linux/atomic.h>
-#include <asm/intel_scu_ipc.h>
-#include <asm/apb_timer.h>
-#include <asm/intel-mid.h>
-
-#include "intel_scu_watchdog.h"
-
-/* Bounds number of times we will retry loading time count */
-/* This retry is a work around for a silicon bug. */
-#define MAX_RETRY 16
-
-#define IPC_SET_WATCHDOG_TIMER 0xF8
-
-static int timer_margin = DEFAULT_SOFT_TO_HARD_MARGIN;
-module_param(timer_margin, int, 0);
-MODULE_PARM_DESC(timer_margin,
- "Watchdog timer margin"
- "Time between interrupt and resetting the system"
- "The range is from 1 to 160"
- "This is the time for all keep alives to arrive");
-
-static int timer_set = DEFAULT_TIME;
-module_param(timer_set, int, 0);
-MODULE_PARM_DESC(timer_set,
- "Default Watchdog timer setting"
- "Complete cycle time"
- "The range is from 1 to 170"
- "This is the time for all keep alives to arrive");
-
-/* After watchdog device is closed, check force_boot. If:
- * force_boot == 0, then force boot on next watchdog interrupt after close,
- * force_boot == 1, then force boot immediately when device is closed.
- */
-static int force_boot;
-module_param(force_boot, int, 0);
-MODULE_PARM_DESC(force_boot,
- "A value of 1 means that the driver will reboot"
- "the system immediately if the /dev/watchdog device is closed"
- "A value of 0 means that when /dev/watchdog device is closed"
- "the watchdog timer will be refreshed for one more interval"
- "of length: timer_set. At the end of this interval, the"
- "watchdog timer will reset the system."
- );
-
-/* there is only one device in the system now; this can be made into
- * an array in the future if we have more than one device */
-
-static struct intel_scu_watchdog_dev watchdog_device;
-
-/* Forces restart, if force_reboot is set */
-static void watchdog_fire(void)
-{
- if (force_boot) {
- pr_crit("Initiating system reboot\n");
- emergency_restart();
- pr_crit("Reboot didn't ?????\n");
- }
-
- else {
- pr_crit("Immediate Reboot Disabled\n");
- pr_crit("System will reset when watchdog timer times out!\n");
- }
-}
-
-static int check_timer_margin(int new_margin)
-{
- if ((new_margin < MIN_TIME_CYCLE) ||
- (new_margin > MAX_TIME - timer_set)) {
- pr_debug("value of new_margin %d is out of the range %d to %d\n",
- new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
- return -EINVAL;
- }
- return 0;
-}
-
-/*
- * IPC operations
- */
-static int watchdog_set_ipc(int soft_threshold, int threshold)
-{
- u32 *ipc_wbuf;
- u8 cbuf[16] = { '\0' };
- int ipc_ret = 0;
-
- ipc_wbuf = (u32 *)&cbuf;
- ipc_wbuf[0] = soft_threshold;
- ipc_wbuf[1] = threshold;
-
- ipc_ret = intel_scu_ipc_command(
- IPC_SET_WATCHDOG_TIMER,
- 0,
- ipc_wbuf,
- 2,
- NULL,
- 0);
-
- if (ipc_ret != 0)
- pr_err("Error setting SCU watchdog timer: %x\n", ipc_ret);
-
- return ipc_ret;
-};
-
-/*
- * Intel_SCU operations
- */
-
-/* timer interrupt handler */
-static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id)
-{
- int int_status;
- int_status = ioread32(watchdog_device.timer_interrupt_status_addr);
-
- pr_debug("irq, int_status: %x\n", int_status);
-
- if (int_status != 0)
- return IRQ_NONE;
-
- /* has the timer been started? If not, then this is spurious */
- if (watchdog_device.timer_started == 0) {
- pr_debug("spurious interrupt received\n");
- return IRQ_HANDLED;
- }
-
- /* temporarily disable the timer */
- iowrite32(0x00000002, watchdog_device.timer_control_addr);
-
- /* set the timer to the threshold */
- iowrite32(watchdog_device.threshold,
- watchdog_device.timer_load_count_addr);
-
- /* allow the timer to run */
- iowrite32(0x00000003, watchdog_device.timer_control_addr);
-
- return IRQ_HANDLED;
-}
-
-static int intel_scu_keepalive(void)
-{
-
- /* read eoi register - clears interrupt */
- ioread32(watchdog_device.timer_clear_interrupt_addr);
-
- /* temporarily disable the timer */
- iowrite32(0x00000002, watchdog_device.timer_control_addr);
-
- /* set the timer to the soft_threshold */
- iowrite32(watchdog_device.soft_threshold,
- watchdog_device.timer_load_count_addr);
-
- /* allow the timer to run */
- iowrite32(0x00000003, watchdog_device.timer_control_addr);
-
- return 0;
-}
-
-static int intel_scu_stop(void)
-{
- iowrite32(0, watchdog_device.timer_control_addr);
- return 0;
-}
-
-static int intel_scu_set_heartbeat(u32 t)
-{
- int ipc_ret;
- int retry_count;
- u32 soft_value;
- u32 hw_value;
-
- watchdog_device.timer_set = t;
- watchdog_device.threshold =
- timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
- watchdog_device.soft_threshold =
- (watchdog_device.timer_set - timer_margin)
- * watchdog_device.timer_tbl_ptr->freq_hz;
-
- pr_debug("set_heartbeat: timer freq is %d\n",
- watchdog_device.timer_tbl_ptr->freq_hz);
- pr_debug("set_heartbeat: timer_set is %x (hex)\n",
- watchdog_device.timer_set);
- pr_debug("set_heartbeat: timer_margin is %x (hex)\n", timer_margin);
- pr_debug("set_heartbeat: threshold is %x (hex)\n",
- watchdog_device.threshold);
- pr_debug("set_heartbeat: soft_threshold is %x (hex)\n",
- watchdog_device.soft_threshold);
-
- /* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */
- /* watchdog timing come out right. */
- watchdog_device.threshold =
- watchdog_device.threshold / FREQ_ADJUSTMENT;
- watchdog_device.soft_threshold =
- watchdog_device.soft_threshold / FREQ_ADJUSTMENT;
-
- /* temporarily disable the timer */
- iowrite32(0x00000002, watchdog_device.timer_control_addr);
-
- /* send the threshold and soft_threshold via IPC to the processor */
- ipc_ret = watchdog_set_ipc(watchdog_device.soft_threshold,
- watchdog_device.threshold);
-
- if (ipc_ret != 0) {
- /* Make sure the watchdog timer is stopped */
- intel_scu_stop();
- return ipc_ret;
- }
-
- /* Soft Threshold set loop. Early versions of silicon did */
- /* not always set this count correctly. This loop checks */
- /* the value and retries if it was not set correctly. */
-
- retry_count = 0;
- soft_value = watchdog_device.soft_threshold & 0xFFFF0000;
- do {
-
- /* Make sure timer is stopped */
- intel_scu_stop();
-
- if (MAX_RETRY < retry_count++) {
- /* Unable to set timer value */
- pr_err("Unable to set timer\n");
- return -ENODEV;
- }
-
- /* set the timer to the soft threshold */
- iowrite32(watchdog_device.soft_threshold,
- watchdog_device.timer_load_count_addr);
-
- /* read count value before starting timer */
- ioread32(watchdog_device.timer_load_count_addr);
-
- /* Start the timer */
- iowrite32(0x00000003, watchdog_device.timer_control_addr);
-
- /* read the value the time loaded into its count reg */
- hw_value = ioread32(watchdog_device.timer_load_count_addr);
- hw_value = hw_value & 0xFFFF0000;
-
-
- } while (soft_value != hw_value);
-
- watchdog_device.timer_started = 1;
-
- return 0;
-}
-
-/*
- * /dev/watchdog handling
- */
-
-static int intel_scu_open(struct inode *inode, struct file *file)
-{
-
- /* Set flag to indicate that watchdog device is open */
- if (test_and_set_bit(0, &watchdog_device.driver_open))
- return -EBUSY;
-
- /* Check for reopen of driver. Reopens are not allowed */
- if (watchdog_device.driver_closed)
- return -EPERM;
-
- return stream_open(inode, file);
-}
-
-static int intel_scu_release(struct inode *inode, struct file *file)
-{
- /*
- * This watchdog should not be closed, after the timer
- * is started with the WDIPC_SETTIMEOUT ioctl
- * If force_boot is set watchdog_fire() will cause an
- * immediate reset. If force_boot is not set, the watchdog
- * timer is refreshed for one more interval. At the end
- * of that interval, the watchdog timer will reset the system.
- */
-
- if (!test_and_clear_bit(0, &watchdog_device.driver_open)) {
- pr_debug("intel_scu_release, without open\n");
- return -ENOTTY;
- }
-
- if (!watchdog_device.timer_started) {
- /* Just close, since timer has not been started */
- pr_debug("closed, without starting timer\n");
- return 0;
- }
-
- pr_crit("Unexpected close of /dev/watchdog!\n");
-
- /* Since the timer was started, prevent future reopens */
- watchdog_device.driver_closed = 1;
-
- /* Refresh the timer for one more interval */
- intel_scu_keepalive();
-
- /* Reboot system (if force_boot is set) */
- watchdog_fire();
-
- /* We should only reach this point if force_boot is not set */
- return 0;
-}
-
-static ssize_t intel_scu_write(struct file *file,
- char const *data,
- size_t len,
- loff_t *ppos)
-{
-
- if (watchdog_device.timer_started)
- /* Watchdog already started, keep it alive */
- intel_scu_keepalive();
- else
- /* Start watchdog with timer value set by init */
- intel_scu_set_heartbeat(watchdog_device.timer_set);
-
- return len;
-}
-
-static long intel_scu_ioctl(struct file *file,
- unsigned int cmd,
- unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- u32 __user *p = argp;
- u32 new_margin;
-
-
- static const struct watchdog_info ident = {
- .options = WDIOF_SETTIMEOUT
- | WDIOF_KEEPALIVEPING,
- .firmware_version = 0, /* @todo Get from SCU via
- ipc_get_scu_fw_version()? */
- .identity = "Intel_SCU IOH Watchdog" /* len < 32 */
- };
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- return copy_to_user(argp,
- &ident,
- sizeof(ident)) ? -EFAULT : 0;
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, p);
- case WDIOC_KEEPALIVE:
- intel_scu_keepalive();
-
- return 0;
- case WDIOC_SETTIMEOUT:
- if (get_user(new_margin, p))
- return -EFAULT;
-
- if (check_timer_margin(new_margin))
- return -EINVAL;
-
- if (intel_scu_set_heartbeat(new_margin))
- return -EINVAL;
- return 0;
- case WDIOC_GETTIMEOUT:
- return put_user(watchdog_device.soft_threshold, p);
-
- default:
- return -ENOTTY;
- }
-}
-
-/*
- * Notifier for system down
- */
-static int intel_scu_notify_sys(struct notifier_block *this,
- unsigned long code,
- void *another_unused)
-{
- if (code == SYS_DOWN || code == SYS_HALT)
- /* Turn off the watchdog timer. */
- intel_scu_stop();
- return NOTIFY_DONE;
-}
-
-/*
- * Kernel Interfaces
- */
-static const struct file_operations intel_scu_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = intel_scu_write,
- .unlocked_ioctl = intel_scu_ioctl,
- .compat_ioctl = compat_ptr_ioctl,
- .open = intel_scu_open,
- .release = intel_scu_release,
-};
-
-static int __init intel_scu_watchdog_init(void)
-{
- int ret;
- u32 __iomem *tmp_addr;
-
- /*
- * We don't really need to check this as the SFI timer get will fail
- * but if we do so we can exit with a clearer reason and no noise.
- *
- * If it isn't an intel MID device then it doesn't have this watchdog
- */
- if (!intel_mid_identify_cpu())
- return -ENODEV;
-
- /* Check boot parameters to verify that their initial values */
- /* are in range. */
- /* Check value of timer_set boot parameter */
- if ((timer_set < MIN_TIME_CYCLE) ||
- (timer_set > MAX_TIME - MIN_TIME_CYCLE)) {
- pr_err("value of timer_set %x (hex) is out of range from %x to %x (hex)\n",
- timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
- return -EINVAL;
- }
-
- /* Check value of timer_margin boot parameter */
- if (check_timer_margin(timer_margin))
- return -EINVAL;
-
- watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);
-
- if (watchdog_device.timer_tbl_ptr == NULL) {
- pr_debug("timer is not available\n");
- return -ENODEV;
- }
- /* make sure the timer exists */
- if (watchdog_device.timer_tbl_ptr->phys_addr == 0) {
- pr_debug("timer %d does not have valid physical memory\n",
- sfi_mtimer_num);
- return -ENODEV;
- }
-
- if (watchdog_device.timer_tbl_ptr->irq == 0) {
- pr_debug("timer %d invalid irq\n", sfi_mtimer_num);
- return -ENODEV;
- }
-
- tmp_addr = ioremap(watchdog_device.timer_tbl_ptr->phys_addr,
- 20);
-
- if (tmp_addr == NULL) {
- pr_debug("timer unable to ioremap\n");
- return -ENOMEM;
- }
-
- watchdog_device.timer_load_count_addr = tmp_addr++;
- watchdog_device.timer_current_value_addr = tmp_addr++;
- watchdog_device.timer_control_addr = tmp_addr++;
- watchdog_device.timer_clear_interrupt_addr = tmp_addr++;
- watchdog_device.timer_interrupt_status_addr = tmp_addr++;
-
- /* Set the default time values in device structure */
-
- watchdog_device.timer_set = timer_set;
- watchdog_device.threshold =
- timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
- watchdog_device.soft_threshold =
- (watchdog_device.timer_set - timer_margin)
- * watchdog_device.timer_tbl_ptr->freq_hz;
-
-
- watchdog_device.intel_scu_notifier.notifier_call =
- intel_scu_notify_sys;
-
- ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier);
- if (ret) {
- pr_err("cannot register notifier %d)\n", ret);
- goto register_reboot_error;
- }
-
- watchdog_device.miscdev.minor = WATCHDOG_MINOR;
- watchdog_device.miscdev.name = "watchdog";
- watchdog_device.miscdev.fops = &intel_scu_fops;
-
- ret = misc_register(&watchdog_device.miscdev);
- if (ret) {
- pr_err("cannot register miscdev %d err =%d\n",
- WATCHDOG_MINOR, ret);
- goto misc_register_error;
- }
-
- ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq,
- watchdog_timer_interrupt,
- IRQF_SHARED, "watchdog",
- &watchdog_device.timer_load_count_addr);
- if (ret) {
- pr_err("error requesting irq %d\n", ret);
- goto request_irq_error;
- }
- /* Make sure timer is disabled before returning */
- intel_scu_stop();
- return 0;
-
-/* error cleanup */
-
-request_irq_error:
- misc_deregister(&watchdog_device.miscdev);
-misc_register_error:
- unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
-register_reboot_error:
- intel_scu_stop();
- iounmap(watchdog_device.timer_load_count_addr);
- return ret;
-}
-late_initcall(intel_scu_watchdog_init);
diff --git a/drivers/watchdog/intel_scu_watchdog.h b/drivers/watchdog/intel_scu_watchdog.h
deleted file mode 100644
index fb12a25ee417..000000000000
--- a/drivers/watchdog/intel_scu_watchdog.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device
- * for Intel part #(s):
- * - AF82MP20 PCH
- *
- * Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
- */
-
-#ifndef __INTEL_SCU_WATCHDOG_H
-#define __INTEL_SCU_WATCHDOG_H
-
-#define WDT_VER "0.3"
-
-/* minimum time between interrupts */
-#define MIN_TIME_CYCLE 1
-
-/* Time from warning to reboot is 2 seconds */
-#define DEFAULT_SOFT_TO_HARD_MARGIN 2
-
-#define MAX_TIME 170
-
-#define DEFAULT_TIME 5
-
-#define MAX_SOFT_TO_HARD_MARGIN (MAX_TIME-MIN_TIME_CYCLE)
-
-/* Ajustment to clock tick frequency to make timing come out right */
-#define FREQ_ADJUSTMENT 8
-
-struct intel_scu_watchdog_dev {
- ulong driver_open;
- ulong driver_closed;
- u32 timer_started;
- u32 timer_set;
- u32 threshold;
- u32 soft_threshold;
- u32 __iomem *timer_load_count_addr;
- u32 __iomem *timer_current_value_addr;
- u32 __iomem *timer_control_addr;
- u32 __iomem *timer_clear_interrupt_addr;
- u32 __iomem *timer_interrupt_status_addr;
- struct sfi_timer_table_entry *timer_tbl_ptr;
- struct notifier_block intel_scu_notifier;
- struct miscdevice miscdev;
-};
-
-extern int sfi_mtimer_num;
-
-/* extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint); */
-#endif /* __INTEL_SCU_WATCHDOG_H */