linux/drivers/thermal/armada_thermal.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Marvell EBU Armada SoCs thermal sensor driver
   4 *
   5 * Copyright (C) 2013 Marvell
   6 */
   7#include <linux/device.h>
   8#include <linux/err.h>
   9#include <linux/io.h>
  10#include <linux/kernel.h>
  11#include <linux/of.h>
  12#include <linux/module.h>
  13#include <linux/delay.h>
  14#include <linux/platform_device.h>
  15#include <linux/of_device.h>
  16#include <linux/thermal.h>
  17#include <linux/iopoll.h>
  18#include <linux/mfd/syscon.h>
  19#include <linux/regmap.h>
  20#include <linux/interrupt.h>
  21
  22#include "thermal_core.h"
  23
  24/* Thermal Manager Control and Status Register */
  25#define PMU_TDC0_SW_RST_MASK            (0x1 << 1)
  26#define PMU_TM_DISABLE_OFFS             0
  27#define PMU_TM_DISABLE_MASK             (0x1 << PMU_TM_DISABLE_OFFS)
  28#define PMU_TDC0_REF_CAL_CNT_OFFS       11
  29#define PMU_TDC0_REF_CAL_CNT_MASK       (0x1ff << PMU_TDC0_REF_CAL_CNT_OFFS)
  30#define PMU_TDC0_OTF_CAL_MASK           (0x1 << 30)
  31#define PMU_TDC0_START_CAL_MASK         (0x1 << 25)
  32
  33#define A375_UNIT_CONTROL_SHIFT         27
  34#define A375_UNIT_CONTROL_MASK          0x7
  35#define A375_READOUT_INVERT             BIT(15)
  36#define A375_HW_RESETn                  BIT(8)
  37
  38/* Errata fields */
  39#define CONTROL0_TSEN_TC_TRIM_MASK      0x7
  40#define CONTROL0_TSEN_TC_TRIM_VAL       0x3
  41
  42#define CONTROL0_TSEN_START             BIT(0)
  43#define CONTROL0_TSEN_RESET             BIT(1)
  44#define CONTROL0_TSEN_ENABLE            BIT(2)
  45#define CONTROL0_TSEN_AVG_BYPASS        BIT(6)
  46#define CONTROL0_TSEN_CHAN_SHIFT        13
  47#define CONTROL0_TSEN_CHAN_MASK         0xF
  48#define CONTROL0_TSEN_OSR_SHIFT         24
  49#define CONTROL0_TSEN_OSR_MAX           0x3
  50#define CONTROL0_TSEN_MODE_SHIFT        30
  51#define CONTROL0_TSEN_MODE_EXTERNAL     0x2
  52#define CONTROL0_TSEN_MODE_MASK         0x3
  53
  54#define CONTROL1_TSEN_AVG_MASK          0x7
  55#define CONTROL1_EXT_TSEN_SW_RESET      BIT(7)
  56#define CONTROL1_EXT_TSEN_HW_RESETn     BIT(8)
  57#define CONTROL1_TSEN_INT_EN            BIT(25)
  58#define CONTROL1_TSEN_SELECT_OFF        21
  59#define CONTROL1_TSEN_SELECT_MASK       0x3
  60
  61#define STATUS_POLL_PERIOD_US           1000
  62#define STATUS_POLL_TIMEOUT_US          100000
  63#define OVERHEAT_INT_POLL_DELAY_MS      1000
  64
  65struct armada_thermal_data;
  66
  67/* Marvell EBU Thermal Sensor Dev Structure */
  68struct armada_thermal_priv {
  69        struct device *dev;
  70        struct regmap *syscon;
  71        char zone_name[THERMAL_NAME_LENGTH];
  72        /* serialize temperature reads/updates */
  73        struct mutex update_lock;
  74        struct armada_thermal_data *data;
  75        struct thermal_zone_device *overheat_sensor;
  76        int interrupt_source;
  77        int current_channel;
  78        long current_threshold;
  79        long current_hysteresis;
  80};
  81
  82struct armada_thermal_data {
  83        /* Initialize the thermal IC */
  84        void (*init)(struct platform_device *pdev,
  85                     struct armada_thermal_priv *priv);
  86
  87        /* Formula coeficients: temp = (b - m * reg) / div */
  88        s64 coef_b;
  89        s64 coef_m;
  90        u32 coef_div;
  91        bool inverted;
  92        bool signed_sample;
  93
  94        /* Register shift and mask to access the sensor temperature */
  95        unsigned int temp_shift;
  96        unsigned int temp_mask;
  97        unsigned int thresh_shift;
  98        unsigned int hyst_shift;
  99        unsigned int hyst_mask;
 100        u32 is_valid_bit;
 101
 102        /* Syscon access */
 103        unsigned int syscon_control0_off;
 104        unsigned int syscon_control1_off;
 105        unsigned int syscon_status_off;
 106        unsigned int dfx_irq_cause_off;
 107        unsigned int dfx_irq_mask_off;
 108        unsigned int dfx_overheat_irq;
 109        unsigned int dfx_server_irq_mask_off;
 110        unsigned int dfx_server_irq_en;
 111
 112        /* One sensor is in the thermal IC, the others are in the CPUs if any */
 113        unsigned int cpu_nr;
 114};
 115
 116struct armada_drvdata {
 117        enum drvtype {
 118                LEGACY,
 119                SYSCON
 120        } type;
 121        union {
 122                struct armada_thermal_priv *priv;
 123                struct thermal_zone_device *tz;
 124        } data;
 125};
 126
 127/*
 128 * struct armada_thermal_sensor - hold the information of one thermal sensor
 129 * @thermal: pointer to the local private structure
 130 * @tzd: pointer to the thermal zone device
 131 * @id: identifier of the thermal sensor
 132 */
 133struct armada_thermal_sensor {
 134        struct armada_thermal_priv *priv;
 135        int id;
 136};
 137
 138static void armadaxp_init(struct platform_device *pdev,
 139                          struct armada_thermal_priv *priv)
 140{
 141        struct armada_thermal_data *data = priv->data;
 142        u32 reg;
 143
 144        regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 145        reg |= PMU_TDC0_OTF_CAL_MASK;
 146
 147        /* Reference calibration value */
 148        reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
 149        reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
 150
 151        /* Reset the sensor */
 152        reg |= PMU_TDC0_SW_RST_MASK;
 153
 154        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 155
 156        reg &= ~PMU_TDC0_SW_RST_MASK;
 157        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 158
 159        /* Enable the sensor */
 160        regmap_read(priv->syscon, data->syscon_status_off, &reg);
 161        reg &= ~PMU_TM_DISABLE_MASK;
 162        regmap_write(priv->syscon, data->syscon_status_off, reg);
 163}
 164
 165static void armada370_init(struct platform_device *pdev,
 166                           struct armada_thermal_priv *priv)
 167{
 168        struct armada_thermal_data *data = priv->data;
 169        u32 reg;
 170
 171        regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 172        reg |= PMU_TDC0_OTF_CAL_MASK;
 173
 174        /* Reference calibration value */
 175        reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
 176        reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
 177
 178        /* Reset the sensor */
 179        reg &= ~PMU_TDC0_START_CAL_MASK;
 180
 181        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 182
 183        msleep(10);
 184}
 185
 186static void armada375_init(struct platform_device *pdev,
 187                           struct armada_thermal_priv *priv)
 188{
 189        struct armada_thermal_data *data = priv->data;
 190        u32 reg;
 191
 192        regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 193        reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
 194        reg &= ~A375_READOUT_INVERT;
 195        reg &= ~A375_HW_RESETn;
 196        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 197
 198        msleep(20);
 199
 200        reg |= A375_HW_RESETn;
 201        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 202
 203        msleep(50);
 204}
 205
 206static int armada_wait_sensor_validity(struct armada_thermal_priv *priv)
 207{
 208        u32 reg;
 209
 210        return regmap_read_poll_timeout(priv->syscon,
 211                                        priv->data->syscon_status_off, reg,
 212                                        reg & priv->data->is_valid_bit,
 213                                        STATUS_POLL_PERIOD_US,
 214                                        STATUS_POLL_TIMEOUT_US);
 215}
 216
 217static void armada380_init(struct platform_device *pdev,
 218                           struct armada_thermal_priv *priv)
 219{
 220        struct armada_thermal_data *data = priv->data;
 221        u32 reg;
 222
 223        /* Disable the HW/SW reset */
 224        regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 225        reg |= CONTROL1_EXT_TSEN_HW_RESETn;
 226        reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
 227        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 228
 229        /* Set Tsen Tc Trim to correct default value (errata #132698) */
 230        regmap_read(priv->syscon, data->syscon_control0_off, &reg);
 231        reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
 232        reg |= CONTROL0_TSEN_TC_TRIM_VAL;
 233        regmap_write(priv->syscon, data->syscon_control0_off, reg);
 234}
 235
 236static void armada_ap806_init(struct platform_device *pdev,
 237                              struct armada_thermal_priv *priv)
 238{
 239        struct armada_thermal_data *data = priv->data;
 240        u32 reg;
 241
 242        regmap_read(priv->syscon, data->syscon_control0_off, &reg);
 243        reg &= ~CONTROL0_TSEN_RESET;
 244        reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE;
 245
 246        /* Sample every ~2ms */
 247        reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
 248
 249        /* Enable average (2 samples by default) */
 250        reg &= ~CONTROL0_TSEN_AVG_BYPASS;
 251
 252        regmap_write(priv->syscon, data->syscon_control0_off, reg);
 253}
 254
 255static void armada_cp110_init(struct platform_device *pdev,
 256                              struct armada_thermal_priv *priv)
 257{
 258        struct armada_thermal_data *data = priv->data;
 259        u32 reg;
 260
 261        armada380_init(pdev, priv);
 262
 263        /* Sample every ~2ms */
 264        regmap_read(priv->syscon, data->syscon_control0_off, &reg);
 265        reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
 266        regmap_write(priv->syscon, data->syscon_control0_off, reg);
 267
 268        /* Average the output value over 2^1 = 2 samples */
 269        regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 270        reg &= ~CONTROL1_TSEN_AVG_MASK;
 271        reg |= 1;
 272        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 273}
 274
 275static bool armada_is_valid(struct armada_thermal_priv *priv)
 276{
 277        u32 reg;
 278
 279        if (!priv->data->is_valid_bit)
 280                return true;
 281
 282        regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
 283
 284        return reg & priv->data->is_valid_bit;
 285}
 286
 287static void armada_enable_overheat_interrupt(struct armada_thermal_priv *priv)
 288{
 289        struct armada_thermal_data *data = priv->data;
 290        u32 reg;
 291
 292        /* Clear DFX temperature IRQ cause */
 293        regmap_read(priv->syscon, data->dfx_irq_cause_off, &reg);
 294
 295        /* Enable DFX Temperature IRQ */
 296        regmap_read(priv->syscon, data->dfx_irq_mask_off, &reg);
 297        reg |= data->dfx_overheat_irq;
 298        regmap_write(priv->syscon, data->dfx_irq_mask_off, reg);
 299
 300        /* Enable DFX server IRQ */
 301        regmap_read(priv->syscon, data->dfx_server_irq_mask_off, &reg);
 302        reg |= data->dfx_server_irq_en;
 303        regmap_write(priv->syscon, data->dfx_server_irq_mask_off, reg);
 304
 305        /* Enable overheat interrupt */
 306        regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 307        reg |= CONTROL1_TSEN_INT_EN;
 308        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 309}
 310
 311static void __maybe_unused
 312armada_disable_overheat_interrupt(struct armada_thermal_priv *priv)
 313{
 314        struct armada_thermal_data *data = priv->data;
 315        u32 reg;
 316
 317        regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 318        reg &= ~CONTROL1_TSEN_INT_EN;
 319        regmap_write(priv->syscon, data->syscon_control1_off, reg);
 320}
 321
 322/* There is currently no board with more than one sensor per channel */
 323static int armada_select_channel(struct armada_thermal_priv *priv, int channel)
 324{
 325        struct armada_thermal_data *data = priv->data;
 326        u32 ctrl0;
 327
 328        if (channel < 0 || channel > priv->data->cpu_nr)
 329                return -EINVAL;
 330
 331        if (priv->current_channel == channel)
 332                return 0;
 333
 334        /* Stop the measurements */
 335        regmap_read(priv->syscon, data->syscon_control0_off, &ctrl0);
 336        ctrl0 &= ~CONTROL0_TSEN_START;
 337        regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
 338
 339        /* Reset the mode, internal sensor will be automatically selected */
 340        ctrl0 &= ~(CONTROL0_TSEN_MODE_MASK << CONTROL0_TSEN_MODE_SHIFT);
 341
 342        /* Other channels are external and should be selected accordingly */
 343        if (channel) {
 344                /* Change the mode to external */
 345                ctrl0 |= CONTROL0_TSEN_MODE_EXTERNAL <<
 346                         CONTROL0_TSEN_MODE_SHIFT;
 347                /* Select the sensor */
 348                ctrl0 &= ~(CONTROL0_TSEN_CHAN_MASK << CONTROL0_TSEN_CHAN_SHIFT);
 349                ctrl0 |= (channel - 1) << CONTROL0_TSEN_CHAN_SHIFT;
 350        }
 351
 352        /* Actually set the mode/channel */
 353        regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
 354        priv->current_channel = channel;
 355
 356        /* Re-start the measurements */
 357        ctrl0 |= CONTROL0_TSEN_START;
 358        regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
 359
 360        /*
 361         * The IP has a latency of ~15ms, so after updating the selected source,
 362         * we must absolutely wait for the sensor validity bit to ensure we read
 363         * actual data.
 364         */
 365        if (armada_wait_sensor_validity(priv)) {
 366                dev_err(priv->dev,
 367                        "Temperature sensor reading not valid\n");
 368                return -EIO;
 369        }
 370
 371        return 0;
 372}
 373
 374static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp)
 375{
 376        u32 reg, div;
 377        s64 sample, b, m;
 378
 379        regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
 380        reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask;
 381        if (priv->data->signed_sample)
 382                /* The most significant bit is the sign bit */
 383                sample = sign_extend32(reg, fls(priv->data->temp_mask) - 1);
 384        else
 385                sample = reg;
 386
 387        /* Get formula coeficients */
 388        b = priv->data->coef_b;
 389        m = priv->data->coef_m;
 390        div = priv->data->coef_div;
 391
 392        if (priv->data->inverted)
 393                *temp = div_s64((m * sample) - b, div);
 394        else
 395                *temp = div_s64(b - (m * sample), div);
 396
 397        return 0;
 398}
 399
 400static int armada_get_temp_legacy(struct thermal_zone_device *thermal,
 401                                  int *temp)
 402{
 403        struct armada_thermal_priv *priv = thermal->devdata;
 404        int ret;
 405
 406        /* Valid check */
 407        if (!armada_is_valid(priv)) {
 408                dev_err(priv->dev,
 409                        "Temperature sensor reading not valid\n");
 410                return -EIO;
 411        }
 412
 413        /* Do the actual reading */
 414        ret = armada_read_sensor(priv, temp);
 415
 416        return ret;
 417}
 418
 419static struct thermal_zone_device_ops legacy_ops = {
 420        .get_temp = armada_get_temp_legacy,
 421};
 422
 423static int armada_get_temp(void *_sensor, int *temp)
 424{
 425        struct armada_thermal_sensor *sensor = _sensor;
 426        struct armada_thermal_priv *priv = sensor->priv;
 427        int ret;
 428
 429        mutex_lock(&priv->update_lock);
 430
 431        /* Select the desired channel */
 432        ret = armada_select_channel(priv, sensor->id);
 433        if (ret)
 434                goto unlock_mutex;
 435
 436        /* Do the actual reading */
 437        ret = armada_read_sensor(priv, temp);
 438        if (ret)
 439                goto unlock_mutex;
 440
 441        /*
 442         * Select back the interrupt source channel from which a potential
 443         * critical trip point has been set.
 444         */
 445        ret = armada_select_channel(priv, priv->interrupt_source);
 446
 447unlock_mutex:
 448        mutex_unlock(&priv->update_lock);
 449
 450        return ret;
 451}
 452
 453static const struct thermal_zone_of_device_ops of_ops = {
 454        .get_temp = armada_get_temp,
 455};
 456
 457static unsigned int armada_mc_to_reg_temp(struct armada_thermal_data *data,
 458                                          unsigned int temp_mc)
 459{
 460        s64 b = data->coef_b;
 461        s64 m = data->coef_m;
 462        s64 div = data->coef_div;
 463        unsigned int sample;
 464
 465        if (data->inverted)
 466                sample = div_s64(((temp_mc * div) + b), m);
 467        else
 468                sample = div_s64((b - (temp_mc * div)), m);
 469
 470        return sample & data->temp_mask;
 471}
 472
 473/*
 474 * The documentation states:
 475 * high/low watermark = threshold +/- 0.4761 * 2^(hysteresis + 2)
 476 * which is the mathematical derivation for:
 477 * 0x0 <=> 1.9°C, 0x1 <=> 3.8°C, 0x2 <=> 7.6°C, 0x3 <=> 15.2°C
 478 */
 479static unsigned int hyst_levels_mc[] = {1900, 3800, 7600, 15200};
 480
 481static unsigned int armada_mc_to_reg_hyst(struct armada_thermal_data *data,
 482                                          unsigned int hyst_mc)
 483{
 484        int i;
 485
 486        /*
 487         * We will always take the smallest possible hysteresis to avoid risking
 488         * the hardware integrity by enlarging the threshold by +8°C in the
 489         * worst case.
 490         */
 491        for (i = ARRAY_SIZE(hyst_levels_mc) - 1; i > 0; i--)
 492                if (hyst_mc >= hyst_levels_mc[i])
 493                        break;
 494
 495        return i & data->hyst_mask;
 496}
 497
 498static void armada_set_overheat_thresholds(struct armada_thermal_priv *priv,
 499                                           int thresh_mc, int hyst_mc)
 500{
 501        struct armada_thermal_data *data = priv->data;
 502        unsigned int threshold = armada_mc_to_reg_temp(data, thresh_mc);
 503        unsigned int hysteresis = armada_mc_to_reg_hyst(data, hyst_mc);
 504        u32 ctrl1;
 505
 506        regmap_read(priv->syscon, data->syscon_control1_off, &ctrl1);
 507
 508        /* Set Threshold */
 509        if (thresh_mc >= 0) {
 510                ctrl1 &= ~(data->temp_mask << data->thresh_shift);
 511                ctrl1 |= threshold << data->thresh_shift;
 512                priv->current_threshold = thresh_mc;
 513        }
 514
 515        /* Set Hysteresis */
 516        if (hyst_mc >= 0) {
 517                ctrl1 &= ~(data->hyst_mask << data->hyst_shift);
 518                ctrl1 |= hysteresis << data->hyst_shift;
 519                priv->current_hysteresis = hyst_mc;
 520        }
 521
 522        regmap_write(priv->syscon, data->syscon_control1_off, ctrl1);
 523}
 524
 525static irqreturn_t armada_overheat_isr(int irq, void *blob)
 526{
 527        /*
 528         * Disable the IRQ and continue in thread context (thermal core
 529         * notification and temperature monitoring).
 530         */
 531        disable_irq_nosync(irq);
 532
 533        return IRQ_WAKE_THREAD;
 534}
 535
 536static irqreturn_t armada_overheat_isr_thread(int irq, void *blob)
 537{
 538        struct armada_thermal_priv *priv = blob;
 539        int low_threshold = priv->current_threshold - priv->current_hysteresis;
 540        int temperature;
 541        u32 dummy;
 542        int ret;
 543
 544        /* Notify the core in thread context */
 545        thermal_zone_device_update(priv->overheat_sensor,
 546                                   THERMAL_EVENT_UNSPECIFIED);
 547
 548        /*
 549         * The overheat interrupt must be cleared by reading the DFX interrupt
 550         * cause _after_ the temperature has fallen down to the low threshold.
 551         * Otherwise future interrupts might not be served.
 552         */
 553        do {
 554                msleep(OVERHEAT_INT_POLL_DELAY_MS);
 555                mutex_lock(&priv->update_lock);
 556                ret = armada_read_sensor(priv, &temperature);
 557                mutex_unlock(&priv->update_lock);
 558                if (ret)
 559                        goto enable_irq;
 560        } while (temperature >= low_threshold);
 561
 562        regmap_read(priv->syscon, priv->data->dfx_irq_cause_off, &dummy);
 563
 564        /* Notify the thermal core that the temperature is acceptable again */
 565        thermal_zone_device_update(priv->overheat_sensor,
 566                                   THERMAL_EVENT_UNSPECIFIED);
 567
 568enable_irq:
 569        enable_irq(irq);
 570
 571        return IRQ_HANDLED;
 572}
 573
 574static const struct armada_thermal_data armadaxp_data = {
 575        .init = armadaxp_init,
 576        .temp_shift = 10,
 577        .temp_mask = 0x1ff,
 578        .coef_b = 3153000000ULL,
 579        .coef_m = 10000000ULL,
 580        .coef_div = 13825,
 581        .syscon_status_off = 0xb0,
 582        .syscon_control1_off = 0x2d0,
 583};
 584
 585static const struct armada_thermal_data armada370_data = {
 586        .init = armada370_init,
 587        .is_valid_bit = BIT(9),
 588        .temp_shift = 10,
 589        .temp_mask = 0x1ff,
 590        .coef_b = 3153000000ULL,
 591        .coef_m = 10000000ULL,
 592        .coef_div = 13825,
 593        .syscon_status_off = 0x0,
 594        .syscon_control1_off = 0x4,
 595};
 596
 597static const struct armada_thermal_data armada375_data = {
 598        .init = armada375_init,
 599        .is_valid_bit = BIT(10),
 600        .temp_shift = 0,
 601        .temp_mask = 0x1ff,
 602        .coef_b = 3171900000ULL,
 603        .coef_m = 10000000ULL,
 604        .coef_div = 13616,
 605        .syscon_status_off = 0x78,
 606        .syscon_control0_off = 0x7c,
 607        .syscon_control1_off = 0x80,
 608};
 609
 610static const struct armada_thermal_data armada380_data = {
 611        .init = armada380_init,
 612        .is_valid_bit = BIT(10),
 613        .temp_shift = 0,
 614        .temp_mask = 0x3ff,
 615        .coef_b = 1172499100ULL,
 616        .coef_m = 2000096ULL,
 617        .coef_div = 4201,
 618        .inverted = true,
 619        .syscon_control0_off = 0x70,
 620        .syscon_control1_off = 0x74,
 621        .syscon_status_off = 0x78,
 622};
 623
 624static const struct armada_thermal_data armada_ap806_data = {
 625        .init = armada_ap806_init,
 626        .is_valid_bit = BIT(16),
 627        .temp_shift = 0,
 628        .temp_mask = 0x3ff,
 629        .thresh_shift = 3,
 630        .hyst_shift = 19,
 631        .hyst_mask = 0x3,
 632        .coef_b = -150000LL,
 633        .coef_m = 423ULL,
 634        .coef_div = 1,
 635        .inverted = true,
 636        .signed_sample = true,
 637        .syscon_control0_off = 0x84,
 638        .syscon_control1_off = 0x88,
 639        .syscon_status_off = 0x8C,
 640        .dfx_irq_cause_off = 0x108,
 641        .dfx_irq_mask_off = 0x10C,
 642        .dfx_overheat_irq = BIT(22),
 643        .dfx_server_irq_mask_off = 0x104,
 644        .dfx_server_irq_en = BIT(1),
 645        .cpu_nr = 4,
 646};
 647
 648static const struct armada_thermal_data armada_cp110_data = {
 649        .init = armada_cp110_init,
 650        .is_valid_bit = BIT(10),
 651        .temp_shift = 0,
 652        .temp_mask = 0x3ff,
 653        .thresh_shift = 16,
 654        .hyst_shift = 26,
 655        .hyst_mask = 0x3,
 656        .coef_b = 1172499100ULL,
 657        .coef_m = 2000096ULL,
 658        .coef_div = 4201,
 659        .inverted = true,
 660        .syscon_control0_off = 0x70,
 661        .syscon_control1_off = 0x74,
 662        .syscon_status_off = 0x78,
 663        .dfx_irq_cause_off = 0x108,
 664        .dfx_irq_mask_off = 0x10C,
 665        .dfx_overheat_irq = BIT(20),
 666        .dfx_server_irq_mask_off = 0x104,
 667        .dfx_server_irq_en = BIT(1),
 668};
 669
 670static const struct of_device_id armada_thermal_id_table[] = {
 671        {
 672                .compatible = "marvell,armadaxp-thermal",
 673                .data       = &armadaxp_data,
 674        },
 675        {
 676                .compatible = "marvell,armada370-thermal",
 677                .data       = &armada370_data,
 678        },
 679        {
 680                .compatible = "marvell,armada375-thermal",
 681                .data       = &armada375_data,
 682        },
 683        {
 684                .compatible = "marvell,armada380-thermal",
 685                .data       = &armada380_data,
 686        },
 687        {
 688                .compatible = "marvell,armada-ap806-thermal",
 689                .data       = &armada_ap806_data,
 690        },
 691        {
 692                .compatible = "marvell,armada-cp110-thermal",
 693                .data       = &armada_cp110_data,
 694        },
 695        {
 696                /* sentinel */
 697        },
 698};
 699MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
 700
 701static const struct regmap_config armada_thermal_regmap_config = {
 702        .reg_bits = 32,
 703        .reg_stride = 4,
 704        .val_bits = 32,
 705        .fast_io = true,
 706};
 707
 708static int armada_thermal_probe_legacy(struct platform_device *pdev,
 709                                       struct armada_thermal_priv *priv)
 710{
 711        struct armada_thermal_data *data = priv->data;
 712        struct resource *res;
 713        void __iomem *base;
 714
 715        /* First memory region points towards the status register */
 716        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 717        base = devm_ioremap_resource(&pdev->dev, res);
 718        if (IS_ERR(base))
 719                return PTR_ERR(base);
 720
 721        /*
 722         * Fix up from the old individual DT register specification to
 723         * cover all the registers.  We do this by adjusting the ioremap()
 724         * result, which should be fine as ioremap() deals with pages.
 725         * However, validate that we do not cross a page boundary while
 726         * making this adjustment.
 727         */
 728        if (((unsigned long)base & ~PAGE_MASK) < data->syscon_status_off)
 729                return -EINVAL;
 730        base -= data->syscon_status_off;
 731
 732        priv->syscon = devm_regmap_init_mmio(&pdev->dev, base,
 733                                             &armada_thermal_regmap_config);
 734        return PTR_ERR_OR_ZERO(priv->syscon);
 735}
 736
 737static int armada_thermal_probe_syscon(struct platform_device *pdev,
 738                                       struct armada_thermal_priv *priv)
 739{
 740        priv->syscon = syscon_node_to_regmap(pdev->dev.parent->of_node);
 741        return PTR_ERR_OR_ZERO(priv->syscon);
 742}
 743
 744static void armada_set_sane_name(struct platform_device *pdev,
 745                                 struct armada_thermal_priv *priv)
 746{
 747        const char *name = dev_name(&pdev->dev);
 748        char *insane_char;
 749
 750        if (strlen(name) > THERMAL_NAME_LENGTH) {
 751                /*
 752                 * When inside a system controller, the device name has the
 753                 * form: f06f8000.system-controller:ap-thermal so stripping
 754                 * after the ':' should give us a shorter but meaningful name.
 755                 */
 756                name = strrchr(name, ':');
 757                if (!name)
 758                        name = "armada_thermal";
 759                else
 760                        name++;
 761        }
 762
 763        /* Save the name locally */
 764        strncpy(priv->zone_name, name, THERMAL_NAME_LENGTH - 1);
 765        priv->zone_name[THERMAL_NAME_LENGTH - 1] = '\0';
 766
 767        /* Then check there are no '-' or hwmon core will complain */
 768        do {
 769                insane_char = strpbrk(priv->zone_name, "-");
 770                if (insane_char)
 771                        *insane_char = '_';
 772        } while (insane_char);
 773}
 774
 775/*
 776 * The IP can manage to trigger interrupts on overheat situation from all the
 777 * sensors. However, the interrupt source changes along with the last selected
 778 * source (ie. the last read sensor), which is an inconsistent behavior. Avoid
 779 * possible glitches by always selecting back only one channel (arbitrarily: the
 780 * first in the DT which has a critical trip point). We also disable sensor
 781 * switch during overheat situations.
 782 */
 783static int armada_configure_overheat_int(struct armada_thermal_priv *priv,
 784                                         struct thermal_zone_device *tz,
 785                                         int sensor_id)
 786{
 787        /* Retrieve the critical trip point to enable the overheat interrupt */
 788        const struct thermal_trip *trips = of_thermal_get_trip_points(tz);
 789        int ret;
 790        int i;
 791
 792        if (!trips)
 793                return -EINVAL;
 794
 795        for (i = 0; i < of_thermal_get_ntrips(tz); i++)
 796                if (trips[i].type == THERMAL_TRIP_CRITICAL)
 797                        break;
 798
 799        if (i == of_thermal_get_ntrips(tz))
 800                return -EINVAL;
 801
 802        ret = armada_select_channel(priv, sensor_id);
 803        if (ret)
 804                return ret;
 805
 806        armada_set_overheat_thresholds(priv,
 807                                       trips[i].temperature,
 808                                       trips[i].hysteresis);
 809        priv->overheat_sensor = tz;
 810        priv->interrupt_source = sensor_id;
 811
 812        armada_enable_overheat_interrupt(priv);
 813
 814        return 0;
 815}
 816
 817static int armada_thermal_probe(struct platform_device *pdev)
 818{
 819        struct thermal_zone_device *tz;
 820        struct armada_thermal_sensor *sensor;
 821        struct armada_drvdata *drvdata;
 822        const struct of_device_id *match;
 823        struct armada_thermal_priv *priv;
 824        int sensor_id, irq;
 825        int ret;
 826
 827        match = of_match_device(armada_thermal_id_table, &pdev->dev);
 828        if (!match)
 829                return -ENODEV;
 830
 831        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 832        if (!priv)
 833                return -ENOMEM;
 834
 835        drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
 836        if (!drvdata)
 837                return -ENOMEM;
 838
 839        priv->dev = &pdev->dev;
 840        priv->data = (struct armada_thermal_data *)match->data;
 841
 842        mutex_init(&priv->update_lock);
 843
 844        /*
 845         * Legacy DT bindings only described "control1" register (also referred
 846         * as "control MSB" on old documentation). Then, bindings moved to cover
 847         * "control0/control LSB" and "control1/control MSB" registers within
 848         * the same resource, which was then of size 8 instead of 4.
 849         *
 850         * The logic of defining sporadic registers is broken. For instance, it
 851         * blocked the addition of the overheat interrupt feature that needed
 852         * another resource somewhere else in the same memory area. One solution
 853         * is to define an overall system controller and put the thermal node
 854         * into it, which requires the use of regmaps across all the driver.
 855         */
 856        if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) {
 857                /* Ensure device name is correct for the thermal core */
 858                armada_set_sane_name(pdev, priv);
 859
 860                ret = armada_thermal_probe_legacy(pdev, priv);
 861                if (ret)
 862                        return ret;
 863
 864                priv->data->init(pdev, priv);
 865
 866                /* Wait the sensors to be valid */
 867                armada_wait_sensor_validity(priv);
 868
 869                tz = thermal_zone_device_register(priv->zone_name, 0, 0, priv,
 870                                                  &legacy_ops, NULL, 0, 0);
 871                if (IS_ERR(tz)) {
 872                        dev_err(&pdev->dev,
 873                                "Failed to register thermal zone device\n");
 874                        return PTR_ERR(tz);
 875                }
 876
 877                ret = thermal_zone_device_enable(tz);
 878                if (ret) {
 879                        thermal_zone_device_unregister(tz);
 880                        return ret;
 881                }
 882
 883                drvdata->type = LEGACY;
 884                drvdata->data.tz = tz;
 885                platform_set_drvdata(pdev, drvdata);
 886
 887                return 0;
 888        }
 889
 890        ret = armada_thermal_probe_syscon(pdev, priv);
 891        if (ret)
 892                return ret;
 893
 894        priv->current_channel = -1;
 895        priv->data->init(pdev, priv);
 896        drvdata->type = SYSCON;
 897        drvdata->data.priv = priv;
 898        platform_set_drvdata(pdev, drvdata);
 899
 900        irq = platform_get_irq(pdev, 0);
 901        if (irq == -EPROBE_DEFER)
 902                return irq;
 903
 904        /* The overheat interrupt feature is not mandatory */
 905        if (irq > 0) {
 906                ret = devm_request_threaded_irq(&pdev->dev, irq,
 907                                                armada_overheat_isr,
 908                                                armada_overheat_isr_thread,
 909                                                0, NULL, priv);
 910                if (ret) {
 911                        dev_err(&pdev->dev, "Cannot request threaded IRQ %d\n",
 912                                irq);
 913                        return ret;
 914                }
 915        }
 916
 917        /*
 918         * There is one channel for the IC and one per CPU (if any), each
 919         * channel has one sensor.
 920         */
 921        for (sensor_id = 0; sensor_id <= priv->data->cpu_nr; sensor_id++) {
 922                sensor = devm_kzalloc(&pdev->dev,
 923                                      sizeof(struct armada_thermal_sensor),
 924                                      GFP_KERNEL);
 925                if (!sensor)
 926                        return -ENOMEM;
 927
 928                /* Register the sensor */
 929                sensor->priv = priv;
 930                sensor->id = sensor_id;
 931                tz = devm_thermal_zone_of_sensor_register(&pdev->dev,
 932                                                          sensor->id, sensor,
 933                                                          &of_ops);
 934                if (IS_ERR(tz)) {
 935                        dev_info(&pdev->dev, "Thermal sensor %d unavailable\n",
 936                                 sensor_id);
 937                        devm_kfree(&pdev->dev, sensor);
 938                        continue;
 939                }
 940
 941                /*
 942                 * The first channel that has a critical trip point registered
 943                 * in the DT will serve as interrupt source. Others possible
 944                 * critical trip points will simply be ignored by the driver.
 945                 */
 946                if (irq > 0 && !priv->overheat_sensor)
 947                        armada_configure_overheat_int(priv, tz, sensor->id);
 948        }
 949
 950        /* Just complain if no overheat interrupt was set up */
 951        if (!priv->overheat_sensor)
 952                dev_warn(&pdev->dev, "Overheat interrupt not available\n");
 953
 954        return 0;
 955}
 956
 957static int armada_thermal_exit(struct platform_device *pdev)
 958{
 959        struct armada_drvdata *drvdata = platform_get_drvdata(pdev);
 960
 961        if (drvdata->type == LEGACY)
 962                thermal_zone_device_unregister(drvdata->data.tz);
 963
 964        return 0;
 965}
 966
 967static struct platform_driver armada_thermal_driver = {
 968        .probe = armada_thermal_probe,
 969        .remove = armada_thermal_exit,
 970        .driver = {
 971                .name = "armada_thermal",
 972                .of_match_table = armada_thermal_id_table,
 973        },
 974};
 975
 976module_platform_driver(armada_thermal_driver);
 977
 978MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
 979MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver");
 980MODULE_LICENSE("GPL v2");
 981