linux/drivers/thermal/exynos_thermal.c
<<
>>
Prefs
   1/*
   2 * exynos_thermal.c - Samsung EXYNOS TMU (Thermal Management Unit)
   3 *
   4 *  Copyright (C) 2011 Samsung Electronics
   5 *  Donggeun Kim <dg77.kim@samsung.com>
   6 *  Amit Daniel Kachhap <amit.kachhap@linaro.org>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 *
  22 */
  23
  24#include <linux/module.h>
  25#include <linux/err.h>
  26#include <linux/kernel.h>
  27#include <linux/slab.h>
  28#include <linux/platform_device.h>
  29#include <linux/interrupt.h>
  30#include <linux/clk.h>
  31#include <linux/workqueue.h>
  32#include <linux/sysfs.h>
  33#include <linux/kobject.h>
  34#include <linux/io.h>
  35#include <linux/mutex.h>
  36#include <linux/platform_data/exynos_thermal.h>
  37#include <linux/thermal.h>
  38#include <linux/cpufreq.h>
  39#include <linux/cpu_cooling.h>
  40#include <linux/of.h>
  41
  42/* Exynos generic registers */
  43#define EXYNOS_TMU_REG_TRIMINFO         0x0
  44#define EXYNOS_TMU_REG_CONTROL          0x20
  45#define EXYNOS_TMU_REG_STATUS           0x28
  46#define EXYNOS_TMU_REG_CURRENT_TEMP     0x40
  47#define EXYNOS_TMU_REG_INTEN            0x70
  48#define EXYNOS_TMU_REG_INTSTAT          0x74
  49#define EXYNOS_TMU_REG_INTCLEAR         0x78
  50
  51#define EXYNOS_TMU_TRIM_TEMP_MASK       0xff
  52#define EXYNOS_TMU_GAIN_SHIFT           8
  53#define EXYNOS_TMU_REF_VOLTAGE_SHIFT    24
  54#define EXYNOS_TMU_CORE_ON              3
  55#define EXYNOS_TMU_CORE_OFF             2
  56#define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET      50
  57
  58/* Exynos4210 specific registers */
  59#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP       0x44
  60#define EXYNOS4210_TMU_REG_TRIG_LEVEL0  0x50
  61#define EXYNOS4210_TMU_REG_TRIG_LEVEL1  0x54
  62#define EXYNOS4210_TMU_REG_TRIG_LEVEL2  0x58
  63#define EXYNOS4210_TMU_REG_TRIG_LEVEL3  0x5C
  64#define EXYNOS4210_TMU_REG_PAST_TEMP0   0x60
  65#define EXYNOS4210_TMU_REG_PAST_TEMP1   0x64
  66#define EXYNOS4210_TMU_REG_PAST_TEMP2   0x68
  67#define EXYNOS4210_TMU_REG_PAST_TEMP3   0x6C
  68
  69#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK 0x1
  70#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK 0x10
  71#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK 0x100
  72#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK 0x1000
  73#define EXYNOS4210_TMU_INTCLEAR_VAL     0x1111
  74
  75/* Exynos5250 and Exynos4412 specific registers */
  76#define EXYNOS_TMU_TRIMINFO_CON 0x14
  77#define EXYNOS_THD_TEMP_RISE            0x50
  78#define EXYNOS_THD_TEMP_FALL            0x54
  79#define EXYNOS_EMUL_CON         0x80
  80
  81#define EXYNOS_TRIMINFO_RELOAD          0x1
  82#define EXYNOS_TMU_CLEAR_RISE_INT       0x111
  83#define EXYNOS_TMU_CLEAR_FALL_INT       (0x111 << 12)
  84#define EXYNOS_MUX_ADDR_VALUE           6
  85#define EXYNOS_MUX_ADDR_SHIFT           20
  86#define EXYNOS_TMU_TRIP_MODE_SHIFT      13
  87
  88#define EFUSE_MIN_VALUE 40
  89#define EFUSE_MAX_VALUE 100
  90
  91/* In-kernel thermal framework related macros & definations */
  92#define SENSOR_NAME_LEN 16
  93#define MAX_TRIP_COUNT  8
  94#define MAX_COOLING_DEVICE 4
  95#define MAX_THRESHOLD_LEVS 4
  96
  97#define ACTIVE_INTERVAL 500
  98#define IDLE_INTERVAL 10000
  99#define MCELSIUS        1000
 100
 101#ifdef CONFIG_THERMAL_EMULATION
 102#define EXYNOS_EMUL_TIME        0x57F0
 103#define EXYNOS_EMUL_TIME_SHIFT  16
 104#define EXYNOS_EMUL_DATA_SHIFT  8
 105#define EXYNOS_EMUL_DATA_MASK   0xFF
 106#define EXYNOS_EMUL_ENABLE      0x1
 107#endif /* CONFIG_THERMAL_EMULATION */
 108
 109/* CPU Zone information */
 110#define PANIC_ZONE      4
 111#define WARN_ZONE       3
 112#define MONITOR_ZONE    2
 113#define SAFE_ZONE       1
 114
 115#define GET_ZONE(trip) (trip + 2)
 116#define GET_TRIP(zone) (zone - 2)
 117
 118#define EXYNOS_ZONE_COUNT       3
 119
 120struct exynos_tmu_data {
 121        struct exynos_tmu_platform_data *pdata;
 122        struct resource *mem;
 123        void __iomem *base;
 124        int irq;
 125        enum soc_type soc;
 126        struct work_struct irq_work;
 127        struct mutex lock;
 128        struct clk *clk;
 129        u8 temp_error1, temp_error2;
 130};
 131
 132struct  thermal_trip_point_conf {
 133        int trip_val[MAX_TRIP_COUNT];
 134        int trip_count;
 135        u8 trigger_falling;
 136};
 137
 138struct  thermal_cooling_conf {
 139        struct freq_clip_table freq_data[MAX_TRIP_COUNT];
 140        int freq_clip_count;
 141};
 142
 143struct thermal_sensor_conf {
 144        char name[SENSOR_NAME_LEN];
 145        int (*read_temperature)(void *data);
 146        int (*write_emul_temp)(void *drv_data, unsigned long temp);
 147        struct thermal_trip_point_conf trip_data;
 148        struct thermal_cooling_conf cooling_data;
 149        void *private_data;
 150};
 151
 152struct exynos_thermal_zone {
 153        enum thermal_device_mode mode;
 154        struct thermal_zone_device *therm_dev;
 155        struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
 156        unsigned int cool_dev_size;
 157        struct platform_device *exynos4_dev;
 158        struct thermal_sensor_conf *sensor_conf;
 159        bool bind;
 160};
 161
 162static struct exynos_thermal_zone *th_zone;
 163static void exynos_unregister_thermal(void);
 164static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
 165
 166/* Get mode callback functions for thermal zone */
 167static int exynos_get_mode(struct thermal_zone_device *thermal,
 168                        enum thermal_device_mode *mode)
 169{
 170        if (th_zone)
 171                *mode = th_zone->mode;
 172        return 0;
 173}
 174
 175/* Set mode callback functions for thermal zone */
 176static int exynos_set_mode(struct thermal_zone_device *thermal,
 177                        enum thermal_device_mode mode)
 178{
 179        if (!th_zone->therm_dev) {
 180                pr_notice("thermal zone not registered\n");
 181                return 0;
 182        }
 183
 184        mutex_lock(&th_zone->therm_dev->lock);
 185
 186        if (mode == THERMAL_DEVICE_ENABLED &&
 187                !th_zone->sensor_conf->trip_data.trigger_falling)
 188                th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
 189        else
 190                th_zone->therm_dev->polling_delay = 0;
 191
 192        mutex_unlock(&th_zone->therm_dev->lock);
 193
 194        th_zone->mode = mode;
 195        thermal_zone_device_update(th_zone->therm_dev);
 196        pr_info("thermal polling set for duration=%d msec\n",
 197                                th_zone->therm_dev->polling_delay);
 198        return 0;
 199}
 200
 201
 202/* Get trip type callback functions for thermal zone */
 203static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
 204                                 enum thermal_trip_type *type)
 205{
 206        switch (GET_ZONE(trip)) {
 207        case MONITOR_ZONE:
 208        case WARN_ZONE:
 209                *type = THERMAL_TRIP_ACTIVE;
 210                break;
 211        case PANIC_ZONE:
 212                *type = THERMAL_TRIP_CRITICAL;
 213                break;
 214        default:
 215                return -EINVAL;
 216        }
 217        return 0;
 218}
 219
 220/* Get trip temperature callback functions for thermal zone */
 221static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
 222                                unsigned long *temp)
 223{
 224        if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
 225                return -EINVAL;
 226
 227        *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
 228        /* convert the temperature into millicelsius */
 229        *temp = *temp * MCELSIUS;
 230
 231        return 0;
 232}
 233
 234/* Get critical temperature callback functions for thermal zone */
 235static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
 236                                unsigned long *temp)
 237{
 238        int ret;
 239        /* Panic zone */
 240        ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
 241        return ret;
 242}
 243
 244/* Bind callback functions for thermal zone */
 245static int exynos_bind(struct thermal_zone_device *thermal,
 246                        struct thermal_cooling_device *cdev)
 247{
 248        int ret = 0, i, tab_size, level;
 249        struct freq_clip_table *tab_ptr, *clip_data;
 250        struct thermal_sensor_conf *data = th_zone->sensor_conf;
 251
 252        tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
 253        tab_size = data->cooling_data.freq_clip_count;
 254
 255        if (tab_ptr == NULL || tab_size == 0)
 256                return -EINVAL;
 257
 258        /* find the cooling device registered*/
 259        for (i = 0; i < th_zone->cool_dev_size; i++)
 260                if (cdev == th_zone->cool_dev[i])
 261                        break;
 262
 263        /* No matching cooling device */
 264        if (i == th_zone->cool_dev_size)
 265                return 0;
 266
 267        /* Bind the thermal zone to the cpufreq cooling device */
 268        for (i = 0; i < tab_size; i++) {
 269                clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
 270                level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
 271                if (level == THERMAL_CSTATE_INVALID)
 272                        return 0;
 273                switch (GET_ZONE(i)) {
 274                case MONITOR_ZONE:
 275                case WARN_ZONE:
 276                        if (thermal_zone_bind_cooling_device(thermal, i, cdev,
 277                                                                level, 0)) {
 278                                pr_err("error binding cdev inst %d\n", i);
 279                                ret = -EINVAL;
 280                        }
 281                        th_zone->bind = true;
 282                        break;
 283                default:
 284                        ret = -EINVAL;
 285                }
 286        }
 287
 288        return ret;
 289}
 290
 291/* Unbind callback functions for thermal zone */
 292static int exynos_unbind(struct thermal_zone_device *thermal,
 293                        struct thermal_cooling_device *cdev)
 294{
 295        int ret = 0, i, tab_size;
 296        struct thermal_sensor_conf *data = th_zone->sensor_conf;
 297
 298        if (th_zone->bind == false)
 299                return 0;
 300
 301        tab_size = data->cooling_data.freq_clip_count;
 302
 303        if (tab_size == 0)
 304                return -EINVAL;
 305
 306        /* find the cooling device registered*/
 307        for (i = 0; i < th_zone->cool_dev_size; i++)
 308                if (cdev == th_zone->cool_dev[i])
 309                        break;
 310
 311        /* No matching cooling device */
 312        if (i == th_zone->cool_dev_size)
 313                return 0;
 314
 315        /* Bind the thermal zone to the cpufreq cooling device */
 316        for (i = 0; i < tab_size; i++) {
 317                switch (GET_ZONE(i)) {
 318                case MONITOR_ZONE:
 319                case WARN_ZONE:
 320                        if (thermal_zone_unbind_cooling_device(thermal, i,
 321                                                                cdev)) {
 322                                pr_err("error unbinding cdev inst=%d\n", i);
 323                                ret = -EINVAL;
 324                        }
 325                        th_zone->bind = false;
 326                        break;
 327                default:
 328                        ret = -EINVAL;
 329                }
 330        }
 331        return ret;
 332}
 333
 334/* Get temperature callback functions for thermal zone */
 335static int exynos_get_temp(struct thermal_zone_device *thermal,
 336                        unsigned long *temp)
 337{
 338        void *data;
 339
 340        if (!th_zone->sensor_conf) {
 341                pr_info("Temperature sensor not initialised\n");
 342                return -EINVAL;
 343        }
 344        data = th_zone->sensor_conf->private_data;
 345        *temp = th_zone->sensor_conf->read_temperature(data);
 346        /* convert the temperature into millicelsius */
 347        *temp = *temp * MCELSIUS;
 348        return 0;
 349}
 350
 351/* Get temperature callback functions for thermal zone */
 352static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
 353                                                unsigned long temp)
 354{
 355        void *data;
 356        int ret = -EINVAL;
 357
 358        if (!th_zone->sensor_conf) {
 359                pr_info("Temperature sensor not initialised\n");
 360                return -EINVAL;
 361        }
 362        data = th_zone->sensor_conf->private_data;
 363        if (th_zone->sensor_conf->write_emul_temp)
 364                ret = th_zone->sensor_conf->write_emul_temp(data, temp);
 365        return ret;
 366}
 367
 368/* Get the temperature trend */
 369static int exynos_get_trend(struct thermal_zone_device *thermal,
 370                        int trip, enum thermal_trend *trend)
 371{
 372        int ret;
 373        unsigned long trip_temp;
 374
 375        ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
 376        if (ret < 0)
 377                return ret;
 378
 379        if (thermal->temperature >= trip_temp)
 380                *trend = THERMAL_TREND_RAISE_FULL;
 381        else
 382                *trend = THERMAL_TREND_DROP_FULL;
 383
 384        return 0;
 385}
 386/* Operation callback functions for thermal zone */
 387static struct thermal_zone_device_ops const exynos_dev_ops = {
 388        .bind = exynos_bind,
 389        .unbind = exynos_unbind,
 390        .get_temp = exynos_get_temp,
 391        .set_emul_temp = exynos_set_emul_temp,
 392        .get_trend = exynos_get_trend,
 393        .get_mode = exynos_get_mode,
 394        .set_mode = exynos_set_mode,
 395        .get_trip_type = exynos_get_trip_type,
 396        .get_trip_temp = exynos_get_trip_temp,
 397        .get_crit_temp = exynos_get_crit_temp,
 398};
 399
 400/*
 401 * This function may be called from interrupt based temperature sensor
 402 * when threshold is changed.
 403 */
 404static void exynos_report_trigger(void)
 405{
 406        unsigned int i;
 407        char data[10];
 408        char *envp[] = { data, NULL };
 409
 410        if (!th_zone || !th_zone->therm_dev)
 411                return;
 412        if (th_zone->bind == false) {
 413                for (i = 0; i < th_zone->cool_dev_size; i++) {
 414                        if (!th_zone->cool_dev[i])
 415                                continue;
 416                        exynos_bind(th_zone->therm_dev,
 417                                        th_zone->cool_dev[i]);
 418                }
 419        }
 420
 421        thermal_zone_device_update(th_zone->therm_dev);
 422
 423        mutex_lock(&th_zone->therm_dev->lock);
 424        /* Find the level for which trip happened */
 425        for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
 426                if (th_zone->therm_dev->last_temperature <
 427                        th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
 428                        break;
 429        }
 430
 431        if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
 432                !th_zone->sensor_conf->trip_data.trigger_falling) {
 433                if (i > 0)
 434                        th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
 435                else
 436                        th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
 437        }
 438
 439        snprintf(data, sizeof(data), "%u", i);
 440        kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
 441        mutex_unlock(&th_zone->therm_dev->lock);
 442}
 443
 444/* Register with the in-kernel thermal management */
 445static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
 446{
 447        int ret;
 448        struct cpumask mask_val;
 449
 450        if (!sensor_conf || !sensor_conf->read_temperature) {
 451                pr_err("Temperature sensor not initialised\n");
 452                return -EINVAL;
 453        }
 454
 455        th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
 456        if (!th_zone)
 457                return -ENOMEM;
 458
 459        th_zone->sensor_conf = sensor_conf;
 460        cpumask_set_cpu(0, &mask_val);
 461        th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
 462        if (IS_ERR(th_zone->cool_dev[0])) {
 463                pr_err("Failed to register cpufreq cooling device\n");
 464                ret = -EINVAL;
 465                goto err_unregister;
 466        }
 467        th_zone->cool_dev_size++;
 468
 469        th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
 470                        EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
 471                        sensor_conf->trip_data.trigger_falling ?
 472                        0 : IDLE_INTERVAL);
 473
 474        if (IS_ERR(th_zone->therm_dev)) {
 475                pr_err("Failed to register thermal zone device\n");
 476                ret = PTR_ERR(th_zone->therm_dev);
 477                goto err_unregister;
 478        }
 479        th_zone->mode = THERMAL_DEVICE_ENABLED;
 480
 481        pr_info("Exynos: Kernel Thermal management registered\n");
 482
 483        return 0;
 484
 485err_unregister:
 486        exynos_unregister_thermal();
 487        return ret;
 488}
 489
 490/* Un-Register with the in-kernel thermal management */
 491static void exynos_unregister_thermal(void)
 492{
 493        int i;
 494
 495        if (!th_zone)
 496                return;
 497
 498        if (th_zone->therm_dev)
 499                thermal_zone_device_unregister(th_zone->therm_dev);
 500
 501        for (i = 0; i < th_zone->cool_dev_size; i++) {
 502                if (th_zone->cool_dev[i])
 503                        cpufreq_cooling_unregister(th_zone->cool_dev[i]);
 504        }
 505
 506        kfree(th_zone);
 507        pr_info("Exynos: Kernel Thermal management unregistered\n");
 508}
 509
 510/*
 511 * TMU treats temperature as a mapped temperature code.
 512 * The temperature is converted differently depending on the calibration type.
 513 */
 514static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
 515{
 516        struct exynos_tmu_platform_data *pdata = data->pdata;
 517        int temp_code;
 518
 519        if (data->soc == SOC_ARCH_EXYNOS4210)
 520                /* temp should range between 25 and 125 */
 521                if (temp < 25 || temp > 125) {
 522                        temp_code = -EINVAL;
 523                        goto out;
 524                }
 525
 526        switch (pdata->cal_type) {
 527        case TYPE_TWO_POINT_TRIMMING:
 528                temp_code = (temp - 25) *
 529                    (data->temp_error2 - data->temp_error1) /
 530                    (85 - 25) + data->temp_error1;
 531                break;
 532        case TYPE_ONE_POINT_TRIMMING:
 533                temp_code = temp + data->temp_error1 - 25;
 534                break;
 535        default:
 536                temp_code = temp + EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
 537                break;
 538        }
 539out:
 540        return temp_code;
 541}
 542
 543/*
 544 * Calculate a temperature value from a temperature code.
 545 * The unit of the temperature is degree Celsius.
 546 */
 547static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
 548{
 549        struct exynos_tmu_platform_data *pdata = data->pdata;
 550        int temp;
 551
 552        if (data->soc == SOC_ARCH_EXYNOS4210)
 553                /* temp_code should range between 75 and 175 */
 554                if (temp_code < 75 || temp_code > 175) {
 555                        temp = -ENODATA;
 556                        goto out;
 557                }
 558
 559        switch (pdata->cal_type) {
 560        case TYPE_TWO_POINT_TRIMMING:
 561                temp = (temp_code - data->temp_error1) * (85 - 25) /
 562                    (data->temp_error2 - data->temp_error1) + 25;
 563                break;
 564        case TYPE_ONE_POINT_TRIMMING:
 565                temp = temp_code - data->temp_error1 + 25;
 566                break;
 567        default:
 568                temp = temp_code - EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
 569                break;
 570        }
 571out:
 572        return temp;
 573}
 574
 575static int exynos_tmu_initialize(struct platform_device *pdev)
 576{
 577        struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 578        struct exynos_tmu_platform_data *pdata = data->pdata;
 579        unsigned int status, trim_info;
 580        unsigned int rising_threshold = 0, falling_threshold = 0;
 581        int ret = 0, threshold_code, i, trigger_levs = 0;
 582
 583        mutex_lock(&data->lock);
 584        clk_enable(data->clk);
 585
 586        status = readb(data->base + EXYNOS_TMU_REG_STATUS);
 587        if (!status) {
 588                ret = -EBUSY;
 589                goto out;
 590        }
 591
 592        if (data->soc == SOC_ARCH_EXYNOS) {
 593                __raw_writel(EXYNOS_TRIMINFO_RELOAD,
 594                                data->base + EXYNOS_TMU_TRIMINFO_CON);
 595        }
 596        /* Save trimming info in order to perform calibration */
 597        trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
 598        data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
 599        data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
 600
 601        if ((EFUSE_MIN_VALUE > data->temp_error1) ||
 602                        (data->temp_error1 > EFUSE_MAX_VALUE) ||
 603                        (data->temp_error2 != 0))
 604                data->temp_error1 = pdata->efuse_value;
 605
 606        /* Count trigger levels to be enabled */
 607        for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
 608                if (pdata->trigger_levels[i])
 609                        trigger_levs++;
 610
 611        if (data->soc == SOC_ARCH_EXYNOS4210) {
 612                /* Write temperature code for threshold */
 613                threshold_code = temp_to_code(data, pdata->threshold);
 614                if (threshold_code < 0) {
 615                        ret = threshold_code;
 616                        goto out;
 617                }
 618                writeb(threshold_code,
 619                        data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
 620                for (i = 0; i < trigger_levs; i++)
 621                        writeb(pdata->trigger_levels[i],
 622                        data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
 623
 624                writel(EXYNOS4210_TMU_INTCLEAR_VAL,
 625                        data->base + EXYNOS_TMU_REG_INTCLEAR);
 626        } else if (data->soc == SOC_ARCH_EXYNOS) {
 627                /* Write temperature code for rising and falling threshold */
 628                for (i = 0; i < trigger_levs; i++) {
 629                        threshold_code = temp_to_code(data,
 630                                                pdata->trigger_levels[i]);
 631                        if (threshold_code < 0) {
 632                                ret = threshold_code;
 633                                goto out;
 634                        }
 635                        rising_threshold |= threshold_code << 8 * i;
 636                        if (pdata->threshold_falling) {
 637                                threshold_code = temp_to_code(data,
 638                                                pdata->trigger_levels[i] -
 639                                                pdata->threshold_falling);
 640                                if (threshold_code > 0)
 641                                        falling_threshold |=
 642                                                threshold_code << 8 * i;
 643                        }
 644                }
 645
 646                writel(rising_threshold,
 647                                data->base + EXYNOS_THD_TEMP_RISE);
 648                writel(falling_threshold,
 649                                data->base + EXYNOS_THD_TEMP_FALL);
 650
 651                writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
 652                                data->base + EXYNOS_TMU_REG_INTCLEAR);
 653        }
 654out:
 655        clk_disable(data->clk);
 656        mutex_unlock(&data->lock);
 657
 658        return ret;
 659}
 660
 661static void exynos_tmu_control(struct platform_device *pdev, bool on)
 662{
 663        struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 664        struct exynos_tmu_platform_data *pdata = data->pdata;
 665        unsigned int con, interrupt_en;
 666
 667        mutex_lock(&data->lock);
 668        clk_enable(data->clk);
 669
 670        con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
 671                pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
 672
 673        if (data->soc == SOC_ARCH_EXYNOS) {
 674                con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
 675                con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
 676        }
 677
 678        if (on) {
 679                con |= EXYNOS_TMU_CORE_ON;
 680                interrupt_en = pdata->trigger_level3_en << 12 |
 681                        pdata->trigger_level2_en << 8 |
 682                        pdata->trigger_level1_en << 4 |
 683                        pdata->trigger_level0_en;
 684                if (pdata->threshold_falling)
 685                        interrupt_en |= interrupt_en << 16;
 686        } else {
 687                con |= EXYNOS_TMU_CORE_OFF;
 688                interrupt_en = 0; /* Disable all interrupts */
 689        }
 690        writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
 691        writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
 692
 693        clk_disable(data->clk);
 694        mutex_unlock(&data->lock);
 695}
 696
 697static int exynos_tmu_read(struct exynos_tmu_data *data)
 698{
 699        u8 temp_code;
 700        int temp;
 701
 702        mutex_lock(&data->lock);
 703        clk_enable(data->clk);
 704
 705        temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
 706        temp = code_to_temp(data, temp_code);
 707
 708        clk_disable(data->clk);
 709        mutex_unlock(&data->lock);
 710
 711        return temp;
 712}
 713
 714#ifdef CONFIG_THERMAL_EMULATION
 715static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
 716{
 717        struct exynos_tmu_data *data = drv_data;
 718        unsigned int reg;
 719        int ret = -EINVAL;
 720
 721        if (data->soc == SOC_ARCH_EXYNOS4210)
 722                goto out;
 723
 724        if (temp && temp < MCELSIUS)
 725                goto out;
 726
 727        mutex_lock(&data->lock);
 728        clk_enable(data->clk);
 729
 730        reg = readl(data->base + EXYNOS_EMUL_CON);
 731
 732        if (temp) {
 733                temp /= MCELSIUS;
 734
 735                reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
 736                        (temp_to_code(data, temp)
 737                         << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
 738        } else {
 739                reg &= ~EXYNOS_EMUL_ENABLE;
 740        }
 741
 742        writel(reg, data->base + EXYNOS_EMUL_CON);
 743
 744        clk_disable(data->clk);
 745        mutex_unlock(&data->lock);
 746        return 0;
 747out:
 748        return ret;
 749}
 750#else
 751static int exynos_tmu_set_emulation(void *drv_data,     unsigned long temp)
 752        { return -EINVAL; }
 753#endif/*CONFIG_THERMAL_EMULATION*/
 754
 755static void exynos_tmu_work(struct work_struct *work)
 756{
 757        struct exynos_tmu_data *data = container_of(work,
 758                        struct exynos_tmu_data, irq_work);
 759
 760        exynos_report_trigger();
 761        mutex_lock(&data->lock);
 762        clk_enable(data->clk);
 763        if (data->soc == SOC_ARCH_EXYNOS)
 764                writel(EXYNOS_TMU_CLEAR_RISE_INT |
 765                                EXYNOS_TMU_CLEAR_FALL_INT,
 766                                data->base + EXYNOS_TMU_REG_INTCLEAR);
 767        else
 768                writel(EXYNOS4210_TMU_INTCLEAR_VAL,
 769                                data->base + EXYNOS_TMU_REG_INTCLEAR);
 770        clk_disable(data->clk);
 771        mutex_unlock(&data->lock);
 772
 773        enable_irq(data->irq);
 774}
 775
 776static irqreturn_t exynos_tmu_irq(int irq, void *id)
 777{
 778        struct exynos_tmu_data *data = id;
 779
 780        disable_irq_nosync(irq);
 781        schedule_work(&data->irq_work);
 782
 783        return IRQ_HANDLED;
 784}
 785static struct thermal_sensor_conf exynos_sensor_conf = {
 786        .name                   = "exynos-therm",
 787        .read_temperature       = (int (*)(void *))exynos_tmu_read,
 788        .write_emul_temp        = exynos_tmu_set_emulation,
 789};
 790
 791#if defined(CONFIG_CPU_EXYNOS4210)
 792static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
 793        .threshold = 80,
 794        .trigger_levels[0] = 5,
 795        .trigger_levels[1] = 20,
 796        .trigger_levels[2] = 30,
 797        .trigger_level0_en = 1,
 798        .trigger_level1_en = 1,
 799        .trigger_level2_en = 1,
 800        .trigger_level3_en = 0,
 801        .gain = 15,
 802        .reference_voltage = 7,
 803        .cal_type = TYPE_ONE_POINT_TRIMMING,
 804        .freq_tab[0] = {
 805                .freq_clip_max = 800 * 1000,
 806                .temp_level = 85,
 807        },
 808        .freq_tab[1] = {
 809                .freq_clip_max = 200 * 1000,
 810                .temp_level = 100,
 811        },
 812        .freq_tab_count = 2,
 813        .type = SOC_ARCH_EXYNOS4210,
 814};
 815#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
 816#else
 817#define EXYNOS4210_TMU_DRV_DATA (NULL)
 818#endif
 819
 820#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
 821static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
 822        .threshold_falling = 10,
 823        .trigger_levels[0] = 85,
 824        .trigger_levels[1] = 103,
 825        .trigger_levels[2] = 110,
 826        .trigger_level0_en = 1,
 827        .trigger_level1_en = 1,
 828        .trigger_level2_en = 1,
 829        .trigger_level3_en = 0,
 830        .gain = 8,
 831        .reference_voltage = 16,
 832        .noise_cancel_mode = 4,
 833        .cal_type = TYPE_ONE_POINT_TRIMMING,
 834        .efuse_value = 55,
 835        .freq_tab[0] = {
 836                .freq_clip_max = 800 * 1000,
 837                .temp_level = 85,
 838        },
 839        .freq_tab[1] = {
 840                .freq_clip_max = 200 * 1000,
 841                .temp_level = 103,
 842        },
 843        .freq_tab_count = 2,
 844        .type = SOC_ARCH_EXYNOS,
 845};
 846#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
 847#else
 848#define EXYNOS_TMU_DRV_DATA (NULL)
 849#endif
 850
 851#ifdef CONFIG_OF
 852static const struct of_device_id exynos_tmu_match[] = {
 853        {
 854                .compatible = "samsung,exynos4210-tmu",
 855                .data = (void *)EXYNOS4210_TMU_DRV_DATA,
 856        },
 857        {
 858                .compatible = "samsung,exynos4412-tmu",
 859                .data = (void *)EXYNOS_TMU_DRV_DATA,
 860        },
 861        {
 862                .compatible = "samsung,exynos5250-tmu",
 863                .data = (void *)EXYNOS_TMU_DRV_DATA,
 864        },
 865        {},
 866};
 867MODULE_DEVICE_TABLE(of, exynos_tmu_match);
 868#endif
 869
 870static struct platform_device_id exynos_tmu_driver_ids[] = {
 871        {
 872                .name           = "exynos4210-tmu",
 873                .driver_data    = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
 874        },
 875        {
 876                .name           = "exynos5250-tmu",
 877                .driver_data    = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
 878        },
 879        { },
 880};
 881MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
 882
 883static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
 884                        struct platform_device *pdev)
 885{
 886#ifdef CONFIG_OF
 887        if (pdev->dev.of_node) {
 888                const struct of_device_id *match;
 889                match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
 890                if (!match)
 891                        return NULL;
 892                return (struct exynos_tmu_platform_data *) match->data;
 893        }
 894#endif
 895        return (struct exynos_tmu_platform_data *)
 896                        platform_get_device_id(pdev)->driver_data;
 897}
 898
 899static int exynos_tmu_probe(struct platform_device *pdev)
 900{
 901        struct exynos_tmu_data *data;
 902        struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
 903        int ret, i;
 904
 905        if (!pdata)
 906                pdata = exynos_get_driver_data(pdev);
 907
 908        if (!pdata) {
 909                dev_err(&pdev->dev, "No platform init data supplied.\n");
 910                return -ENODEV;
 911        }
 912        data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
 913                                        GFP_KERNEL);
 914        if (!data) {
 915                dev_err(&pdev->dev, "Failed to allocate driver structure\n");
 916                return -ENOMEM;
 917        }
 918
 919        data->irq = platform_get_irq(pdev, 0);
 920        if (data->irq < 0) {
 921                dev_err(&pdev->dev, "Failed to get platform irq\n");
 922                return data->irq;
 923        }
 924
 925        INIT_WORK(&data->irq_work, exynos_tmu_work);
 926
 927        data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 928        data->base = devm_ioremap_resource(&pdev->dev, data->mem);
 929        if (IS_ERR(data->base))
 930                return PTR_ERR(data->base);
 931
 932        ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
 933                IRQF_TRIGGER_RISING, "exynos-tmu", data);
 934        if (ret) {
 935                dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
 936                return ret;
 937        }
 938
 939        data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
 940        if (IS_ERR(data->clk)) {
 941                dev_err(&pdev->dev, "Failed to get clock\n");
 942                return  PTR_ERR(data->clk);
 943        }
 944
 945        ret = clk_prepare(data->clk);
 946        if (ret)
 947                return ret;
 948
 949        if (pdata->type == SOC_ARCH_EXYNOS ||
 950                                pdata->type == SOC_ARCH_EXYNOS4210)
 951                data->soc = pdata->type;
 952        else {
 953                ret = -EINVAL;
 954                dev_err(&pdev->dev, "Platform not supported\n");
 955                goto err_clk;
 956        }
 957
 958        data->pdata = pdata;
 959        platform_set_drvdata(pdev, data);
 960        mutex_init(&data->lock);
 961
 962        ret = exynos_tmu_initialize(pdev);
 963        if (ret) {
 964                dev_err(&pdev->dev, "Failed to initialize TMU\n");
 965                goto err_clk;
 966        }
 967
 968        exynos_tmu_control(pdev, true);
 969
 970        /* Register the sensor with thermal management interface */
 971        (&exynos_sensor_conf)->private_data = data;
 972        exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en +
 973                        pdata->trigger_level1_en + pdata->trigger_level2_en +
 974                        pdata->trigger_level3_en;
 975
 976        for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
 977                exynos_sensor_conf.trip_data.trip_val[i] =
 978                        pdata->threshold + pdata->trigger_levels[i];
 979
 980        exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
 981
 982        exynos_sensor_conf.cooling_data.freq_clip_count =
 983                                                pdata->freq_tab_count;
 984        for (i = 0; i < pdata->freq_tab_count; i++) {
 985                exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
 986                                        pdata->freq_tab[i].freq_clip_max;
 987                exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
 988                                        pdata->freq_tab[i].temp_level;
 989        }
 990
 991        ret = exynos_register_thermal(&exynos_sensor_conf);
 992        if (ret) {
 993                dev_err(&pdev->dev, "Failed to register thermal interface\n");
 994                goto err_clk;
 995        }
 996
 997        return 0;
 998err_clk:
 999        platform_set_drvdata(pdev, NULL);
