summaryrefslogtreecommitdiff
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig23
-rw-r--r--drivers/platform/x86/Makefile3
-rw-r--r--drivers/platform/x86/intel_mid_powerbtn.c233
-rw-r--r--drivers/platform/x86/intel_mid_thermal.c560
-rw-r--r--drivers/platform/x86/intel_scu_wdt.c75
5 files changed, 84 insertions, 810 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 91e6176cdfbd..0bb85eabace1 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1327,21 +1327,6 @@ config INTEL_CHTDC_TI_PWRBTN
To compile this driver as a module, choose M here: the module
will be called intel_chtdc_ti_pwrbtn.
-config INTEL_MFLD_THERMAL
- tristate "Thermal driver for Intel Medfield platform"
- depends on MFD_INTEL_MSIC && THERMAL
- help
- Say Y here to enable thermal driver support for the Intel Medfield
- platform.
-
-config INTEL_MID_POWER_BUTTON
- tristate "power button driver for Intel MID platforms"
- depends on INTEL_SCU && INPUT
- help
- This driver handles the power button on the Intel MID platforms.
-
- If unsure, say N.
-
config INTEL_MRFLD_PWRBTN
tristate "Intel Merrifield Basin Cove power button driver"
depends on INTEL_SOC_PMIC_MRFLD
@@ -1439,6 +1424,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 581475f59819..19306450d791 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -137,8 +137,6 @@ obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o
# Intel PMIC / PMC / P-Unit devices
obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o
obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
-obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
-obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o
obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o
obj-$(CONFIG_INTEL_PMT_CLASS) += intel_pmt_class.o
@@ -148,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_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c
deleted file mode 100644
index df434abbb66f..000000000000
--- a/drivers/platform/x86/intel_mid_powerbtn.c
+++ /dev/null
@@ -1,233 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Power button driver for Intel MID platforms.
- *
- * Copyright (C) 2010,2017 Intel Corp
- *
- * Author: Hong Liu <hong.liu@intel.com>
- * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
- */
-
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/intel_msic.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_wakeirq.h>
-#include <linux/slab.h>
-
-#include <asm/cpu_device_id.h>
-#include <asm/intel-family.h>
-#include <asm/intel_scu_ipc.h>
-
-#define DRIVER_NAME "msic_power_btn"
-
-#define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */
-
-/*
- * MSIC document ti_datasheet defines the 1st bit reg 0x21 is used to mask
- * power button interrupt
- */
-#define MSIC_PWRBTNM (1 << 0)
-
-/* Intel Tangier */
-#define BCOVE_PB_LEVEL (1 << 4) /* 1 - release, 0 - press */
-
-/* Basin Cove PMIC */
-#define BCOVE_PBIRQ 0x02
-#define BCOVE_IRQLVL1MSK 0x0c
-#define BCOVE_PBIRQMASK 0x0d
-#define BCOVE_PBSTATUS 0x27
-
-struct mid_pb_ddata {
- struct device *dev;
- int irq;
- struct input_dev *input;
- unsigned short mirqlvl1_addr;
- unsigned short pbstat_addr;
- u8 pbstat_mask;
- struct intel_scu_ipc_dev *scu;
- int (*setup)(struct mid_pb_ddata *ddata);
-};
-
-static int mid_pbstat(struct mid_pb_ddata *ddata, int *value)
-{
- struct input_dev *input = ddata->input;
- int ret;
- u8 pbstat;
-
- ret = intel_scu_ipc_dev_ioread8(ddata->scu, ddata->pbstat_addr,
- &pbstat);
- if (ret)
- return ret;
-
- dev_dbg(input->dev.parent, "PB_INT status= %d\n", pbstat);
-
- *value = !(pbstat & ddata->pbstat_mask);
- return 0;
-}
-
-static int mid_irq_ack(struct mid_pb_ddata *ddata)
-{
- return intel_scu_ipc_dev_update(ddata->scu, ddata->mirqlvl1_addr, 0,
- MSIC_PWRBTNM);
-}
-
-static int mrfld_setup(struct mid_pb_ddata *ddata)
-{
- /* Unmask the PBIRQ and MPBIRQ on Tangier */
- intel_scu_ipc_dev_update(ddata->scu, BCOVE_PBIRQ, 0, MSIC_PWRBTNM);
- intel_scu_ipc_dev_update(ddata->scu, BCOVE_PBIRQMASK, 0, MSIC_PWRBTNM);
-
- return 0;
-}
-
-static irqreturn_t mid_pb_isr(int irq, void *dev_id)
-{
- struct mid_pb_ddata *ddata = dev_id;
- struct input_dev *input = ddata->input;
- int value = 0;
- int ret;
-
- ret = mid_pbstat(ddata, &value);
- if (ret < 0) {
- dev_err(input->dev.parent,
- "Read error %d while reading MSIC_PB_STATUS\n", ret);
- } else {
- input_event(input, EV_KEY, KEY_POWER, value);
- input_sync(input);
- }
-
- mid_irq_ack(ddata);
- return IRQ_HANDLED;
-}
-
-static const struct mid_pb_ddata mfld_ddata = {
- .mirqlvl1_addr = INTEL_MSIC_IRQLVL1MSK,
- .pbstat_addr = INTEL_MSIC_PBSTATUS,
- .pbstat_mask = MSIC_PB_LEVEL,
-};
-
-static const struct mid_pb_ddata mrfld_ddata = {
- .mirqlvl1_addr = BCOVE_IRQLVL1MSK,
- .pbstat_addr = BCOVE_PBSTATUS,
- .pbstat_mask = BCOVE_PB_LEVEL,
- .setup = mrfld_setup,
-};
-
-static const struct x86_cpu_id mid_pb_cpu_ids[] = {
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL_MID, &mfld_ddata),
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &mrfld_ddata),
- {}
-};
-
-static int mid_pb_probe(struct platform_device *pdev)
-{
- const struct x86_cpu_id *id;
- struct mid_pb_ddata *ddata;
- struct input_dev *input;
- int irq = platform_get_irq(pdev, 0);
- int error;
-
- id = x86_match_cpu(mid_pb_cpu_ids);
- if (!id)
- return -ENODEV;
-
- if (irq < 0) {
- dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
- return irq;
- }
-
- input = devm_input_allocate_device(&pdev->dev);
- if (!input)
- return -ENOMEM;
-
- input->name = pdev->name;
- input->phys = "power-button/input0";
- input->id.bustype = BUS_HOST;
- input->dev.parent = &pdev->dev;
-
- input_set_capability(input, EV_KEY, KEY_POWER);
-
- ddata = devm_kmemdup(&pdev->dev, (void *)id->driver_data,
- sizeof(*ddata), GFP_KERNEL);
- if (!ddata)
- return -ENOMEM;
-
- ddata->dev = &pdev->dev;
- ddata->irq = irq;
- ddata->input = input;
-
- if (ddata->setup) {
- error = ddata->setup(ddata);
- if (error)
- return error;
- }
-
- ddata->scu = devm_intel_scu_ipc_dev_get(&pdev->dev);
- if (!ddata->scu)
- return -EPROBE_DEFER;
-
- error = devm_request_threaded_irq(&pdev->dev, irq, NULL, mid_pb_isr,
- IRQF_ONESHOT, DRIVER_NAME, ddata);
- if (error) {
- dev_err(&pdev->dev,
- "Unable to request irq %d for MID power button\n", irq);
- return error;
- }
-
- error = input_register_device(input);
- if (error) {
- dev_err(&pdev->dev,
- "Unable to register input dev, error %d\n", error);
- return error;
- }
-
- platform_set_drvdata(pdev, ddata);
-
- /*
- * SCU firmware might send power button interrupts to IA core before
- * kernel boots and doesn't get EOI from IA core. The first bit of
- * MSIC reg 0x21 is kept masked, and SCU firmware doesn't send new
- * power interrupt to Android kernel. Unmask the bit when probing
- * power button in kernel.
- * There is a very narrow race between irq handler and power button
- * initialization. The race happens rarely. So we needn't worry
- * about it.
- */
- error = mid_irq_ack(ddata);
- if (error) {
- dev_err(&pdev->dev,
- "Unable to clear power button interrupt, error: %d\n",
- error);
- return error;
- }
-
- device_init_wakeup(&pdev->dev, true);
- dev_pm_set_wake_irq(&pdev->dev, irq);
-
- return 0;
-}
-
-static int mid_pb_remove(struct platform_device *pdev)
-{
- dev_pm_clear_wake_irq(&pdev->dev);
- device_init_wakeup(&pdev->dev, false);
-
- return 0;
-}
-
-static struct platform_driver mid_pb_driver = {
- .driver = {
- .name = DRIVER_NAME,
- },
- .probe = mid_pb_probe,
- .remove = mid_pb_remove,
-};
-
-module_platform_driver(mid_pb_driver);
-
-MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
-MODULE_DESCRIPTION("Intel MID Power Button Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
deleted file mode 100644
index f12f4e7bd971..000000000000
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ /dev/null
@@ -1,560 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Intel MID platform thermal driver
- *
- * Copyright (C) 2011 Intel Corporation
- *
- * Author: Durgadoss R <durgadoss.r@intel.com>
- */
-
-#define pr_fmt(fmt) "intel_mid_thermal: " fmt
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/mfd/intel_msic.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/slab.h>
-#include <linux/thermal.h>
-
-/* Number of thermal sensors */
-#define MSIC_THERMAL_SENSORS 4
-
-/* ADC1 - thermal registers */
-#define MSIC_ADC_ENBL 0x10
-#define MSIC_ADC_START 0x08
-
-#define MSIC_ADCTHERM_ENBL 0x04
-#define MSIC_ADCRRDATA_ENBL 0x05
-#define MSIC_CHANL_MASK_VAL 0x0F
-
-#define MSIC_STOPBIT_MASK 16
-#define MSIC_ADCTHERM_MASK 4
-/* Number of ADC channels */
-#define ADC_CHANLS_MAX 15
-#define ADC_LOOP_MAX (ADC_CHANLS_MAX - MSIC_THERMAL_SENSORS)
-
-/* ADC channel code values */
-#define SKIN_SENSOR0_CODE 0x08
-#define SKIN_SENSOR1_CODE 0x09
-#define SYS_SENSOR_CODE 0x0A
-#define MSIC_DIE_SENSOR_CODE 0x03
-
-#define SKIN_THERM_SENSOR0 0
-#define SKIN_THERM_SENSOR1 1
-#define SYS_THERM_SENSOR2 2
-#define MSIC_DIE_THERM_SENSOR3 3
-
-/* ADC code range */
-#define ADC_MAX 977
-#define ADC_MIN 162
-#define ADC_VAL0C 887
-#define ADC_VAL20C 720
-#define ADC_VAL40C 508
-#define ADC_VAL60C 315
-
-/* ADC base addresses */
-#define ADC_CHNL_START_ADDR INTEL_MSIC_ADC1ADDR0 /* increments by 1 */
-#define ADC_DATA_START_ADDR INTEL_MSIC_ADC1SNS0H /* increments by 2 */
-
-/* MSIC die attributes */
-#define MSIC_DIE_ADC_MIN 488
-#define MSIC_DIE_ADC_MAX 1004
-
-/* This holds the address of the first free ADC channel,
- * among the 15 channels
- */
-static int channel_index;
-
-struct platform_info {
- struct platform_device *pdev;
- struct thermal_zone_device *tzd[MSIC_THERMAL_SENSORS];
-};
-
-struct thermal_device_info {
- unsigned int chnl_addr;
- int direct;
- /* This holds the current temperature in millidegree celsius */
- long curr_temp;
-};
-
-/**
- * to_msic_die_temp - converts adc_val to msic_die temperature
- * @adc_val: ADC value to be converted
- *
- * Can sleep
- */
-static int to_msic_die_temp(uint16_t adc_val)
-{
- return (368 * (adc_val) / 1000) - 220;
-}
-
-/**
- * is_valid_adc - checks whether the adc code is within the defined range
- * @min: minimum value for the sensor
- * @max: maximum value for the sensor
- *
- * Can sleep
- */
-static int is_valid_adc(uint16_t adc_val, uint16_t min, uint16_t max)
-{
- return (adc_val >= min) && (adc_val <= max);
-}
-
-/**
- * adc_to_temp - converts the ADC code to temperature in C
- * @direct: true if ths channel is direct index
- * @adc_val: the adc_val that needs to be converted
- * @tp: temperature return value
- *
- * Linear approximation is used to covert the skin adc value into temperature.
- * This technique is used to avoid very long look-up table to get
- * the appropriate temp value from ADC value.
- * The adc code vs sensor temp curve is split into five parts
- * to achieve very close approximate temp value with less than
- * 0.5C error
- */
-static int adc_to_temp(int direct, uint16_t adc_val, int *tp)
-{
- int temp;
-
- /* Direct conversion for die temperature */
- if (direct) {
- if (is_valid_adc(adc_val, MSIC_DIE_ADC_MIN, MSIC_DIE_ADC_MAX)) {
- *tp = to_msic_die_temp(adc_val) * 1000;
- return 0;
- }
- return -ERANGE;
- }
-
- if (!is_valid_adc(adc_val, ADC_MIN, ADC_MAX))
- return -ERANGE;
-
- /* Linear approximation for skin temperature */
- if (adc_val > ADC_VAL0C)
- temp = 177 - (adc_val/5);
- else if ((adc_val <= ADC_VAL0C) && (adc_val > ADC_VAL20C))
- temp = 111 - (adc_val/8);
- else if ((adc_val <= ADC_VAL20C) && (adc_val > ADC_VAL40C))
- temp = 92 - (adc_val/10);
- else if ((adc_val <= ADC_VAL40C) && (adc_val > ADC_VAL60C))
- temp = 91 - (adc_val/10);
- else
- temp = 112 - (adc_val/6);
-
- /* Convert temperature in celsius to milli degree celsius */
- *tp = temp * 1000;
- return 0;
-}
-
-/**
- * mid_read_temp - read sensors for temperature
- * @temp: holds the current temperature for the sensor after reading
- *
- * reads the adc_code from the channel and converts it to real
- * temperature. The converted value is stored in temp.
- *
- * Can sleep
- */
-static int mid_read_temp(struct thermal_zone_device *tzd, int *temp)
-{
- struct thermal_device_info *td_info = tzd->devdata;
- uint16_t adc_val, addr;
- uint8_t data = 0;
- int ret;
- int curr_temp;
-
- addr = td_info->chnl_addr;
-
- /* Enable the msic for conversion before reading */
- ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, MSIC_ADCRRDATA_ENBL);
- if (ret)
- return ret;
-
- /* Re-toggle the RRDATARD bit (temporary workaround) */
- ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, MSIC_ADCTHERM_ENBL);
- if (ret)
- return ret;
-
- /* Read the higher bits of data */
- ret = intel_msic_reg_read(addr, &data);
- if (ret)
- return ret;
-
- /* Shift bits to accommodate the lower two data bits */
- adc_val = (data << 2);
- addr++;
-
- ret = intel_msic_reg_read(addr, &data);/* Read lower bits */
- if (ret)
- return ret;
-
- /* Adding lower two bits to the higher bits */
- data &= 03;
- adc_val += data;
-
- /* Convert ADC value to temperature */
- ret = adc_to_temp(td_info->direct, adc_val, &curr_temp);
- if (ret == 0)
- *temp = td_info->curr_temp = curr_temp;
- return ret;
-}
-
-/**
- * configure_adc - enables/disables the ADC for conversion
- * @val: zero: disables the ADC non-zero:enables the ADC
- *
- * Enable/Disable the ADC depending on the argument
- *
- * Can sleep
- */
-static int configure_adc(int val)
-{
- int ret;
- uint8_t data;
-
- ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL1, &data);
- if (ret)
- return ret;
-
- if (val) {
- /* Enable and start the ADC */
- data |= (MSIC_ADC_ENBL | MSIC_ADC_START);
- } else {
- /* Just stop the ADC */
- data &= (~MSIC_ADC_START);
- }
- return intel_msic_reg_write(INTEL_MSIC_ADC1CNTL1, data);
-}
-
-/**
- * set_up_therm_channel - enable thermal channel for conversion
- * @base_addr: index of free msic ADC channel
- *
- * Enable all the three channels for conversion
- *
- * Can sleep
- */
-static int set_up_therm_channel(u16 base_addr)
-{
- int ret;
-
- /* Enable all the sensor channels */
- ret = intel_msic_reg_write(base_addr, SKIN_SENSOR0_CODE);
- if (ret)
- return ret;
-
- ret = intel_msic_reg_write(base_addr + 1, SKIN_SENSOR1_CODE);
- if (ret)
- return ret;
-
- ret = intel_msic_reg_write(base_addr + 2, SYS_SENSOR_CODE);
- if (ret)
- return ret;
-
- /* Since this is the last channel, set the stop bit
- * to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
- ret = intel_msic_reg_write(base_addr + 3,
- (MSIC_DIE_SENSOR_CODE | 0x10));
- if (ret)
- return ret;
-
- /* Enable ADC and start it */
- return configure_adc(1);
-}
-
-/**
- * reset_stopbit - sets the stop bit to 0 on the given channel
- * @addr: address of the channel
- *
- * Can sleep
- */
-static int reset_stopbit(uint16_t addr)
-{
- int ret;
- uint8_t data;
- ret = intel_msic_reg_read(addr, &data);
- if (ret)
- return ret;
- /* Set the stop bit to zero */
- return intel_msic_reg_write(addr, (data & 0xEF));
-}
-
-/**
- * find_free_channel - finds an empty channel for conversion
- *
- * If the ADC is not enabled then start using 0th channel
- * itself. Otherwise find an empty channel by looking for a
- * channel in which the stopbit is set to 1. returns the index
- * of the first free channel if succeeds or an error code.
- *
- * Context: can sleep
- *
- * FIXME: Ultimately the channel allocator will move into the intel_scu_ipc
- * code.
- */
-static int find_free_channel(void)
-{
- int ret;
- int i;
- uint8_t data;
-
- /* check whether ADC is enabled */
- ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL1, &data);
- if (ret)
- return ret;
-
- if ((data & MSIC_ADC_ENBL) == 0)
- return 0;
-
- /* ADC is already enabled; Looking for an empty channel */
- for (i = 0; i < ADC_CHANLS_MAX; i++) {
- ret = intel_msic_reg_read(ADC_CHNL_START_ADDR + i, &data);
- if (ret)
- return ret;
-
- if (data & MSIC_STOPBIT_MASK) {
- ret = i;
- break;
- }
- }
- return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
-}
-
-/**
- * mid_initialize_adc - initializing the ADC
- * @dev: our device structure
- *
- * Initialize the ADC for reading thermistor values. Can sleep.
- */
-static int mid_initialize_adc(struct device *dev)
-{
- u8 data;
- u16 base_addr;
- int ret;
-
- /*
- * Ensure that adctherm is disabled before we
- * initialize the ADC
- */
- ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL3, &data);
- if (ret)
- return ret;
-
- data &= ~MSIC_ADCTHERM_MASK;
- ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, data);
- if (ret)
- return ret;
-
- /* Index of the first channel in which the stop bit is set */
- channel_index = find_free_channel();
- if (channel_index < 0) {
- dev_err(dev, "No free ADC channels");
- return channel_index;
- }
-
- base_addr = ADC_CHNL_START_ADDR + channel_index;
-
- if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
- /* Reset stop bit for channels other than 0 and 12 */
- ret = reset_stopbit(base_addr);
- if (ret)
- return ret;
-
- /* Index of the first free channel */
- base_addr++;
- channel_index++;
- }
-
- ret = set_up_therm_channel(base_addr);
- if (ret) {
- dev_err(dev, "unable to enable ADC");
- return ret;
- }
- dev_dbg(dev, "ADC initialization successful");
- return ret;
-}
-
-/**
- * initialize_sensor - sets default temp and timer ranges
- * @index: index of the sensor
- *
- * Context: can sleep
- */
-static struct thermal_device_info *initialize_sensor(int index)
-{
- struct thermal_device_info *td_info =
- kzalloc(sizeof(struct thermal_device_info), GFP_KERNEL);
-
- if (!td_info)
- return NULL;
-
- /* Set the base addr of the channel for this sensor */
- td_info->chnl_addr = ADC_DATA_START_ADDR + 2 * (channel_index + index);
- /* Sensor 3 is direct conversion */
- if (index == 3)
- td_info->direct = 1;
- return td_info;
-}
-
-#ifdef CONFIG_PM_SLEEP
-/**
- * mid_thermal_resume - resume routine
- * @dev: device structure
- *
- * mid thermal resume: re-initializes the adc. Can sleep.
- */
-static int mid_thermal_resume(struct device *dev)
-{
- return mid_initialize_adc(dev);
-}
-
-/**
- * mid_thermal_suspend - suspend routine
- * @dev: device structure
- *
- * mid thermal suspend implements the suspend functionality
- * by stopping the ADC. Can sleep.
- */
-static int mid_thermal_suspend(struct device *dev)
-{
- /*
- * This just stops the ADC and does not disable it.
- * temporary workaround until we have a generic ADC driver.
- * If 0 is passed, it disables the ADC.
- */
- return configure_adc(0);
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(mid_thermal_pm,
- mid_thermal_suspend, mid_thermal_resume);
-
-/**
- * read_curr_temp - reads the current temperature and stores in temp
- * @temp: holds the current temperature value after reading
- *
- * Can sleep
- */
-static int read_curr_temp(struct thermal_zone_device *tzd, int *temp)
-{
- WARN_ON(tzd == NULL);
- return mid_read_temp(tzd, temp);
-}
-
-/* Can't be const */
-static struct thermal_zone_device_ops tzd_ops = {
- .get_temp = read_curr_temp,
-};
-
-/**
- * mid_thermal_probe - mfld thermal initialize
- * @pdev: platform device structure
- *
- * mid thermal probe initializes the hardware and registers
- * all the sensors with the generic thermal framework. Can sleep.
- */
-static int mid_thermal_probe(struct platform_device *pdev)
-{
- static char *name[MSIC_THERMAL_SENSORS] = {
- "skin0", "skin1", "sys", "msicdie"
- };
-
- int ret;
- int i;
- struct platform_info *pinfo;
-
- pinfo = devm_kzalloc(&pdev->dev, sizeof(struct platform_info),
- GFP_KERNEL);
- if (!pinfo)
- return -ENOMEM;
-
- /* Initializing the hardware */
- ret = mid_initialize_adc(&pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "ADC init failed");
- return ret;
- }
-
- /* Register each sensor with the generic thermal framework*/
- for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
- struct thermal_device_info *td_info = initialize_sensor(i);
-
- if (!td_info) {
- ret = -ENOMEM;
- goto err;
- }
- pinfo->tzd[i] = thermal_zone_device_register(name[i],
- 0, 0, td_info, &tzd_ops, NULL, 0, 0);
- if (IS_ERR(pinfo->tzd[i])) {
- kfree(td_info);
- ret = PTR_ERR(pinfo->tzd[i]);
- goto err;
- }
- ret = thermal_zone_device_enable(pinfo->tzd[i]);
- if (ret) {
- kfree(td_info);
- thermal_zone_device_unregister(pinfo->tzd[i]);
- goto err;
- }
- }
-
- pinfo->pdev = pdev;
- platform_set_drvdata(pdev, pinfo);
- return 0;
-
-err:
- while (--i >= 0) {
- kfree(pinfo->tzd[i]->devdata);
- thermal_zone_device_unregister(pinfo->tzd[i]);
- }
- configure_adc(0);
- return ret;
-}
-
-/**
- * mid_thermal_remove - mfld thermal finalize
- * @dev: platform device structure
- *
- * MLFD thermal remove unregisters all the sensors from the generic
- * thermal framework. Can sleep.
- */
-static int mid_thermal_remove(struct platform_device *pdev)
-{
- int i;
- struct platform_info *pinfo = platform_get_drvdata(pdev);
-
- for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
- kfree(pinfo->tzd[i]->devdata);
- thermal_zone_device_unregister(pinfo->tzd[i]);
- }
-
- /* Stop the ADC */
- return configure_adc(0);
-}
-
-#define DRIVER_NAME "msic_thermal"
-
-static const struct platform_device_id therm_id_table[] = {
- { DRIVER_NAME, 1 },
- { }
-};
-MODULE_DEVICE_TABLE(platform, therm_id_table);
-
-static struct platform_driver mid_thermal_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .pm = &mid_thermal_pm,
- },
- .probe = mid_thermal_probe,
- .remove = mid_thermal_remove,
- .id_table = therm_id_table,
-};
-
-module_platform_driver(mid_thermal_driver);
-
-MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
-MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/intel_scu_wdt.c b/drivers/platform/x86/intel_scu_wdt.c
new file mode 100644
index 000000000000..c2479777a1d6
--- /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 = (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);