123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- /*
- * Copyright (C) 2018 Marvell International Ltd.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- * https://spdx.org/licenses
- */
- #include <common/debug.h>
- #include <drivers/delay_timer.h>
- #include <drivers/marvell/thermal.h>
- #include <lib/mmio.h>
- #include <mvebu_def.h>
- #define THERMAL_TIMEOUT 1200
- #define THERMAL_SEN_CTRL_LSB_STRT_OFFSET 0
- #define THERMAL_SEN_CTRL_LSB_STRT_MASK \
- (0x1 << THERMAL_SEN_CTRL_LSB_STRT_OFFSET)
- #define THERMAL_SEN_CTRL_LSB_RST_OFFSET 1
- #define THERMAL_SEN_CTRL_LSB_RST_MASK \
- (0x1 << THERMAL_SEN_CTRL_LSB_RST_OFFSET)
- #define THERMAL_SEN_CTRL_LSB_EN_OFFSET 2
- #define THERMAL_SEN_CTRL_LSB_EN_MASK \
- (0x1 << THERMAL_SEN_CTRL_LSB_EN_OFFSET)
- #define THERMAL_SEN_CTRL_STATS_VALID_OFFSET 16
- #define THERMAL_SEN_CTRL_STATS_VALID_MASK \
- (0x1 << THERMAL_SEN_CTRL_STATS_VALID_OFFSET)
- #define THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET 0
- #define THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK \
- (0x3FF << THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET)
- #define THERMAL_SEN_OUTPUT_MSB 512
- #define THERMAL_SEN_OUTPUT_COMP 1024
- struct tsen_regs {
- uint32_t ext_tsen_ctrl_lsb;
- uint32_t ext_tsen_ctrl_msb;
- uint32_t ext_tsen_status;
- };
- static int ext_tsen_probe(struct tsen_config *tsen_cfg)
- {
- uint32_t reg, timeout = 0;
- struct tsen_regs *base;
- if (tsen_cfg == NULL && tsen_cfg->regs_base == NULL) {
- ERROR("initial thermal sensor configuration is missing\n");
- return -1;
- }
- base = (struct tsen_regs *)tsen_cfg->regs_base;
- INFO("initializing thermal sensor\n");
- /* initialize thermal sensor hardware reset once */
- reg = mmio_read_32((uintptr_t)&base->ext_tsen_ctrl_lsb);
- reg &= ~THERMAL_SEN_CTRL_LSB_RST_OFFSET; /* de-assert TSEN_RESET */
- reg |= THERMAL_SEN_CTRL_LSB_EN_MASK; /* set TSEN_EN to 1 */
- reg |= THERMAL_SEN_CTRL_LSB_STRT_MASK; /* set TSEN_START to 1 */
- mmio_write_32((uintptr_t)&base->ext_tsen_ctrl_lsb, reg);
- reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
- while ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0 &&
- timeout < THERMAL_TIMEOUT) {
- udelay(100);
- reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
- timeout++;
- }
- if ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0) {
- ERROR("thermal sensor is not ready\n");
- return -1;
- }
- tsen_cfg->tsen_ready = 1;
- VERBOSE("thermal sensor was initialized\n");
- return 0;
- }
- static int ext_tsen_read(struct tsen_config *tsen_cfg, int *temp)
- {
- uint32_t reg;
- struct tsen_regs *base;
- if (tsen_cfg == NULL && !tsen_cfg->tsen_ready) {
- ERROR("thermal sensor was not initialized\n");
- return -1;
- }
- base = (struct tsen_regs *)tsen_cfg->regs_base;
- reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
- reg = ((reg & THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK) >>
- THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET);
- /*
- * TSEN output format is signed as a 2s complement number
- * ranging from-512 to +511. when MSB is set, need to
- * calculate the complement number
- */
- if (reg >= THERMAL_SEN_OUTPUT_MSB)
- reg -= THERMAL_SEN_OUTPUT_COMP;
- if (tsen_cfg->tsen_divisor == 0) {
- ERROR("thermal sensor divisor cannot be zero\n");
- return -1;
- }
- *temp = ((tsen_cfg->tsen_gain * ((int)reg)) +
- tsen_cfg->tsen_offset) / tsen_cfg->tsen_divisor;
- return 0;
- }
- static struct tsen_config tsen_cfg = {
- .tsen_offset = 153400,
- .tsen_gain = 425,
- .tsen_divisor = 1000,
- .tsen_ready = 0,
- .regs_base = (void *)MVEBU_AP_EXT_TSEN_BASE,
- .ptr_tsen_probe = ext_tsen_probe,
- .ptr_tsen_read = ext_tsen_read
- };
- struct tsen_config *marvell_thermal_config_get(void)
- {
- return &tsen_cfg;
- }
|