plat_thermal.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * Copyright (C) 2018 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. * https://spdx.org/licenses
  6. */
  7. #include <common/debug.h>
  8. #include <drivers/delay_timer.h>
  9. #include <drivers/marvell/thermal.h>
  10. #include <lib/mmio.h>
  11. #include <mvebu_def.h>
  12. #define THERMAL_TIMEOUT 1200
  13. #define THERMAL_SEN_CTRL_LSB_STRT_OFFSET 0
  14. #define THERMAL_SEN_CTRL_LSB_STRT_MASK \
  15. (0x1 << THERMAL_SEN_CTRL_LSB_STRT_OFFSET)
  16. #define THERMAL_SEN_CTRL_LSB_RST_OFFSET 1
  17. #define THERMAL_SEN_CTRL_LSB_RST_MASK \
  18. (0x1 << THERMAL_SEN_CTRL_LSB_RST_OFFSET)
  19. #define THERMAL_SEN_CTRL_LSB_EN_OFFSET 2
  20. #define THERMAL_SEN_CTRL_LSB_EN_MASK \
  21. (0x1 << THERMAL_SEN_CTRL_LSB_EN_OFFSET)
  22. #define THERMAL_SEN_CTRL_STATS_VALID_OFFSET 16
  23. #define THERMAL_SEN_CTRL_STATS_VALID_MASK \
  24. (0x1 << THERMAL_SEN_CTRL_STATS_VALID_OFFSET)
  25. #define THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET 0
  26. #define THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK \
  27. (0x3FF << THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET)
  28. #define THERMAL_SEN_OUTPUT_MSB 512
  29. #define THERMAL_SEN_OUTPUT_COMP 1024
  30. struct tsen_regs {
  31. uint32_t ext_tsen_ctrl_lsb;
  32. uint32_t ext_tsen_ctrl_msb;
  33. uint32_t ext_tsen_status;
  34. };
  35. static int ext_tsen_probe(struct tsen_config *tsen_cfg)
  36. {
  37. uint32_t reg, timeout = 0;
  38. struct tsen_regs *base;
  39. if (tsen_cfg == NULL && tsen_cfg->regs_base == NULL) {
  40. ERROR("initial thermal sensor configuration is missing\n");
  41. return -1;
  42. }
  43. base = (struct tsen_regs *)tsen_cfg->regs_base;
  44. INFO("initializing thermal sensor\n");
  45. /* initialize thermal sensor hardware reset once */
  46. reg = mmio_read_32((uintptr_t)&base->ext_tsen_ctrl_lsb);
  47. reg &= ~THERMAL_SEN_CTRL_LSB_RST_OFFSET; /* de-assert TSEN_RESET */
  48. reg |= THERMAL_SEN_CTRL_LSB_EN_MASK; /* set TSEN_EN to 1 */
  49. reg |= THERMAL_SEN_CTRL_LSB_STRT_MASK; /* set TSEN_START to 1 */
  50. mmio_write_32((uintptr_t)&base->ext_tsen_ctrl_lsb, reg);
  51. reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
  52. while ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0 &&
  53. timeout < THERMAL_TIMEOUT) {
  54. udelay(100);
  55. reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
  56. timeout++;
  57. }
  58. if ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0) {
  59. ERROR("thermal sensor is not ready\n");
  60. return -1;
  61. }
  62. tsen_cfg->tsen_ready = 1;
  63. VERBOSE("thermal sensor was initialized\n");
  64. return 0;
  65. }
  66. static int ext_tsen_read(struct tsen_config *tsen_cfg, int *temp)
  67. {
  68. uint32_t reg;
  69. struct tsen_regs *base;
  70. if (tsen_cfg == NULL && !tsen_cfg->tsen_ready) {
  71. ERROR("thermal sensor was not initialized\n");
  72. return -1;
  73. }
  74. base = (struct tsen_regs *)tsen_cfg->regs_base;
  75. reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
  76. reg = ((reg & THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK) >>
  77. THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET);
  78. /*
  79. * TSEN output format is signed as a 2s complement number
  80. * ranging from-512 to +511. when MSB is set, need to
  81. * calculate the complement number
  82. */
  83. if (reg >= THERMAL_SEN_OUTPUT_MSB)
  84. reg -= THERMAL_SEN_OUTPUT_COMP;
  85. if (tsen_cfg->tsen_divisor == 0) {
  86. ERROR("thermal sensor divisor cannot be zero\n");
  87. return -1;
  88. }
  89. *temp = ((tsen_cfg->tsen_gain * ((int)reg)) +
  90. tsen_cfg->tsen_offset) / tsen_cfg->tsen_divisor;
  91. return 0;
  92. }
  93. static struct tsen_config tsen_cfg = {
  94. .tsen_offset = 153400,
  95. .tsen_gain = 425,
  96. .tsen_divisor = 1000,
  97. .tsen_ready = 0,
  98. .regs_base = (void *)MVEBU_AP_EXT_TSEN_BASE,
  99. .ptr_tsen_probe = ext_tsen_probe,
  100. .ptr_tsen_read = ext_tsen_read
  101. };
  102. struct tsen_config *marvell_thermal_config_get(void)
  103. {
  104. return &tsen_cfg;
  105. }