1000        clk_unprepare(data->clk);
1001        return ret;
1002}
1003
1004static int exynos_tmu_remove(struct platform_device *pdev)
1005{
1006        struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1007
1008        exynos_tmu_control(pdev, false);
1009
1010        exynos_unregister_thermal();
1011
1012        clk_unprepare(data->clk);
1013
1014        platform_set_drvdata(pdev, NULL);
1015
1016        return 0;
1017}
1018
1019#ifdef CONFIG_PM_SLEEP
1020static int exynos_tmu_suspend(struct device *dev)
1021{
1022        exynos_tmu_control(to_platform_device(dev), false);
1023
1024        return 0;
1025}
1026
1027static int exynos_tmu_resume(struct device *dev)
1028{
1029        struct platform_device *pdev = to_platform_device(dev);
1030
1031        exynos_tmu_initialize(pdev);
1032        exynos_tmu_control(pdev, true);
1033
1034        return 0;
1035}
1036
1037static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
1038                         exynos_tmu_suspend, exynos_tmu_resume);
1039#define EXYNOS_TMU_PM   (&exynos_tmu_pm)
1040#else
1041#define EXYNOS_TMU_PM   NULL
1042#endif
1043
1044static struct platform_driver exynos_tmu_driver = {
1045        .driver = {
1046                .name   = "exynos-tmu",
1047                .owner  = THIS_MODULE,
1048                .pm     = EXYNOS_TMU_PM,
1049                .of_match_table = of_match_ptr(exynos_tmu_match),
1050        },
1051        .probe = exynos_tmu_probe,
1052        .remove = exynos_tmu_remove,
1053        .id_table = exynos_tmu_driver_ids,
1054};
1055
1056module_platform_driver(exynos_tmu_driver);
1057
1058MODULE_DESCRIPTION("EXYNOS TMU Driver");
1059MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
1060MODULE_LICENSE("GPL");
1061MODULE_ALIAS("platform:exynos-tmu");
1062
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.