/*
 * ST Thermal Sensor Driver for memory mapped sensors.
 * Author: Ajit Pal Singh <ajitpal.singh@st.com>
 *
 * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/of.h>
#include <linux/module.h>

#include "st_thermal.h"

#define STIH416_MPE_CONF			0x0
#define STIH416_MPE_STATUS			0x4
#define STIH416_MPE_INT_THRESH			0x8
#define STIH416_MPE_INT_EN			0xC

/* Power control bits for the memory mapped thermal sensor */
#define THERMAL_PDN				BIT(4)
#define THERMAL_SRSTN				BIT(10)

static const struct reg_field st_mmap_thermal_regfields[MAX_REGFIELDS] = {
	/*
	 * According to the STIH416 MPE temp sensor data sheet -
	 * the PDN (Power Down Bit) and SRSTN (Soft Reset Bit) need to be
	 * written simultaneously for powering on and off the temperature
	 * sensor. regmap_update_bits() will be used to update the register.
	 */
	[INT_THRESH_HI]	= REG_FIELD(STIH416_MPE_INT_THRESH, 	0,  7),
	[DCORRECT]	= REG_FIELD(STIH416_MPE_CONF,		5,  9),
	[OVERFLOW]	= REG_FIELD(STIH416_MPE_STATUS,		9,  9),
	[DATA]		= REG_FIELD(STIH416_MPE_STATUS,		11, 18),
	[INT_ENABLE]	= REG_FIELD(STIH416_MPE_INT_EN,		0,  0),
};

static irqreturn_t st_mmap_thermal_trip_handler(int irq, void *sdata)
{
	struct st_thermal_sensor *sensor = sdata;

	thermal_zone_device_update(sensor->thermal_dev,
				   THERMAL_EVENT_UNSPECIFIED);

	return IRQ_HANDLED;
}

/* Private ops for the Memory Mapped based thermal sensors */
static int st_mmap_power_ctrl(struct st_thermal_sensor *sensor,
			      enum st_thermal_power_state power_state)
{
	const unsigned int mask = (THERMAL_PDN | THERMAL_SRSTN);
	const unsigned int val = power_state ? mask : 0;

	return regmap_update_bits(sensor->regmap, STIH416_MPE_CONF, mask, val);
}

static int st_mmap_alloc_regfields(struct st_thermal_sensor *sensor)
{
	struct device *dev = sensor->dev;
	struct regmap *regmap = sensor->regmap;
	const struct reg_field *reg_fields = sensor->cdata->reg_fields;

	sensor->int_thresh_hi = devm_regmap_field_alloc(dev, regmap,
						reg_fields[INT_THRESH_HI]);
	sensor->int_enable = devm_regmap_field_alloc(dev, regmap,
						reg_fields[INT_ENABLE]);

	if (IS_ERR(sensor->int_thresh_hi) || IS_ERR(sensor->int_enable)) {
		dev_err(dev, "failed to alloc mmap regfields\n");
		return -EINVAL;
	}

	return 0;
}

static int st_mmap_enable_irq(struct st_thermal_sensor *sensor)
{
	int ret;

	/* Set upper critical threshold */
	ret = regmap_field_write(sensor->int_thresh_hi,
				 sensor->cdata->crit_temp -
				 sensor->cdata->temp_adjust_val);
	if (ret)
		return ret;

	return regmap_field_write(sensor->int_enable, 1);
}

static int st_mmap_register_enable_irq(struct st_thermal_sensor *sensor)
{
	struct device *dev = sensor->dev;
	struct platform_device *pdev = to_platform_device(dev);
	int ret;

	sensor->irq = platform_get_irq(pdev, 0);
	if (sensor->irq < 0) {
		dev_err(dev, "failed to register IRQ\n");
		return sensor->irq;
	}

	ret = devm_request_threaded_irq(dev, sensor->irq,
					NULL, st_mmap_thermal_trip_handler,
					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
					dev->driver->name, sensor);
	if (ret) {
		dev_err(dev, "failed to register IRQ %d\n", sensor->irq);
		return ret;
	}

	return st_mmap_enable_irq(sensor);
}

static const struct regmap_config st_416mpe_regmap_config = {
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,
};

static int st_mmap_regmap_init(struct st_thermal_sensor *sensor)
{
	struct device *dev = sensor->dev;
	struct platform_device *pdev = to_platform_device(dev);
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "no memory resources defined\n");
		return -ENODEV;
	}

	sensor->mmio_base = devm_ioremap_resource(dev, res);
	if (IS_ERR(sensor->mmio_base)) {
		dev_err(dev, "failed to remap IO\n");
		return PTR_ERR(sensor->mmio_base);
	}

	sensor->regmap = devm_regmap_init_mmio(dev, sensor->mmio_base,
				&st_416mpe_regmap_config);
	if (IS_ERR(sensor->regmap)) {
		dev_err(dev, "failed to initialise regmap\n");
		return PTR_ERR(sensor->regmap);
	}

	return 0;
}

static const struct st_thermal_sensor_ops st_mmap_sensor_ops = {
	.power_ctrl		= st_mmap_power_ctrl,
	.alloc_regfields	= st_mmap_alloc_regfields,
	.regmap_init		= st_mmap_regmap_init,
	.register_enable_irq	= st_mmap_register_enable_irq,
	.enable_irq		= st_mmap_enable_irq,
};

/* Compatible device data stih416 mpe thermal sensor */
static const struct st_thermal_compat_data st_416mpe_cdata = {
	.reg_fields		= st_mmap_thermal_regfields,
	.ops			= &st_mmap_sensor_ops,
	.calibration_val	= 14,
	.temp_adjust_val	= -95,
	.crit_temp		= 120,
};

/* Compatible device data stih407 thermal sensor */
static const struct st_thermal_compat_data st_407_cdata = {
	.reg_fields		= st_mmap_thermal_regfields,
	.ops			= &st_mmap_sensor_ops,
	.calibration_val	= 16,
	.temp_adjust_val	= -95,
	.crit_temp		= 120,
};

static const struct of_device_id st_mmap_thermal_of_match[] = {
	{ .compatible = "st,stih416-mpe-thermal", .data = &st_416mpe_cdata },
	{ .compatible = "st,stih407-thermal",     .data = &st_407_cdata },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, st_mmap_thermal_of_match);

static int st_mmap_probe(struct platform_device *pdev)
{
	return st_thermal_register(pdev,  st_mmap_thermal_of_match);
}

static int st_mmap_remove(struct platform_device *pdev)
{
	return st_thermal_unregister(pdev);
}

static struct platform_driver st_mmap_thermal_driver = {
	.driver = {
		.name	= "st_thermal_mmap",
		.pm     = &st_thermal_pm_ops,
		.of_match_table = st_mmap_thermal_of_match,
	},
	.probe		= st_mmap_probe,
	.remove		= st_mmap_remove,
};

module_platform_driver(st_mmap_thermal_driver);

MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>");
MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver");
MODULE_LICENSE("GPL v2");
