Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Marvell EBU Armada SoCs thermal sensor driver
0004  *
0005  * Copyright (C) 2013 Marvell
0006  */
0007 #include <linux/device.h>
0008 #include <linux/err.h>
0009 #include <linux/io.h>
0010 #include <linux/kernel.h>
0011 #include <linux/of.h>
0012 #include <linux/module.h>
0013 #include <linux/delay.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/of_device.h>
0016 #include <linux/thermal.h>
0017 #include <linux/iopoll.h>
0018 #include <linux/mfd/syscon.h>
0019 #include <linux/regmap.h>
0020 #include <linux/interrupt.h>
0021 
0022 #include "thermal_core.h"
0023 
0024 /* Thermal Manager Control and Status Register */
0025 #define PMU_TDC0_SW_RST_MASK        (0x1 << 1)
0026 #define PMU_TM_DISABLE_OFFS     0
0027 #define PMU_TM_DISABLE_MASK     (0x1 << PMU_TM_DISABLE_OFFS)
0028 #define PMU_TDC0_REF_CAL_CNT_OFFS   11
0029 #define PMU_TDC0_REF_CAL_CNT_MASK   (0x1ff << PMU_TDC0_REF_CAL_CNT_OFFS)
0030 #define PMU_TDC0_OTF_CAL_MASK       (0x1 << 30)
0031 #define PMU_TDC0_START_CAL_MASK     (0x1 << 25)
0032 
0033 #define A375_UNIT_CONTROL_SHIFT     27
0034 #define A375_UNIT_CONTROL_MASK      0x7
0035 #define A375_READOUT_INVERT     BIT(15)
0036 #define A375_HW_RESETn          BIT(8)
0037 
0038 /* Errata fields */
0039 #define CONTROL0_TSEN_TC_TRIM_MASK  0x7
0040 #define CONTROL0_TSEN_TC_TRIM_VAL   0x3
0041 
0042 #define CONTROL0_TSEN_START     BIT(0)
0043 #define CONTROL0_TSEN_RESET     BIT(1)
0044 #define CONTROL0_TSEN_ENABLE        BIT(2)
0045 #define CONTROL0_TSEN_AVG_BYPASS    BIT(6)
0046 #define CONTROL0_TSEN_CHAN_SHIFT    13
0047 #define CONTROL0_TSEN_CHAN_MASK     0xF
0048 #define CONTROL0_TSEN_OSR_SHIFT     24
0049 #define CONTROL0_TSEN_OSR_MAX       0x3
0050 #define CONTROL0_TSEN_MODE_SHIFT    30
0051 #define CONTROL0_TSEN_MODE_EXTERNAL 0x2
0052 #define CONTROL0_TSEN_MODE_MASK     0x3
0053 
0054 #define CONTROL1_TSEN_AVG_MASK      0x7
0055 #define CONTROL1_EXT_TSEN_SW_RESET  BIT(7)
0056 #define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
0057 #define CONTROL1_TSEN_INT_EN        BIT(25)
0058 #define CONTROL1_TSEN_SELECT_OFF    21
0059 #define CONTROL1_TSEN_SELECT_MASK   0x3
0060 
0061 #define STATUS_POLL_PERIOD_US       1000
0062 #define STATUS_POLL_TIMEOUT_US      100000
0063 #define OVERHEAT_INT_POLL_DELAY_MS  1000
0064 
0065 struct armada_thermal_data;
0066 
0067 /* Marvell EBU Thermal Sensor Dev Structure */
0068 struct armada_thermal_priv {
0069     struct device *dev;
0070     struct regmap *syscon;
0071     char zone_name[THERMAL_NAME_LENGTH];
0072     /* serialize temperature reads/updates */
0073     struct mutex update_lock;
0074     struct armada_thermal_data *data;
0075     struct thermal_zone_device *overheat_sensor;
0076     int interrupt_source;
0077     int current_channel;
0078     long current_threshold;
0079     long current_hysteresis;
0080 };
0081 
0082 struct armada_thermal_data {
0083     /* Initialize the thermal IC */
0084     void (*init)(struct platform_device *pdev,
0085              struct armada_thermal_priv *priv);
0086 
0087     /* Formula coeficients: temp = (b - m * reg) / div */
0088     s64 coef_b;
0089     s64 coef_m;
0090     u32 coef_div;
0091     bool inverted;
0092     bool signed_sample;
0093 
0094     /* Register shift and mask to access the sensor temperature */
0095     unsigned int temp_shift;
0096     unsigned int temp_mask;
0097     unsigned int thresh_shift;
0098     unsigned int hyst_shift;
0099     unsigned int hyst_mask;
0100     u32 is_valid_bit;
0101 
0102     /* Syscon access */
0103     unsigned int syscon_control0_off;
0104     unsigned int syscon_control1_off;
0105     unsigned int syscon_status_off;
0106     unsigned int dfx_irq_cause_off;
0107     unsigned int dfx_irq_mask_off;
0108     unsigned int dfx_overheat_irq;
0109     unsigned int dfx_server_irq_mask_off;
0110     unsigned int dfx_server_irq_en;
0111 
0112     /* One sensor is in the thermal IC, the others are in the CPUs if any */
0113     unsigned int cpu_nr;
0114 };
0115 
0116 struct armada_drvdata {
0117     enum drvtype {
0118         LEGACY,
0119         SYSCON
0120     } type;
0121     union {
0122         struct armada_thermal_priv *priv;
0123         struct thermal_zone_device *tz;
0124     } data;
0125 };
0126 
0127 /*
0128  * struct armada_thermal_sensor - hold the information of one thermal sensor
0129  * @thermal: pointer to the local private structure
0130  * @tzd: pointer to the thermal zone device
0131  * @id: identifier of the thermal sensor
0132  */
0133 struct armada_thermal_sensor {
0134     struct armada_thermal_priv *priv;
0135     int id;
0136 };
0137 
0138 static void armadaxp_init(struct platform_device *pdev,
0139               struct armada_thermal_priv *priv)
0140 {
0141     struct armada_thermal_data *data = priv->data;
0142     u32 reg;
0143 
0144     regmap_read(priv->syscon, data->syscon_control1_off, &reg);
0145     reg |= PMU_TDC0_OTF_CAL_MASK;
0146 
0147     /* Reference calibration value */
0148     reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
0149     reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
0150 
0151     /* Reset the sensor */
0152     reg |= PMU_TDC0_SW_RST_MASK;
0153 
0154     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0155 
0156     reg &= ~PMU_TDC0_SW_RST_MASK;
0157     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0158 
0159     /* Enable the sensor */
0160     regmap_read(priv->syscon, data->syscon_status_off, &reg);
0161     reg &= ~PMU_TM_DISABLE_MASK;
0162     regmap_write(priv->syscon, data->syscon_status_off, reg);
0163 }
0164 
0165 static void armada370_init(struct platform_device *pdev,
0166                struct armada_thermal_priv *priv)
0167 {
0168     struct armada_thermal_data *data = priv->data;
0169     u32 reg;
0170 
0171     regmap_read(priv->syscon, data->syscon_control1_off, &reg);
0172     reg |= PMU_TDC0_OTF_CAL_MASK;
0173 
0174     /* Reference calibration value */
0175     reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
0176     reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
0177 
0178     /* Reset the sensor */
0179     reg &= ~PMU_TDC0_START_CAL_MASK;
0180 
0181     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0182 
0183     msleep(10);
0184 }
0185 
0186 static void armada375_init(struct platform_device *pdev,
0187                struct armada_thermal_priv *priv)
0188 {
0189     struct armada_thermal_data *data = priv->data;
0190     u32 reg;
0191 
0192     regmap_read(priv->syscon, data->syscon_control1_off, &reg);
0193     reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
0194     reg &= ~A375_READOUT_INVERT;
0195     reg &= ~A375_HW_RESETn;
0196     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0197 
0198     msleep(20);
0199 
0200     reg |= A375_HW_RESETn;
0201     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0202 
0203     msleep(50);
0204 }
0205 
0206 static int armada_wait_sensor_validity(struct armada_thermal_priv *priv)
0207 {
0208     u32 reg;
0209 
0210     return regmap_read_poll_timeout(priv->syscon,
0211                     priv->data->syscon_status_off, reg,
0212                     reg & priv->data->is_valid_bit,
0213                     STATUS_POLL_PERIOD_US,
0214                     STATUS_POLL_TIMEOUT_US);
0215 }
0216 
0217 static void armada380_init(struct platform_device *pdev,
0218                struct armada_thermal_priv *priv)
0219 {
0220     struct armada_thermal_data *data = priv->data;
0221     u32 reg;
0222 
0223     /* Disable the HW/SW reset */
0224     regmap_read(priv->syscon, data->syscon_control1_off, &reg);
0225     reg |= CONTROL1_EXT_TSEN_HW_RESETn;
0226     reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
0227     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0228 
0229     /* Set Tsen Tc Trim to correct default value (errata #132698) */
0230     regmap_read(priv->syscon, data->syscon_control0_off, &reg);
0231     reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
0232     reg |= CONTROL0_TSEN_TC_TRIM_VAL;
0233     regmap_write(priv->syscon, data->syscon_control0_off, reg);
0234 }
0235 
0236 static void armada_ap806_init(struct platform_device *pdev,
0237                   struct armada_thermal_priv *priv)
0238 {
0239     struct armada_thermal_data *data = priv->data;
0240     u32 reg;
0241 
0242     regmap_read(priv->syscon, data->syscon_control0_off, &reg);
0243     reg &= ~CONTROL0_TSEN_RESET;
0244     reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE;
0245 
0246     /* Sample every ~2ms */
0247     reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
0248 
0249     /* Enable average (2 samples by default) */
0250     reg &= ~CONTROL0_TSEN_AVG_BYPASS;
0251 
0252     regmap_write(priv->syscon, data->syscon_control0_off, reg);
0253 }
0254 
0255 static void armada_cp110_init(struct platform_device *pdev,
0256                   struct armada_thermal_priv *priv)
0257 {
0258     struct armada_thermal_data *data = priv->data;
0259     u32 reg;
0260 
0261     armada380_init(pdev, priv);
0262 
0263     /* Sample every ~2ms */
0264     regmap_read(priv->syscon, data->syscon_control0_off, &reg);
0265     reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
0266     regmap_write(priv->syscon, data->syscon_control0_off, reg);
0267 
0268     /* Average the output value over 2^1 = 2 samples */
0269     regmap_read(priv->syscon, data->syscon_control1_off, &reg);
0270     reg &= ~CONTROL1_TSEN_AVG_MASK;
0271     reg |= 1;
0272     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0273 }
0274 
0275 static bool armada_is_valid(struct armada_thermal_priv *priv)
0276 {
0277     u32 reg;
0278 
0279     if (!priv->data->is_valid_bit)
0280         return true;
0281 
0282     regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
0283 
0284     return reg & priv->data->is_valid_bit;
0285 }
0286 
0287 static void armada_enable_overheat_interrupt(struct armada_thermal_priv *priv)
0288 {
0289     struct armada_thermal_data *data = priv->data;
0290     u32 reg;
0291 
0292     /* Clear DFX temperature IRQ cause */
0293     regmap_read(priv->syscon, data->dfx_irq_cause_off, &reg);
0294 
0295     /* Enable DFX Temperature IRQ */
0296     regmap_read(priv->syscon, data->dfx_irq_mask_off, &reg);
0297     reg |= data->dfx_overheat_irq;
0298     regmap_write(priv->syscon, data->dfx_irq_mask_off, reg);
0299 
0300     /* Enable DFX server IRQ */
0301     regmap_read(priv->syscon, data->dfx_server_irq_mask_off, &reg);
0302     reg |= data->dfx_server_irq_en;
0303     regmap_write(priv->syscon, data->dfx_server_irq_mask_off, reg);
0304 
0305     /* Enable overheat interrupt */
0306     regmap_read(priv->syscon, data->syscon_control1_off, &reg);
0307     reg |= CONTROL1_TSEN_INT_EN;
0308     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0309 }
0310 
0311 static void __maybe_unused
0312 armada_disable_overheat_interrupt(struct armada_thermal_priv *priv)
0313 {
0314     struct armada_thermal_data *data = priv->data;
0315     u32 reg;
0316 
0317     regmap_read(priv->syscon, data->syscon_control1_off, &reg);
0318     reg &= ~CONTROL1_TSEN_INT_EN;
0319     regmap_write(priv->syscon, data->syscon_control1_off, reg);
0320 }
0321 
0322 /* There is currently no board with more than one sensor per channel */
0323 static int armada_select_channel(struct armada_thermal_priv *priv, int channel)
0324 {
0325     struct armada_thermal_data *data = priv->data;
0326     u32 ctrl0;
0327 
0328     if (channel < 0 || channel > priv->data->cpu_nr)
0329         return -EINVAL;
0330 
0331     if (priv->current_channel == channel)
0332         return 0;
0333 
0334     /* Stop the measurements */
0335     regmap_read(priv->syscon, data->syscon_control0_off, &ctrl0);
0336     ctrl0 &= ~CONTROL0_TSEN_START;
0337     regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
0338 
0339     /* Reset the mode, internal sensor will be automatically selected */
0340     ctrl0 &= ~(CONTROL0_TSEN_MODE_MASK << CONTROL0_TSEN_MODE_SHIFT);
0341 
0342     /* Other channels are external and should be selected accordingly */
0343     if (channel) {
0344         /* Change the mode to external */
0345         ctrl0 |= CONTROL0_TSEN_MODE_EXTERNAL <<
0346              CONTROL0_TSEN_MODE_SHIFT;
0347         /* Select the sensor */
0348         ctrl0 &= ~(CONTROL0_TSEN_CHAN_MASK << CONTROL0_TSEN_CHAN_SHIFT);
0349         ctrl0 |= (channel - 1) << CONTROL0_TSEN_CHAN_SHIFT;
0350     }
0351 
0352     /* Actually set the mode/channel */
0353     regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
0354     priv->current_channel = channel;
0355 
0356     /* Re-start the measurements */
0357     ctrl0 |= CONTROL0_TSEN_START;
0358     regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
0359 
0360     /*
0361      * The IP has a latency of ~15ms, so after updating the selected source,
0362      * we must absolutely wait for the sensor validity bit to ensure we read
0363      * actual data.
0364      */
0365     if (armada_wait_sensor_validity(priv)) {
0366         dev_err(priv->dev,
0367             "Temperature sensor reading not valid\n");
0368         return -EIO;
0369     }
0370 
0371     return 0;
0372 }
0373 
0374 static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp)
0375 {
0376     u32 reg, div;
0377     s64 sample, b, m;
0378 
0379     regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
0380     reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask;
0381     if (priv->data->signed_sample)
0382         /* The most significant bit is the sign bit */
0383         sample = sign_extend32(reg, fls(priv->data->temp_mask) - 1);
0384     else
0385         sample = reg;
0386 
0387     /* Get formula coeficients */
0388     b = priv->data->coef_b;
0389     m = priv->data->coef_m;
0390     div = priv->data->coef_div;
0391 
0392     if (priv->data->inverted)
0393         *temp = div_s64((m * sample) - b, div);
0394     else
0395         *temp = div_s64(b - (m * sample), div);
0396 
0397     return 0;
0398 }
0399 
0400 static int armada_get_temp_legacy(struct thermal_zone_device *thermal,
0401                   int *temp)
0402 {
0403     struct armada_thermal_priv *priv = thermal->devdata;
0404     int ret;
0405 
0406     /* Valid check */
0407     if (!armada_is_valid(priv)) {
0408         dev_err(priv->dev,
0409             "Temperature sensor reading not valid\n");
0410         return -EIO;
0411     }
0412 
0413     /* Do the actual reading */
0414     ret = armada_read_sensor(priv, temp);
0415 
0416     return ret;
0417 }
0418 
0419 static struct thermal_zone_device_ops legacy_ops = {
0420     .get_temp = armada_get_temp_legacy,
0421 };
0422 
0423 static int armada_get_temp(void *_sensor, int *temp)
0424 {
0425     struct armada_thermal_sensor *sensor = _sensor;
0426     struct armada_thermal_priv *priv = sensor->priv;
0427     int ret;
0428 
0429     mutex_lock(&priv->update_lock);
0430 
0431     /* Select the desired channel */
0432     ret = armada_select_channel(priv, sensor->id);
0433     if (ret)
0434         goto unlock_mutex;
0435 
0436     /* Do the actual reading */
0437     ret = armada_read_sensor(priv, temp);
0438     if (ret)
0439         goto unlock_mutex;
0440 
0441     /*
0442      * Select back the interrupt source channel from which a potential
0443      * critical trip point has been set.
0444      */
0445     ret = armada_select_channel(priv, priv->interrupt_source);
0446 
0447 unlock_mutex:
0448     mutex_unlock(&priv->update_lock);
0449 
0450     return ret;
0451 }
0452 
0453 static const struct thermal_zone_of_device_ops of_ops = {
0454     .get_temp = armada_get_temp,
0455 };
0456 
0457 static unsigned int armada_mc_to_reg_temp(struct armada_thermal_data *data,
0458                       unsigned int temp_mc)
0459 {
0460     s64 b = data->coef_b;
0461     s64 m = data->coef_m;
0462     s64 div = data->coef_div;
0463     unsigned int sample;
0464 
0465     if (data->inverted)
0466         sample = div_s64(((temp_mc * div) + b), m);
0467     else
0468         sample = div_s64((b - (temp_mc * div)), m);
0469 
0470     return sample & data->temp_mask;
0471 }
0472 
0473 /*
0474  * The documentation states:
0475  * high/low watermark = threshold +/- 0.4761 * 2^(hysteresis + 2)
0476  * which is the mathematical derivation for:
0477  * 0x0 <=> 1.9°C, 0x1 <=> 3.8°C, 0x2 <=> 7.6°C, 0x3 <=> 15.2°C
0478  */
0479 static unsigned int hyst_levels_mc[] = {1900, 3800, 7600, 15200};
0480 
0481 static unsigned int armada_mc_to_reg_hyst(struct armada_thermal_data *data,
0482                       unsigned int hyst_mc)
0483 {
0484     int i;
0485 
0486     /*
0487      * We will always take the smallest possible hysteresis to avoid risking
0488      * the hardware integrity by enlarging the threshold by +8°C in the
0489      * worst case.
0490      */
0491     for (i = ARRAY_SIZE(hyst_levels_mc) - 1; i > 0; i--)
0492         if (hyst_mc >= hyst_levels_mc[i])
0493             break;
0494 
0495     return i & data->hyst_mask;
0496 }
0497 
0498 static void armada_set_overheat_thresholds(struct armada_thermal_priv *priv,
0499                        int thresh_mc, int hyst_mc)
0500 {
0501     struct armada_thermal_data *data = priv->data;
0502     unsigned int threshold = armada_mc_to_reg_temp(data, thresh_mc);
0503     unsigned int hysteresis = armada_mc_to_reg_hyst(data, hyst_mc);
0504     u32 ctrl1;
0505 
0506     regmap_read(priv->syscon, data->syscon_control1_off, &ctrl1);
0507 
0508     /* Set Threshold */
0509     if (thresh_mc >= 0) {
0510         ctrl1 &= ~(data->temp_mask << data->thresh_shift);
0511         ctrl1 |= threshold << data->thresh_shift;
0512         priv->current_threshold = thresh_mc;
0513     }
0514 
0515     /* Set Hysteresis */
0516     if (hyst_mc >= 0) {
0517         ctrl1 &= ~(data->hyst_mask << data->hyst_shift);
0518         ctrl1 |= hysteresis << data->hyst_shift;
0519         priv->current_hysteresis = hyst_mc;
0520     }
0521 
0522     regmap_write(priv->syscon, data->syscon_control1_off, ctrl1);
0523 }
0524 
0525 static irqreturn_t armada_overheat_isr(int irq, void *blob)
0526 {
0527     /*
0528      * Disable the IRQ and continue in thread context (thermal core
0529      * notification and temperature monitoring).
0530      */
0531     disable_irq_nosync(irq);
0532 
0533     return IRQ_WAKE_THREAD;
0534 }
0535 
0536 static irqreturn_t armada_overheat_isr_thread(int irq, void *blob)
0537 {
0538     struct armada_thermal_priv *priv = blob;
0539     int low_threshold = priv->current_threshold - priv->current_hysteresis;
0540     int temperature;
0541     u32 dummy;
0542     int ret;
0543 
0544     /* Notify the core in thread context */
0545     thermal_zone_device_update(priv->overheat_sensor,
0546                    THERMAL_EVENT_UNSPECIFIED);
0547 
0548     /*
0549      * The overheat interrupt must be cleared by reading the DFX interrupt
0550      * cause _after_ the temperature has fallen down to the low threshold.
0551      * Otherwise future interrupts might not be served.
0552      */
0553     do {
0554         msleep(OVERHEAT_INT_POLL_DELAY_MS);
0555         mutex_lock(&priv->update_lock);
0556         ret = armada_read_sensor(priv, &temperature);
0557         mutex_unlock(&priv->update_lock);
0558         if (ret)
0559             goto enable_irq;
0560     } while (temperature >= low_threshold);
0561 
0562     regmap_read(priv->syscon, priv->data->dfx_irq_cause_off, &dummy);
0563 
0564     /* Notify the thermal core that the temperature is acceptable again */
0565     thermal_zone_device_update(priv->overheat_sensor,
0566                    THERMAL_EVENT_UNSPECIFIED);
0567 
0568 enable_irq:
0569     enable_irq(irq);
0570 
0571     return IRQ_HANDLED;
0572 }
0573 
0574 static const struct armada_thermal_data armadaxp_data = {
0575     .init = armadaxp_init,
0576     .temp_shift = 10,
0577     .temp_mask = 0x1ff,
0578     .coef_b = 3153000000ULL,
0579     .coef_m = 10000000ULL,
0580     .coef_div = 13825,
0581     .syscon_status_off = 0xb0,
0582     .syscon_control1_off = 0x2d0,
0583 };
0584 
0585 static const struct armada_thermal_data armada370_data = {
0586     .init = armada370_init,
0587     .is_valid_bit = BIT(9),
0588     .temp_shift = 10,
0589     .temp_mask = 0x1ff,
0590     .coef_b = 3153000000ULL,
0591     .coef_m = 10000000ULL,
0592     .coef_div = 13825,
0593     .syscon_status_off = 0x0,
0594     .syscon_control1_off = 0x4,
0595 };
0596 
0597 static const struct armada_thermal_data armada375_data = {
0598     .init = armada375_init,
0599     .is_valid_bit = BIT(10),
0600     .temp_shift = 0,
0601     .temp_mask = 0x1ff,
0602     .coef_b = 3171900000ULL,
0603     .coef_m = 10000000ULL,
0604     .coef_div = 13616,
0605     .syscon_status_off = 0x78,
0606     .syscon_control0_off = 0x7c,
0607     .syscon_control1_off = 0x80,
0608 };
0609 
0610 static const struct armada_thermal_data armada380_data = {
0611     .init = armada380_init,
0612     .is_valid_bit = BIT(10),
0613     .temp_shift = 0,
0614     .temp_mask = 0x3ff,
0615     .coef_b = 1172499100ULL,
0616     .coef_m = 2000096ULL,
0617     .coef_div = 4201,
0618     .inverted = true,
0619     .syscon_control0_off = 0x70,
0620     .syscon_control1_off = 0x74,
0621     .syscon_status_off = 0x78,
0622 };
0623 
0624 static const struct armada_thermal_data armada_ap806_data = {
0625     .init = armada_ap806_init,
0626     .is_valid_bit = BIT(16),
0627     .temp_shift = 0,
0628     .temp_mask = 0x3ff,
0629     .thresh_shift = 3,
0630     .hyst_shift = 19,
0631     .hyst_mask = 0x3,
0632     .coef_b = -150000LL,
0633     .coef_m = 423ULL,
0634     .coef_div = 1,
0635     .inverted = true,
0636     .signed_sample = true,
0637     .syscon_control0_off = 0x84,
0638     .syscon_control1_off = 0x88,
0639     .syscon_status_off = 0x8C,
0640     .dfx_irq_cause_off = 0x108,
0641     .dfx_irq_mask_off = 0x10C,
0642     .dfx_overheat_irq = BIT(22),
0643     .dfx_server_irq_mask_off = 0x104,
0644     .dfx_server_irq_en = BIT(1),
0645     .cpu_nr = 4,
0646 };
0647 
0648 static const struct armada_thermal_data armada_cp110_data = {
0649     .init = armada_cp110_init,
0650     .is_valid_bit = BIT(10),
0651     .temp_shift = 0,
0652     .temp_mask = 0x3ff,
0653     .thresh_shift = 16,
0654     .hyst_shift = 26,
0655     .hyst_mask = 0x3,
0656     .coef_b = 1172499100ULL,
0657     .coef_m = 2000096ULL,
0658     .coef_div = 4201,
0659     .inverted = true,
0660     .syscon_control0_off = 0x70,
0661     .syscon_control1_off = 0x74,
0662     .syscon_status_off = 0x78,
0663     .dfx_irq_cause_off = 0x108,
0664     .dfx_irq_mask_off = 0x10C,
0665     .dfx_overheat_irq = BIT(20),
0666     .dfx_server_irq_mask_off = 0x104,
0667     .dfx_server_irq_en = BIT(1),
0668 };
0669 
0670 static const struct of_device_id armada_thermal_id_table[] = {
0671     {
0672         .compatible = "marvell,armadaxp-thermal",
0673         .data       = &armadaxp_data,
0674     },
0675     {
0676         .compatible = "marvell,armada370-thermal",
0677         .data       = &armada370_data,
0678     },
0679     {
0680         .compatible = "marvell,armada375-thermal",
0681         .data       = &armada375_data,
0682     },
0683     {
0684         .compatible = "marvell,armada380-thermal",
0685         .data       = &armada380_data,
0686     },
0687     {
0688         .compatible = "marvell,armada-ap806-thermal",
0689         .data       = &armada_ap806_data,
0690     },
0691     {
0692         .compatible = "marvell,armada-cp110-thermal",
0693         .data       = &armada_cp110_data,
0694     },
0695     {
0696         /* sentinel */
0697     },
0698 };
0699 MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
0700 
0701 static const struct regmap_config armada_thermal_regmap_config = {
0702     .reg_bits = 32,
0703     .reg_stride = 4,
0704     .val_bits = 32,
0705     .fast_io = true,
0706 };
0707 
0708 static int armada_thermal_probe_legacy(struct platform_device *pdev,
0709                        struct armada_thermal_priv *priv)
0710 {
0711     struct armada_thermal_data *data = priv->data;
0712     struct resource *res;
0713     void __iomem *base;
0714 
0715     /* First memory region points towards the status register */
0716     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0717     base = devm_ioremap_resource(&pdev->dev, res);
0718     if (IS_ERR(base))
0719         return PTR_ERR(base);
0720 
0721     /*
0722      * Fix up from the old individual DT register specification to
0723      * cover all the registers.  We do this by adjusting the ioremap()
0724      * result, which should be fine as ioremap() deals with pages.
0725      * However, validate that we do not cross a page boundary while
0726      * making this adjustment.
0727      */
0728     if (((unsigned long)base & ~PAGE_MASK) < data->syscon_status_off)
0729         return -EINVAL;
0730     base -= data->syscon_status_off;
0731 
0732     priv->syscon = devm_regmap_init_mmio(&pdev->dev, base,
0733                          &armada_thermal_regmap_config);
0734     return PTR_ERR_OR_ZERO(priv->syscon);
0735 }
0736 
0737 static int armada_thermal_probe_syscon(struct platform_device *pdev,
0738                        struct armada_thermal_priv *priv)
0739 {
0740     priv->syscon = syscon_node_to_regmap(pdev->dev.parent->of_node);
0741     return PTR_ERR_OR_ZERO(priv->syscon);
0742 }
0743 
0744 static void armada_set_sane_name(struct platform_device *pdev,
0745                  struct armada_thermal_priv *priv)
0746 {
0747     const char *name = dev_name(&pdev->dev);
0748     char *insane_char;
0749 
0750     if (strlen(name) > THERMAL_NAME_LENGTH) {
0751         /*
0752          * When inside a system controller, the device name has the
0753          * form: f06f8000.system-controller:ap-thermal so stripping
0754          * after the ':' should give us a shorter but meaningful name.
0755          */
0756         name = strrchr(name, ':');
0757         if (!name)
0758             name = "armada_thermal";
0759         else
0760             name++;
0761     }
0762 
0763     /* Save the name locally */
0764     strncpy(priv->zone_name, name, THERMAL_NAME_LENGTH - 1);
0765     priv->zone_name[THERMAL_NAME_LENGTH - 1] = '\0';
0766 
0767     /* Then check there are no '-' or hwmon core will complain */
0768     do {
0769         insane_char = strpbrk(priv->zone_name, "-");
0770         if (insane_char)
0771             *insane_char = '_';
0772     } while (insane_char);
0773 }
0774 
0775 /*
0776  * The IP can manage to trigger interrupts on overheat situation from all the
0777  * sensors. However, the interrupt source changes along with the last selected
0778  * source (ie. the last read sensor), which is an inconsistent behavior. Avoid
0779  * possible glitches by always selecting back only one channel (arbitrarily: the
0780  * first in the DT which has a critical trip point). We also disable sensor
0781  * switch during overheat situations.
0782  */
0783 static int armada_configure_overheat_int(struct armada_thermal_priv *priv,
0784                      struct thermal_zone_device *tz,
0785                      int sensor_id)
0786 {
0787     /* Retrieve the critical trip point to enable the overheat interrupt */
0788     const struct thermal_trip *trips = of_thermal_get_trip_points(tz);
0789     int ret;
0790     int i;
0791 
0792     if (!trips)
0793         return -EINVAL;
0794 
0795     for (i = 0; i < of_thermal_get_ntrips(tz); i++)
0796         if (trips[i].type == THERMAL_TRIP_CRITICAL)
0797             break;
0798 
0799     if (i == of_thermal_get_ntrips(tz))
0800         return -EINVAL;
0801 
0802     ret = armada_select_channel(priv, sensor_id);
0803     if (ret)
0804         return ret;
0805 
0806     armada_set_overheat_thresholds(priv,
0807                        trips[i].temperature,
0808                        trips[i].hysteresis);
0809     priv->overheat_sensor = tz;
0810     priv->interrupt_source = sensor_id;
0811 
0812     armada_enable_overheat_interrupt(priv);
0813 
0814     return 0;
0815 }
0816 
0817 static int armada_thermal_probe(struct platform_device *pdev)
0818 {
0819     struct thermal_zone_device *tz;
0820     struct armada_thermal_sensor *sensor;
0821     struct armada_drvdata *drvdata;
0822     const struct of_device_id *match;
0823     struct armada_thermal_priv *priv;
0824     int sensor_id, irq;
0825     int ret;
0826 
0827     match = of_match_device(armada_thermal_id_table, &pdev->dev);
0828     if (!match)
0829         return -ENODEV;
0830 
0831     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0832     if (!priv)
0833         return -ENOMEM;
0834 
0835     drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
0836     if (!drvdata)
0837         return -ENOMEM;
0838 
0839     priv->dev = &pdev->dev;
0840     priv->data = (struct armada_thermal_data *)match->data;
0841 
0842     mutex_init(&priv->update_lock);
0843 
0844     /*
0845      * Legacy DT bindings only described "control1" register (also referred
0846      * as "control MSB" on old documentation). Then, bindings moved to cover
0847      * "control0/control LSB" and "control1/control MSB" registers within
0848      * the same resource, which was then of size 8 instead of 4.
0849      *
0850      * The logic of defining sporadic registers is broken. For instance, it
0851      * blocked the addition of the overheat interrupt feature that needed
0852      * another resource somewhere else in the same memory area. One solution
0853      * is to define an overall system controller and put the thermal node
0854      * into it, which requires the use of regmaps across all the driver.
0855      */
0856     if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) {
0857         /* Ensure device name is correct for the thermal core */
0858         armada_set_sane_name(pdev, priv);
0859 
0860         ret = armada_thermal_probe_legacy(pdev, priv);
0861         if (ret)
0862             return ret;
0863 
0864         priv->data->init(pdev, priv);
0865 
0866         /* Wait the sensors to be valid */
0867         armada_wait_sensor_validity(priv);
0868 
0869         tz = thermal_zone_device_register(priv->zone_name, 0, 0, priv,
0870                           &legacy_ops, NULL, 0, 0);
0871         if (IS_ERR(tz)) {
0872             dev_err(&pdev->dev,
0873                 "Failed to register thermal zone device\n");
0874             return PTR_ERR(tz);
0875         }
0876 
0877         ret = thermal_zone_device_enable(tz);
0878         if (ret) {
0879             thermal_zone_device_unregister(tz);
0880             return ret;
0881         }
0882 
0883         drvdata->type = LEGACY;
0884         drvdata->data.tz = tz;
0885         platform_set_drvdata(pdev, drvdata);
0886 
0887         return 0;
0888     }
0889 
0890     ret = armada_thermal_probe_syscon(pdev, priv);
0891     if (ret)
0892         return ret;
0893 
0894     priv->current_channel = -1;
0895     priv->data->init(pdev, priv);
0896     drvdata->type = SYSCON;
0897     drvdata->data.priv = priv;
0898     platform_set_drvdata(pdev, drvdata);
0899 
0900     irq = platform_get_irq(pdev, 0);
0901     if (irq == -EPROBE_DEFER)
0902         return irq;
0903 
0904     /* The overheat interrupt feature is not mandatory */
0905     if (irq > 0) {
0906         ret = devm_request_threaded_irq(&pdev->dev, irq,
0907                         armada_overheat_isr,
0908                         armada_overheat_isr_thread,
0909                         0, NULL, priv);
0910         if (ret) {
0911             dev_err(&pdev->dev, "Cannot request threaded IRQ %d\n",
0912                 irq);
0913             return ret;
0914         }
0915     }
0916 
0917     /*
0918      * There is one channel for the IC and one per CPU (if any), each
0919      * channel has one sensor.
0920      */
0921     for (sensor_id = 0; sensor_id <= priv->data->cpu_nr; sensor_id++) {
0922         sensor = devm_kzalloc(&pdev->dev,
0923                       sizeof(struct armada_thermal_sensor),
0924                       GFP_KERNEL);
0925         if (!sensor)
0926             return -ENOMEM;
0927 
0928         /* Register the sensor */
0929         sensor->priv = priv;
0930         sensor->id = sensor_id;
0931         tz = devm_thermal_zone_of_sensor_register(&pdev->dev,
0932                               sensor->id, sensor,
0933                               &of_ops);
0934         if (IS_ERR(tz)) {
0935             dev_info(&pdev->dev, "Thermal sensor %d unavailable\n",
0936                  sensor_id);
0937             devm_kfree(&pdev->dev, sensor);
0938             continue;
0939         }
0940 
0941         /*
0942          * The first channel that has a critical trip point registered
0943          * in the DT will serve as interrupt source. Others possible
0944          * critical trip points will simply be ignored by the driver.
0945          */
0946         if (irq > 0 && !priv->overheat_sensor)
0947             armada_configure_overheat_int(priv, tz, sensor->id);
0948     }
0949 
0950     /* Just complain if no overheat interrupt was set up */
0951     if (!priv->overheat_sensor)
0952         dev_warn(&pdev->dev, "Overheat interrupt not available\n");
0953 
0954     return 0;
0955 }
0956 
0957 static int armada_thermal_exit(struct platform_device *pdev)
0958 {
0959     struct armada_drvdata *drvdata = platform_get_drvdata(pdev);
0960 
0961     if (drvdata->type == LEGACY)
0962         thermal_zone_device_unregister(drvdata->data.tz);
0963 
0964     return 0;
0965 }
0966 
0967 static struct platform_driver armada_thermal_driver = {
0968     .probe = armada_thermal_probe,
0969     .remove = armada_thermal_exit,
0970     .driver = {
0971         .name = "armada_thermal",
0972         .of_match_table = armada_thermal_id_table,
0973     },
0974 };
0975 
0976 module_platform_driver(armada_thermal_driver);
0977 
0978 MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
0979 MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver");
0980 MODULE_LICENSE("GPL v2");