diff options
author | Zhang Rui <rui.zhang@intel.com> | 2017-01-17 02:51:21 -0500 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2017-01-17 02:51:21 -0500 |
commit | 6c75a5d1131eba90fcf04adc586167e65afc79b0 (patch) | |
tree | f8614b9fd8f9662c39c7673e6578d271c85834e7 | |
parent | 0c744ea4f77d72b3dcebb7a8f2684633ec79be88 (diff) | |
parent | db8318865e2c04dbe3d95089c7215b94a5b879b7 (diff) |
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal into thermal-soc
-rw-r--r-- | drivers/thermal/rockchip_thermal.c | 153 |
1 files changed, 100 insertions, 53 deletions
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index b811b0fb61b1..4c7796512453 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c | |||
@@ -118,12 +118,12 @@ struct rockchip_tsadc_chip { | |||
118 | void (*control)(void __iomem *reg, bool on); | 118 | void (*control)(void __iomem *reg, bool on); |
119 | 119 | ||
120 | /* Per-sensor methods */ | 120 | /* Per-sensor methods */ |
121 | int (*get_temp)(struct chip_tsadc_table table, | 121 | int (*get_temp)(const struct chip_tsadc_table *table, |
122 | int chn, void __iomem *reg, int *temp); | 122 | int chn, void __iomem *reg, int *temp); |
123 | void (*set_alarm_temp)(struct chip_tsadc_table table, | 123 | int (*set_alarm_temp)(const struct chip_tsadc_table *table, |
124 | int chn, void __iomem *reg, int temp); | 124 | int chn, void __iomem *reg, int temp); |
125 | void (*set_tshut_temp)(struct chip_tsadc_table table, | 125 | int (*set_tshut_temp)(const struct chip_tsadc_table *table, |
126 | int chn, void __iomem *reg, int temp); | 126 | int chn, void __iomem *reg, int temp); |
127 | void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m); | 127 | void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m); |
128 | 128 | ||
129 | /* Per-table methods */ | 129 | /* Per-table methods */ |
@@ -317,6 +317,7 @@ static const struct tsadc_table rk3288_code_table[] = { | |||
317 | {3452, 115000}, | 317 | {3452, 115000}, |
318 | {3437, 120000}, | 318 | {3437, 120000}, |
319 | {3421, 125000}, | 319 | {3421, 125000}, |
320 | {0, 125000}, | ||
320 | }; | 321 | }; |
321 | 322 | ||
322 | static const struct tsadc_table rk3368_code_table[] = { | 323 | static const struct tsadc_table rk3368_code_table[] = { |
@@ -397,59 +398,80 @@ static const struct tsadc_table rk3399_code_table[] = { | |||
397 | {TSADCV3_DATA_MASK, 125000}, | 398 | {TSADCV3_DATA_MASK, 125000}, |
398 | }; | 399 | }; |
399 | 400 | ||
400 | static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, | 401 | static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table, |
401 | int temp) | 402 | int temp) |
402 | { | 403 | { |
403 | int high, low, mid; | 404 | int high, low, mid; |
404 | u32 error = 0; | 405 | unsigned long num; |
406 | unsigned int denom; | ||
407 | u32 error = table->data_mask; | ||
405 | 408 | ||
406 | low = 0; | 409 | low = 0; |
407 | high = table.length - 1; | 410 | high = (table->length - 1) - 1; /* ignore the last check for table */ |
408 | mid = (high + low) / 2; | 411 | mid = (high + low) / 2; |
409 | 412 | ||
410 | /* Return mask code data when the temp is over table range */ | 413 | /* Return mask code data when the temp is over table range */ |
411 | if (temp < table.id[low].temp || temp > table.id[high].temp) { | 414 | if (temp < table->id[low].temp || temp > table->id[high].temp) |
412 | error = table.data_mask; | ||
413 | goto exit; | 415 | goto exit; |
414 | } | ||
415 | 416 | ||
416 | while (low <= high) { | 417 | while (low <= high) { |
417 | if (temp == table.id[mid].temp) | 418 | if (temp == table->id[mid].temp) |
418 | return table.id[mid].code; | 419 | return table->id[mid].code; |
419 | else if (temp < table.id[mid].temp) | 420 | else if (temp < table->id[mid].temp) |
420 | high = mid - 1; | 421 | high = mid - 1; |
421 | else | 422 | else |
422 | low = mid + 1; | 423 | low = mid + 1; |
423 | mid = (low + high) / 2; | 424 | mid = (low + high) / 2; |
424 | } | 425 | } |
425 | 426 | ||
427 | /* | ||
428 | * The conversion code granularity provided by the table. Let's | ||
429 | * assume that the relationship between temperature and | ||
430 | * analog value between 2 table entries is linear and interpolate | ||
431 | * to produce less granular result. | ||
432 | */ | ||
433 | num = abs(table->id[mid + 1].code - table->id[mid].code); | ||
434 | num *= temp - table->id[mid].temp; | ||
435 | denom = table->id[mid + 1].temp - table->id[mid].temp; | ||
436 | |||
437 | switch (table->mode) { | ||
438 | case ADC_DECREMENT: | ||
439 | return table->id[mid].code - (num / denom); | ||
440 | case ADC_INCREMENT: | ||
441 | return table->id[mid].code + (num / denom); | ||
442 | default: | ||
443 | pr_err("%s: unknown table mode: %d\n", __func__, table->mode); | ||
444 | return error; | ||
445 | } | ||
446 | |||
426 | exit: | 447 | exit: |
427 | pr_err("Invalid the conversion, error=%d\n", error); | 448 | pr_err("%s: invalid temperature, temp=%d error=%d\n", |
449 | __func__, temp, error); | ||
428 | return error; | 450 | return error; |
429 | } | 451 | } |
430 | 452 | ||
431 | static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, | 453 | static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table, |
432 | int *temp) | 454 | u32 code, int *temp) |
433 | { | 455 | { |
434 | unsigned int low = 1; | 456 | unsigned int low = 1; |
435 | unsigned int high = table.length - 1; | 457 | unsigned int high = table->length - 1; |
436 | unsigned int mid = (low + high) / 2; | 458 | unsigned int mid = (low + high) / 2; |
437 | unsigned int num; | 459 | unsigned int num; |
438 | unsigned long denom; | 460 | unsigned long denom; |
439 | 461 | ||
440 | WARN_ON(table.length < 2); | 462 | WARN_ON(table->length < 2); |
441 | 463 | ||
442 | switch (table.mode) { | 464 | switch (table->mode) { |
443 | case ADC_DECREMENT: | 465 | case ADC_DECREMENT: |
444 | code &= table.data_mask; | 466 | code &= table->data_mask; |
445 | if (code < table.id[high].code) | 467 | if (code <= table->id[high].code) |
446 | return -EAGAIN; /* Incorrect reading */ | 468 | return -EAGAIN; /* Incorrect reading */ |
447 | 469 | ||
448 | while (low <= high) { | 470 | while (low <= high) { |
449 | if (code >= table.id[mid].code && | 471 | if (code >= table->id[mid].code && |
450 | code < table.id[mid - 1].code) | 472 | code < table->id[mid - 1].code) |
451 | break; | 473 | break; |
452 | else if (code < table.id[mid].code) | 474 | else if (code < table->id[mid].code) |
453 | low = mid + 1; | 475 | low = mid + 1; |
454 | else | 476 | else |
455 | high = mid - 1; | 477 | high = mid - 1; |
@@ -458,15 +480,15 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, | |||
458 | } | 480 | } |
459 | break; | 481 | break; |
460 | case ADC_INCREMENT: | 482 | case ADC_INCREMENT: |
461 | code &= table.data_mask; | 483 | code &= table->data_mask; |
462 | if (code < table.id[low].code) | 484 | if (code < table->id[low].code) |
463 | return -EAGAIN; /* Incorrect reading */ | 485 | return -EAGAIN; /* Incorrect reading */ |
464 | 486 | ||
465 | while (low <= high) { | 487 | while (low <= high) { |
466 | if (code <= table.id[mid].code && | 488 | if (code <= table->id[mid].code && |
467 | code > table.id[mid - 1].code) | 489 | code > table->id[mid - 1].code) |
468 | break; | 490 | break; |
469 | else if (code > table.id[mid].code) | 491 | else if (code > table->id[mid].code) |
470 | low = mid + 1; | 492 | low = mid + 1; |
471 | else | 493 | else |
472 | high = mid - 1; | 494 | high = mid - 1; |
@@ -475,7 +497,8 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, | |||
475 | } | 497 | } |
476 | break; | 498 | break; |
477 | default: | 499 | default: |
478 | pr_err("Invalid the conversion table\n"); | 500 | pr_err("%s: unknown table mode: %d\n", __func__, table->mode); |
501 | return -EINVAL; | ||
479 | } | 502 | } |
480 | 503 | ||
481 | /* | 504 | /* |
@@ -484,10 +507,10 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, | |||
484 | * temperature between 2 table entries is linear and interpolate | 507 | * temperature between 2 table entries is linear and interpolate |
485 | * to produce less granular result. | 508 | * to produce less granular result. |
486 | */ | 509 | */ |
487 | num = table.id[mid].temp - table.id[mid - 1].temp; | 510 | num = table->id[mid].temp - table->id[mid - 1].temp; |
488 | num *= abs(table.id[mid - 1].code - code); | 511 | num *= abs(table->id[mid - 1].code - code); |
489 | denom = abs(table.id[mid - 1].code - table.id[mid].code); | 512 | denom = abs(table->id[mid - 1].code - table->id[mid].code); |
490 | *temp = table.id[mid - 1].temp + (num / denom); | 513 | *temp = table->id[mid - 1].temp + (num / denom); |
491 | 514 | ||
492 | return 0; | 515 | return 0; |
493 | } | 516 | } |
@@ -638,7 +661,7 @@ static void rk_tsadcv3_control(void __iomem *regs, bool enable) | |||
638 | writel_relaxed(val, regs + TSADCV2_AUTO_CON); | 661 | writel_relaxed(val, regs + TSADCV2_AUTO_CON); |
639 | } | 662 | } |
640 | 663 | ||
641 | static int rk_tsadcv2_get_temp(struct chip_tsadc_table table, | 664 | static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table, |
642 | int chn, void __iomem *regs, int *temp) | 665 | int chn, void __iomem *regs, int *temp) |
643 | { | 666 | { |
644 | u32 val; | 667 | u32 val; |
@@ -648,39 +671,57 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table, | |||
648 | return rk_tsadcv2_code_to_temp(table, val, temp); | 671 | return rk_tsadcv2_code_to_temp(table, val, temp); |
649 | } | 672 | } |
650 | 673 | ||
651 | static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table, | 674 | static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table, |
652 | int chn, void __iomem *regs, int temp) | 675 | int chn, void __iomem *regs, int temp) |
653 | { | 676 | { |
654 | u32 alarm_value, int_en; | 677 | u32 alarm_value; |
678 | u32 int_en, int_clr; | ||
679 | |||
680 | /* | ||
681 | * In some cases, some sensors didn't need the trip points, the | ||
682 | * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm | ||
683 | * in the end, ignore this case and disable the high temperature | ||
684 | * interrupt. | ||
685 | */ | ||
686 | if (temp == INT_MAX) { | ||
687 | int_clr = readl_relaxed(regs + TSADCV2_INT_EN); | ||
688 | int_clr &= ~TSADCV2_INT_SRC_EN(chn); | ||
689 | writel_relaxed(int_clr, regs + TSADCV2_INT_EN); | ||
690 | return 0; | ||
691 | } | ||
655 | 692 | ||
656 | /* Make sure the value is valid */ | 693 | /* Make sure the value is valid */ |
657 | alarm_value = rk_tsadcv2_temp_to_code(table, temp); | 694 | alarm_value = rk_tsadcv2_temp_to_code(table, temp); |
658 | if (alarm_value == table.data_mask) | 695 | if (alarm_value == table->data_mask) |
659 | return; | 696 | return -ERANGE; |
660 | 697 | ||
661 | writel_relaxed(alarm_value & table.data_mask, | 698 | writel_relaxed(alarm_value & table->data_mask, |
662 | regs + TSADCV2_COMP_INT(chn)); | 699 | regs + TSADCV2_COMP_INT(chn)); |
663 | 700 | ||
664 | int_en = readl_relaxed(regs + TSADCV2_INT_EN); | 701 | int_en = readl_relaxed(regs + TSADCV2_INT_EN); |
665 | int_en |= TSADCV2_INT_SRC_EN(chn); | 702 | int_en |= TSADCV2_INT_SRC_EN(chn); |
666 | writel_relaxed(int_en, regs + TSADCV2_INT_EN); | 703 | writel_relaxed(int_en, regs + TSADCV2_INT_EN); |
704 | |||
705 | return 0; | ||
667 | } | 706 | } |
668 | 707 | ||
669 | static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table, | 708 | static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table, |
670 | int chn, void __iomem *regs, int temp) | 709 | int chn, void __iomem *regs, int temp) |
671 | { | 710 | { |
672 | u32 tshut_value, val; | 711 | u32 tshut_value, val; |
673 | 712 | ||
674 | /* Make sure the value is valid */ | 713 | /* Make sure the value is valid */ |
675 | tshut_value = rk_tsadcv2_temp_to_code(table, temp); | 714 | tshut_value = rk_tsadcv2_temp_to_code(table, temp); |
676 | if (tshut_value == table.data_mask) | 715 | if (tshut_value == table->data_mask) |
677 | return; | 716 | return -ERANGE; |
678 | 717 | ||
679 | writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn)); | 718 | writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn)); |
680 | 719 | ||
681 | /* TSHUT will be valid */ | 720 | /* TSHUT will be valid */ |
682 | val = readl_relaxed(regs + TSADCV2_AUTO_CON); | 721 | val = readl_relaxed(regs + TSADCV2_AUTO_CON); |
683 | writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON); | 722 | writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON); |
723 | |||
724 | return 0; | ||
684 | } | 725 | } |
685 | 726 | ||
686 | static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, | 727 | static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, |
@@ -883,10 +924,8 @@ static int rockchip_thermal_set_trips(void *_sensor, int low, int high) | |||
883 | dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n", | 924 | dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n", |
884 | __func__, sensor->id, low, high); | 925 | __func__, sensor->id, low, high); |
885 | 926 | ||
886 | tsadc->set_alarm_temp(tsadc->table, | 927 | return tsadc->set_alarm_temp(&tsadc->table, |
887 | sensor->id, thermal->regs, high); | 928 | sensor->id, thermal->regs, high); |
888 | |||
889 | return 0; | ||
890 | } | 929 | } |
891 | 930 | ||
892 | static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) | 931 | static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) |
@@ -896,7 +935,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) | |||
896 | const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip; | 935 | const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip; |
897 | int retval; | 936 | int retval; |
898 | 937 | ||
899 | retval = tsadc->get_temp(tsadc->table, | 938 | retval = tsadc->get_temp(&tsadc->table, |
900 | sensor->id, thermal->regs, out_temp); | 939 | sensor->id, thermal->regs, out_temp); |
901 | dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n", | 940 | dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n", |
902 | sensor->id, *out_temp, retval); | 941 | sensor->id, *out_temp, retval); |
@@ -982,8 +1021,12 @@ rockchip_thermal_register_sensor(struct platform_device *pdev, | |||
982 | int error; | 1021 | int error; |
983 | 1022 | ||
984 | tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode); | 1023 | tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode); |
985 | tsadc->set_tshut_temp(tsadc->table, id, thermal->regs, | 1024 | |
1025 | error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs, | ||
986 | thermal->tshut_temp); | 1026 | thermal->tshut_temp); |
1027 | if (error) | ||
1028 | dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n", | ||
1029 | __func__, thermal->tshut_temp, error); | ||
987 | 1030 | ||
988 | sensor->thermal = thermal; | 1031 | sensor->thermal = thermal; |
989 | sensor->id = id; | 1032 | sensor->id = id; |
@@ -1196,9 +1239,13 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev) | |||
1196 | 1239 | ||
1197 | thermal->chip->set_tshut_mode(id, thermal->regs, | 1240 | thermal->chip->set_tshut_mode(id, thermal->regs, |
1198 | thermal->tshut_mode); | 1241 | thermal->tshut_mode); |
1199 | thermal->chip->set_tshut_temp(thermal->chip->table, | 1242 | |
1243 | error = thermal->chip->set_tshut_temp(&thermal->chip->table, | ||
1200 | id, thermal->regs, | 1244 | id, thermal->regs, |
1201 | thermal->tshut_temp); | 1245 | thermal->tshut_temp); |
1246 | if (error) | ||
1247 | dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n", | ||
1248 | __func__, thermal->tshut_temp, error); | ||
1202 | } | 1249 | } |
1203 | 1250 | ||
1204 | thermal->chip->control(thermal->regs, true); | 1251 | thermal->chip->control(thermal->regs, true); |