linux/drivers/thermal/st/st_thermal_memmap.c
<<
>>
Prefs
   1/*
   2 * ST Thermal Sensor Driver for memory mapped sensors.
   3 * Author: Ajit Pal Singh <ajitpal.singh@st.com>
   4 *
   5 * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 */
  12
  13#include <linux/of.h>
  14#include <linux/module.h>
  15
  16#include "st_thermal.h"
  17
  18#define STIH416_MPE_CONF                        0x0
  19#define STIH416_MPE_STATUS                      0x4
  20#define STIH416_MPE_INT_THRESH                  0x8
  21#define STIH416_MPE_INT_EN                      0xC
  22
  23/* Power control bits for the memory mapped thermal sensor */
  24#define THERMAL_PDN                             BIT(4)
  25#define THERMAL_SRSTN                           BIT(10)
  26
  27static const struct reg_field st_mmap_thermal_regfields[MAX_REGFIELDS] = {
  28        /*
  29         * According to the STIH416 MPE temp sensor data sheet -
  30         * the PDN (Power Down Bit) and SRSTN (Soft Reset Bit) need to be
  31         * written simultaneously for powering on and off the temperature
  32         * sensor. regmap_update_bits() will be used to update the register.
  33         */
  34        [INT_THRESH_HI] = REG_FIELD(STIH416_MPE_INT_THRESH,     0,  7),
  35        [DCORRECT]      = REG_FIELD(STIH416_MPE_CONF,           5,  9),
  36        [OVERFLOW]      = REG_FIELD(STIH416_MPE_STATUS,         9,  9),
  37        [DATA]          = REG_FIELD(STIH416_MPE_STATUS,         11, 18),
  38        [INT_ENABLE]    = REG_FIELD(STIH416_MPE_INT_EN,         0,  0),
  39};
  40
  41static irqreturn_t st_mmap_thermal_trip_handler(int irq, void *sdata)
  42{
  43        struct st_thermal_sensor *sensor = sdata;
  44
  45        thermal_zone_device_update(sensor->thermal_dev);
  46
  47        return IRQ_HANDLED;
  48}
  49
  50/* Private ops for the Memory Mapped based thermal sensors */
  51static int st_mmap_power_ctrl(struct st_thermal_sensor *sensor,
  52                              enum st_thermal_power_state power_state)
  53{
  54        const unsigned int mask = (THERMAL_PDN | THERMAL_SRSTN);
  55        const unsigned int val = power_state ? mask : 0;
  56
  57        return regmap_update_bits(sensor->regmap, STIH416_MPE_CONF, mask, val);
  58}
  59
  60static int st_mmap_alloc_regfields(struct st_thermal_sensor *sensor)
  61{
  62        struct device *dev = sensor->dev;
  63        struct regmap *regmap = sensor->regmap;
  64        const struct reg_field *reg_fields = sensor->cdata->reg_fields;
  65
  66        sensor->int_thresh_hi = devm_regmap_field_alloc(dev, regmap,
  67                                                reg_fields[INT_THRESH_HI]);
  68        sensor->int_enable = devm_regmap_field_alloc(dev, regmap,
  69                                                reg_fields[INT_ENABLE]);
  70
  71        if (IS_ERR(sensor->int_thresh_hi) || IS_ERR(sensor->int_enable)) {
  72                dev_err(dev, "failed to alloc mmap regfields\n");
  73                return -EINVAL;
  74        }
  75
  76        return 0;
  77}
  78
  79static int st_mmap_enable_irq(struct st_thermal_sensor *sensor)
  80{
  81        int ret;
  82
  83        /* Set upper critical threshold */
  84        ret = regmap_field_write(sensor->int_thresh_hi,
  85                                 sensor->cdata->crit_temp -
  86                                 sensor->cdata->temp_adjust_val);
  87        if (ret)
  88                return ret;
  89
  90        return regmap_field_write(sensor->int_enable, 1);
  91}
  92
  93static int st_mmap_register_enable_irq(struct st_thermal_sensor *sensor)
  94{
  95        struct device *dev = sensor->dev;
  96        struct platform_device *pdev = to_platform_device(dev);
  97        int ret;
  98
  99        sensor->irq = platform_get_irq(pdev, 0);
 100        if (sensor->irq < 0) {
 101                dev_err(dev, "failed to register IRQ\n");
 102                return sensor->irq;
 103        }
 104
 105        ret = devm_request_threaded_irq(dev, sensor->irq,
 106                                        NULL, st_mmap_thermal_trip_handler,
 107                                        IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 108                                        dev->driver->name, sensor);
 109        if (ret) {
 110                dev_err(dev, "failed to register IRQ %d\n", sensor->irq);
 111                return ret;
 112        }
 113
 114        return st_mmap_enable_irq(sensor);
 115}
 116
 117static const struct regmap_config st_416mpe_regmap_config = {
 118        .reg_bits = 32,
 119        .val_bits = 32,
 120        .reg_stride = 4,
 121};
 122
 123static int st_mmap_regmap_init(struct st_thermal_sensor *sensor)
 124{
 125        struct device *dev = sensor->dev;
 126        struct platform_device *pdev = to_platform_device(dev);
 127        struct resource *res;
 128
 129        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 130        if (!res) {
 131                dev_err(dev, "no memory resources defined\n");
 132                return -ENODEV;
 133        }
 134
 135        sensor->mmio_base = devm_ioremap_resource(dev, res);
 136        if (IS_ERR(sensor->mmio_base)) {
 137                dev_err(dev, "failed to remap IO\n");
 138                return PTR_ERR(sensor->mmio_base);
 139        }
 140
 141        sensor->regmap = devm_regmap_init_mmio(dev, sensor->mmio_base,
 142                                &st_416mpe_regmap_config);
 143        if (IS_ERR(sensor->regmap)) {
 144                dev_err(dev, "failed to initialise regmap\n");
 145                return PTR_ERR(sensor->regmap);
 146        }
 147
 148        return 0;
 149}
 150
 151static const struct st_thermal_sensor_ops st_mmap_sensor_ops = {
 152        .power_ctrl             = st_mmap_power_ctrl,
 153        .alloc_regfields        = st_mmap_alloc_regfields,
 154        .regmap_init            = st_mmap_regmap_init,
 155        .register_enable_irq    = st_mmap_register_enable_irq,
 156        .enable_irq             = st_mmap_enable_irq,
 157};
 158
 159/* Compatible device data stih416 mpe thermal sensor */
 160static const struct st_thermal_compat_data st_416mpe_cdata = {
 161        .reg_fields             = st_mmap_thermal_regfields,
 162        .ops                    = &st_mmap_sensor_ops,
 163        .calibration_val        = 14,
 164        .temp_adjust_val        = -95,
 165        .crit_temp              = 120,
 166};
 167
 168/* Compatible device data stih407 thermal sensor */
 169static const struct st_thermal_compat_data st_407_cdata = {
 170        .reg_fields             = st_mmap_thermal_regfields,
 171        .ops                    = &st_mmap_sensor_ops,
 172        .calibration_val        = 16,
 173        .temp_adjust_val        = -95,
 174        .crit_temp              = 120,
 175};
 176
 177static const struct of_device_id st_mmap_thermal_of_match[] = {
 178        { .compatible = "st,stih416-mpe-thermal", .data = &st_416mpe_cdata },
 179        { .compatible = "st,stih407-thermal",     .data = &st_407_cdata },
 180        { /* sentinel */ }
 181};
 182MODULE_DEVICE_TABLE(of, st_mmap_thermal_of_match);
 183
 184static int st_mmap_probe(struct platform_device *pdev)
 185{
 186        return st_thermal_register(pdev,  st_mmap_thermal_of_match);
 187}
 188
 189static int st_mmap_remove(struct platform_device *pdev)
 190{
 191        return st_thermal_unregister(pdev);
 192}
 193
 194static struct platform_driver st_mmap_thermal_driver = {
 195        .driver = {
 196                .name   = "st_thermal_mmap",
 197                .pm     = &st_thermal_pm_ops,
 198                .of_match_table = st_mmap_thermal_of_match,
 199        },
 200        .probe          = st_mmap_probe,
 201        .remove         = st_mmap_remove,
 202};
 203
 204module_platform_driver(st_mmap_thermal_driver);
 205
 206MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>");
 207MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver");
 208MODULE_LICENSE("GPL v2");
 209