^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * TI Bandgap temperature sensor driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: J Keerthy <j-keerthy@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Moiz Sonasath <m-sonasath@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Couple of fixes, DT and MFD adaptation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Eduardo Valentin <eduardo.valentin@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/sys_soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/cpu_pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include "ti-bandgap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static int ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int bandgap_omap_cpu_notifier(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned long cmd, void *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*** Helper functions to access registers and their bitfields ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * ti_bandgap_readl() - simple read helper function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @bgp: pointer to ti_bandgap structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @reg: desired register (offset) to be read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Helper function to read bandgap registers. It uses the io remapped area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * Return: the register value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static u32 ti_bandgap_readl(struct ti_bandgap *bgp, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return readl(bgp->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * ti_bandgap_writel() - simple write helper function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * @bgp: pointer to ti_bandgap structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * @val: desired register value to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * @reg: desired register (offset) to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Helper function to write bandgap registers. It uses the io remapped area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void ti_bandgap_writel(struct ti_bandgap *bgp, u32 val, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) writel(val, bgp->base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * DOC: macro to update bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * RMW_BITS() - used to read, modify and update bandgap bitfields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * The value passed will be shifted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define RMW_BITS(bgp, id, reg, mask, val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct temp_sensor_registers *t; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u32 r; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) t = bgp->conf->sensors[(id)].registers; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) r = ti_bandgap_readl(bgp, t->reg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) r &= ~t->mask; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) r |= (val) << __ffs(t->mask); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ti_bandgap_writel(bgp, r, t->reg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*** Basic helper functions ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * ti_bandgap_power() - controls the power state of a bandgap device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @bgp: pointer to ti_bandgap structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @on: desired power state (1 - on, 0 - off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Used to power on/off a bandgap device instance. Only used on those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * that features tempsoff bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Return: 0 on success, -ENOTSUPP if tempsoff is not supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int ti_bandgap_power(struct ti_bandgap *bgp, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) for (i = 0; i < bgp->conf->sensor_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* active on 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) RMW_BITS(bgp, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * ti_errata814_bandgap_read_temp() - helper function to read dra7 sensor temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @bgp: pointer to ti_bandgap structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @reg: desired register (offset) to be read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * Function to read dra7 bandgap sensor temperature. This is done separately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * so as to workaround the errata "Bandgap Temperature read Dtemp can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * corrupted" - Errata ID: i814".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Read accesses to registers listed below can be corrupted due to incorrect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * resynchronization between clock domains.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * Read access to registers below can be corrupted :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * CTRL_CORE_DTEMP_MPU/GPU/CORE/DSPEVE/IVA_n (n = 0 to 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * CTRL_CORE_TEMP_SENSOR_MPU/GPU/CORE/DSPEVE/IVA_n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * Return: the register value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static u32 ti_errata814_bandgap_read_temp(struct ti_bandgap *bgp, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u32 val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) val1 = ti_bandgap_readl(bgp, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) val2 = ti_bandgap_readl(bgp, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* If both times we read the same value then that is right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (val1 == val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* if val1 and val2 are different read it third time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return ti_bandgap_readl(bgp, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * ti_bandgap_read_temp() - helper function to read sensor temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @bgp: pointer to ti_bandgap structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * @id: bandgap sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * Function to concentrate the steps to read sensor temperature register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * This function is desired because, depending on bandgap device version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * it might be needed to freeze the bandgap state machine, before fetching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * the register value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * Return: temperature in ADC values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u32 temp, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) tsr = bgp->conf->sensors[id].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) reg = tsr->temp_sensor_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * In case we cannot read from cur_dtemp / dtemp_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * then we read from the last valid temp read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) reg = tsr->ctrl_dtemp_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* read temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (TI_BANDGAP_HAS(bgp, ERRATA_814))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) temp = ti_errata814_bandgap_read_temp(bgp, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) temp = ti_bandgap_readl(bgp, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) temp &= tsr->bgap_dtemp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (TI_BANDGAP_HAS(bgp, FREEZE_BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*** IRQ handlers ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * ti_bandgap_talert_irq_handler() - handles Temperature alert IRQs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * @irq: IRQ number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * @data: private data (struct ti_bandgap *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * This is the Talert handler. Use it only if bandgap device features
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * HAS(TALERT). This handler goes over all sensors and checks their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * conditions and acts accordingly. In case there are events pending,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * it will reset the event mask to wait for the opposite event (next event).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * Every time there is a new event, it will be reported to thermal layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * Return: IRQ_HANDLED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static irqreturn_t ti_bandgap_talert_irq_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct ti_bandgap *bgp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u32 t_hot = 0, t_cold = 0, ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) spin_lock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (i = 0; i < bgp->conf->sensor_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) tsr = bgp->conf->sensors[i].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ctrl = ti_bandgap_readl(bgp, tsr->bgap_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* Read the status of t_hot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) t_hot = ctrl & tsr->status_hot_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* Read the status of t_cold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) t_cold = ctrl & tsr->status_cold_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!t_cold && !t_hot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * One TALERT interrupt: Two sources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * If the interrupt is due to t_hot then mask t_hot and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * and unmask t_cold else mask t_cold and unmask t_hot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (t_hot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ctrl &= ~tsr->mask_hot_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ctrl |= tsr->mask_cold_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) } else if (t_cold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ctrl &= ~tsr->mask_cold_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ctrl |= tsr->mask_hot_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) dev_dbg(bgp->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) "%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) __func__, bgp->conf->sensors[i].domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) t_hot, t_cold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* report temperature to whom may concern */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (bgp->conf->report_temperature)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) bgp->conf->report_temperature(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) spin_unlock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * ti_bandgap_tshut_irq_handler() - handles Temperature shutdown signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * @irq: IRQ number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * @data: private data (unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * This is the Tshut handler. Use it only if bandgap device features
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * HAS(TSHUT). If any sensor fires the Tshut signal, we simply shutdown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * the system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * Return: IRQ_HANDLED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static irqreturn_t ti_bandgap_tshut_irq_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) orderly_poweroff(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /*** Helper functions which manipulate conversion ADC <-> mi Celsius ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * ti_bandgap_adc_to_mcelsius() - converts an ADC value to mCelsius scale
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * @bgp: struct ti_bandgap pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * @adc_val: value in ADC representation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * @t: address where to write the resulting temperature in mCelsius
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * Simple conversion from ADC representation to mCelsius. In case the ADC value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * The conversion table is indexed by the ADC values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * Return: 0 if conversion was successful, else -ERANGE in case the @adc_val
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * argument is out of the ADC conv table range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) const struct ti_bandgap_data *conf = bgp->conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* look up for temperature in the table and return the temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) *t = bgp->conf->conv_table[adc_val - conf->adc_start_val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * ti_bandgap_validate() - helper to check the sanity of a struct ti_bandgap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * @bgp: struct ti_bandgap pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * @id: bandgap sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Checks if the bandgap pointer is valid and if the sensor id is also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * applicable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * Return: 0 if no errors, -EINVAL for invalid @bgp pointer or -ERANGE if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * @id cannot index @bgp sensors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!bgp || IS_ERR(bgp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) pr_err("%s: invalid bandgap pointer\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if ((id < 0) || (id >= bgp->conf->sensor_count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) dev_err(bgp->dev, "%s: sensor id out of range (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) __func__, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * ti_bandgap_read_counter() - read the sensor counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * @interval: resulting update interval in miliseconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static void ti_bandgap_read_counter(struct ti_bandgap *bgp, int id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int *interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) tsr = bgp->conf->sensors[id].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) time = ti_bandgap_readl(bgp, tsr->bgap_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) time = (time & tsr->counter_mask) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) __ffs(tsr->counter_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) time = time * 1000 / bgp->clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) *interval = time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * ti_bandgap_read_counter_delay() - read the sensor counter delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * @interval: resulting update interval in miliseconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static void ti_bandgap_read_counter_delay(struct ti_bandgap *bgp, int id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int *interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) tsr = bgp->conf->sensors[id].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) reg_val = (reg_val & tsr->mask_counter_delay_mask) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) __ffs(tsr->mask_counter_delay_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) switch (reg_val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) *interval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) *interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) *interval = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *interval = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) *interval = 250;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) *interval = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) dev_warn(bgp->dev, "Wrong counter delay value read from register %X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * ti_bandgap_read_update_interval() - read the sensor update interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * @interval: resulting update interval in miliseconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * Return: 0 on success or the proper error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int *interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ret = ti_bandgap_validate(bgp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (TI_BANDGAP_HAS(bgp, COUNTER)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ti_bandgap_read_counter(bgp, id, interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) ti_bandgap_read_counter_delay(bgp, id, interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * ti_bandgap_write_counter_delay() - set the counter_delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * @interval: desired update interval in miliseconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * Return: 0 on success or the proper error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static int ti_bandgap_write_counter_delay(struct ti_bandgap *bgp, int id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) u32 interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) switch (interval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) case 0: /* Immediate conversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rval = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) case 1: /* Conversion after ever 1ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) rval = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case 10: /* Conversion after ever 10ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) rval = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) case 100: /* Conversion after ever 100ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) rval = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) case 250: /* Conversion after ever 250ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) rval = 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) case 500: /* Conversion after ever 500ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) rval = 0x5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) dev_warn(bgp->dev, "Delay %d ms is not supported\n", interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) spin_lock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) RMW_BITS(bgp, id, bgap_mask_ctrl, mask_counter_delay_mask, rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) spin_unlock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * ti_bandgap_write_counter() - set the bandgap sensor counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * @interval: desired update interval in miliseconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static void ti_bandgap_write_counter(struct ti_bandgap *bgp, int id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) u32 interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) interval = interval * bgp->clk_rate / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) spin_lock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) RMW_BITS(bgp, id, bgap_counter, counter_mask, interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) spin_unlock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * ti_bandgap_write_update_interval() - set the update interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * @interval: desired update interval in miliseconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * Return: 0 on success or the proper error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int ti_bandgap_write_update_interval(struct ti_bandgap *bgp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int id, u32 interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int ret = ti_bandgap_validate(bgp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (TI_BANDGAP_HAS(bgp, COUNTER)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ti_bandgap_write_counter(bgp, id, interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) ret = ti_bandgap_write_counter_delay(bgp, id, interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * ti_bandgap_read_temperature() - report current temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * @temperature: resulting temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * Return: 0 on success or the proper error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) int *temperature)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ret = ti_bandgap_validate(bgp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (!TI_BANDGAP_HAS(bgp, MODE_CONFIG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ret = ti_bandgap_force_single_read(bgp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) spin_lock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) temp = ti_bandgap_read_temp(bgp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) spin_unlock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ret = ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) *temperature = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * ti_bandgap_set_sensor_data() - helper function to store thermal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * framework related data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * @data: thermal framework related data to be stored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * Return: 0 on success or the proper error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) int ret = ti_bandgap_validate(bgp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) bgp->regval[id].data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * ti_bandgap_get_sensor_data() - helper function to get thermal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * framework related data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * @bgp: pointer to bandgap instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * @id: sensor id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * Return: data stored by set function with sensor id on success or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) int ret = ti_bandgap_validate(bgp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return bgp->regval[id].data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /*** Helper functions used during device initialization ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * ti_bandgap_force_single_read() - executes 1 single ADC conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * @bgp: pointer to struct ti_bandgap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * @id: sensor id which it is desired to read 1 temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * Used to initialize the conversion state machine and set it to a valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * state. Called during device initialization and context restore events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * Return: 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) u32 counter = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* Select single conversion mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) RMW_BITS(bgp, id, bgap_mode_ctrl, mode_ctrl_mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* Start of Conversion = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /* Wait for EOCZ going up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) tsr = bgp->conf->sensors[id].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) while (--counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (ti_bandgap_readl(bgp, tsr->temp_sensor_ctrl) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) tsr->bgap_eocz_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /* Start of Conversion = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /* Wait for EOCZ going down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) counter = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) while (--counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (!(ti_bandgap_readl(bgp, tsr->temp_sensor_ctrl) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) tsr->bgap_eocz_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * ti_bandgap_set_continuous_mode() - One time enabling of continuous mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * @bgp: pointer to struct ti_bandgap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * Call this function only if HAS(MODE_CONFIG) is set. As this driver may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * be used for junction temperature monitoring, it is desirable that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * sensors are operational all the time, so that alerts are generated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * Return: 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static int ti_bandgap_set_continuous_mode(struct ti_bandgap *bgp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) for (i = 0; i < bgp->conf->sensor_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* Perform a single read just before enabling continuous */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ti_bandgap_force_single_read(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) RMW_BITS(bgp, i, bgap_mode_ctrl, mode_ctrl_mask, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * ti_bandgap_get_trend() - To fetch the temperature trend of a sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * @bgp: pointer to struct ti_bandgap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * @id: id of the individual sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * @trend: Pointer to trend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * This function needs to be called to fetch the temperature trend of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * Particular sensor. The function computes the difference in temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * w.r.t time. For the bandgaps with built in history buffer the temperatures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * are read from the buffer and for those without the Buffer -ENOTSUPP is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * Return: 0 if no error, else return corresponding error. If no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * error then the trend value is passed on to trend parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) u32 temp1, temp2, reg1, reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) int t1, t2, interval, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ret = ti_bandgap_validate(bgp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (!TI_BANDGAP_HAS(bgp, HISTORY_BUFFER) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) !TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) spin_lock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) tsr = bgp->conf->sensors[id].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* Freeze and read the last 2 valid readings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) reg1 = tsr->ctrl_dtemp_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) reg2 = tsr->ctrl_dtemp_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* read temperature from history buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) temp1 = ti_bandgap_readl(bgp, reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) temp1 &= tsr->bgap_dtemp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) temp2 = ti_bandgap_readl(bgp, reg2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) temp2 &= tsr->bgap_dtemp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* Convert from adc values to mCelsius temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto unfreeze;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) goto unfreeze;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /* Fetch the update interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) ret = ti_bandgap_read_update_interval(bgp, id, &interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) goto unfreeze;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /* Set the interval to 1 ms if bandgap counter delay is not set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (interval == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) *trend = (t1 - t2) / interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) t1, t2, *trend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) unfreeze:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) spin_unlock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * ti_bandgap_tshut_init() - setup and initialize tshut handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * @bgp: pointer to struct ti_bandgap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * @pdev: pointer to device struct platform_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * Call this function only in case the bandgap features HAS(TSHUT).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * In this case, the driver needs to handle the TSHUT signal as an IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * The IRQ is wired as a GPIO, and for this purpose, it is required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * to specify which GPIO line is used. TSHUT IRQ is fired anytime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * one of the bandgap sensors violates the TSHUT high/hot threshold.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * And in that case, the system must go off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * Return: 0 if no error, else error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static int ti_bandgap_tshut_init(struct ti_bandgap *bgp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) status = request_irq(gpiod_to_irq(bgp->tshut_gpiod),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) ti_bandgap_tshut_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) IRQF_TRIGGER_RISING, "tshut", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) dev_err(bgp->dev, "request irq failed for TSHUT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * ti_bandgap_alert_init() - setup and initialize talert handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * @bgp: pointer to struct ti_bandgap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * @pdev: pointer to device struct platform_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * Call this function only in case the bandgap features HAS(TALERT).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * In this case, the driver needs to handle the TALERT signals as an IRQs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * TALERT is a normal IRQ and it is fired any time thresholds (hot or cold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * are violated. In these situation, the driver must reprogram the thresholds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * accordingly to specified policy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * Return: 0 if no error, else return corresponding error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static int ti_bandgap_talert_init(struct ti_bandgap *bgp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) bgp->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (bgp->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return bgp->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ret = request_threaded_irq(bgp->irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) ti_bandgap_talert_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) "talert", bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) dev_err(&pdev->dev, "Request threaded irq failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static const struct of_device_id of_ti_bandgap_match[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * ti_bandgap_build() - parse DT and setup a struct ti_bandgap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * @pdev: pointer to device struct platform_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * Used to read the device tree properties accordingly to the bandgap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * matching version. Based on bandgap version and its capabilities it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * will build a struct ti_bandgap out of the required DT entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * Return: valid bandgap structure if successful, else returns ERR_PTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * return value must be verified with IS_ERR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct device_node *node = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) const struct of_device_id *of_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) struct ti_bandgap *bgp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) /* just for the sake */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (!node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dev_err(&pdev->dev, "no platform information available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (!bgp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) of_id = of_match_device(of_ti_bandgap_match, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (of_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) bgp->conf = of_id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* register shadow for context save and restore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) bgp->regval = devm_kcalloc(&pdev->dev, bgp->conf->sensor_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) sizeof(*bgp->regval), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (!bgp->regval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) void __iomem *chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) res = platform_get_resource(pdev, IORESOURCE_MEM, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) chunk = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (i == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) bgp->base = chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (IS_ERR(chunk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return ERR_CAST(chunk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) } while (res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (TI_BANDGAP_HAS(bgp, TSHUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) bgp->tshut_gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (IS_ERR(bgp->tshut_gpiod)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) dev_err(&pdev->dev, "invalid gpio for tshut\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return ERR_CAST(bgp->tshut_gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return bgp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * List of SoCs on which the CPU PM notifier can cause erros on the DTEMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * readout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * Enabled notifier on these machines results in erroneous, random values which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) * could trigger unexpected thermal shutdown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) static const struct soc_device_attribute soc_no_cpu_notifier[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) { .machine = "OMAP4430" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /*** Device driver call backs ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) int ti_bandgap_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct ti_bandgap *bgp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) int clk_rate, ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) bgp = ti_bandgap_build(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (IS_ERR(bgp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) dev_err(&pdev->dev, "failed to fetch platform data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return PTR_ERR(bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) bgp->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (TI_BANDGAP_HAS(bgp, UNRELIABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) "This OMAP thermal sensor is unreliable. You've been warned\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (TI_BANDGAP_HAS(bgp, TSHUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) ret = ti_bandgap_tshut_init(bgp, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) "failed to initialize system tshut IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) bgp->fclock = clk_get(NULL, bgp->conf->fclock_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (IS_ERR(bgp->fclock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) dev_err(&pdev->dev, "failed to request fclock reference\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) ret = PTR_ERR(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) goto free_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (IS_ERR(bgp->div_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) dev_err(&pdev->dev, "failed to request div_ts_ck clock ref\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ret = PTR_ERR(bgp->div_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) goto put_fclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) for (i = 0; i < bgp->conf->sensor_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) tsr = bgp->conf->sensors[i].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * check if the efuse has a non-zero value if not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * it is an untrimmed sample and the temperatures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * may not be accurate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) val = ti_bandgap_readl(bgp, tsr->bgap_efuse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) dev_info(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) "Non-trimmed BGAP, Temp not accurate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) clk_rate = clk_round_rate(bgp->div_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) bgp->conf->sensors[0].ts_data->max_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (clk_rate < bgp->conf->sensors[0].ts_data->min_freq ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) clk_rate <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) goto put_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ret = clk_set_rate(bgp->div_clk, clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) bgp->clk_rate = clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) clk_prepare_enable(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) spin_lock_init(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) bgp->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) platform_set_drvdata(pdev, bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) ti_bandgap_power(bgp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /* Set default counter to 1 for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (TI_BANDGAP_HAS(bgp, COUNTER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) for (i = 0; i < bgp->conf->sensor_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) RMW_BITS(bgp, i, bgap_counter, counter_mask, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /* Set default thresholds for alert and shutdown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) for (i = 0; i < bgp->conf->sensor_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct temp_sensor_data *ts_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) ts_data = bgp->conf->sensors[i].ts_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (TI_BANDGAP_HAS(bgp, TALERT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* Set initial Talert thresholds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) RMW_BITS(bgp, i, bgap_threshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) threshold_tcold_mask, ts_data->t_cold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) RMW_BITS(bgp, i, bgap_threshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) threshold_thot_mask, ts_data->t_hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /* Enable the alert events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) RMW_BITS(bgp, i, bgap_mask_ctrl, mask_hot_mask, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) RMW_BITS(bgp, i, bgap_mask_ctrl, mask_cold_mask, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /* Set initial Tshut thresholds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) RMW_BITS(bgp, i, tshut_threshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) tshut_hot_mask, ts_data->tshut_hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) RMW_BITS(bgp, i, tshut_threshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) tshut_cold_mask, ts_data->tshut_cold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) ti_bandgap_set_continuous_mode(bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) /* Set .250 seconds time as default counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (TI_BANDGAP_HAS(bgp, COUNTER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) for (i = 0; i < bgp->conf->sensor_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) RMW_BITS(bgp, i, bgap_counter, counter_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) bgp->clk_rate / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /* Every thing is good? Then expose the sensors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) for (i = 0; i < bgp->conf->sensor_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) char *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (bgp->conf->sensors[i].register_cooling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) ret = bgp->conf->sensors[i].register_cooling(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) goto remove_sensors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (bgp->conf->expose_sensor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) domain = bgp->conf->sensors[i].domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) ret = bgp->conf->expose_sensor(bgp, i, domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) goto remove_last_cooling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) * Enable the Interrupts once everything is set. Otherwise irq handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * might be called as soon as it is enabled where as rest of framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * is still getting initialised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (TI_BANDGAP_HAS(bgp, TALERT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) ret = ti_bandgap_talert_init(bgp, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) i = bgp->conf->sensor_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) goto disable_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) bgp->nb.notifier_call = bandgap_omap_cpu_notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (!soc_device_match(soc_no_cpu_notifier))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) cpu_pm_register_notifier(&bgp->nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) remove_last_cooling:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (bgp->conf->sensors[i].unregister_cooling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) bgp->conf->sensors[i].unregister_cooling(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) remove_sensors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) for (i--; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (bgp->conf->sensors[i].unregister_cooling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) bgp->conf->sensors[i].unregister_cooling(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (bgp->conf->remove_sensor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) bgp->conf->remove_sensor(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) ti_bandgap_power(bgp, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) disable_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) clk_disable_unprepare(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) put_clks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) clk_put(bgp->div_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) put_fclock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) clk_put(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) free_irqs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (TI_BANDGAP_HAS(bgp, TSHUT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) int ti_bandgap_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct ti_bandgap *bgp = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (!soc_device_match(soc_no_cpu_notifier))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) cpu_pm_unregister_notifier(&bgp->nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) /* Remove sensor interfaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) for (i = 0; i < bgp->conf->sensor_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (bgp->conf->sensors[i].unregister_cooling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) bgp->conf->sensors[i].unregister_cooling(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (bgp->conf->remove_sensor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) bgp->conf->remove_sensor(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) ti_bandgap_power(bgp, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) clk_disable_unprepare(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) clk_put(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) clk_put(bgp->div_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (TI_BANDGAP_HAS(bgp, TALERT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) free_irq(bgp->irq, bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (TI_BANDGAP_HAS(bgp, TSHUT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) static int ti_bandgap_save_ctxt(struct ti_bandgap *bgp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) for (i = 0; i < bgp->conf->sensor_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct temp_sensor_regval *rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) rval = &bgp->regval[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) tsr = bgp->conf->sensors[i].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) rval->bg_mode_ctrl = ti_bandgap_readl(bgp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) tsr->bgap_mode_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (TI_BANDGAP_HAS(bgp, COUNTER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) rval->bg_counter = ti_bandgap_readl(bgp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) tsr->bgap_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (TI_BANDGAP_HAS(bgp, TALERT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) rval->bg_threshold = ti_bandgap_readl(bgp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) tsr->bgap_threshold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) rval->bg_ctrl = ti_bandgap_readl(bgp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) tsr->bgap_mask_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) rval->tshut_threshold = ti_bandgap_readl(bgp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) tsr->tshut_threshold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) static int ti_bandgap_restore_ctxt(struct ti_bandgap *bgp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) for (i = 0; i < bgp->conf->sensor_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct temp_sensor_registers *tsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct temp_sensor_regval *rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) u32 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) rval = &bgp->regval[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) tsr = bgp->conf->sensors[i].registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (TI_BANDGAP_HAS(bgp, COUNTER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) val = ti_bandgap_readl(bgp, tsr->bgap_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) ti_bandgap_writel(bgp, rval->tshut_threshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) tsr->tshut_threshold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /* Force immediate temperature measurement and update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) * of the DTEMP field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) ti_bandgap_force_single_read(bgp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (TI_BANDGAP_HAS(bgp, COUNTER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) ti_bandgap_writel(bgp, rval->bg_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) tsr->bgap_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ti_bandgap_writel(bgp, rval->bg_mode_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) tsr->bgap_mode_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (TI_BANDGAP_HAS(bgp, TALERT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) ti_bandgap_writel(bgp, rval->bg_threshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) tsr->bgap_threshold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) ti_bandgap_writel(bgp, rval->bg_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) tsr->bgap_mask_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) static int ti_bandgap_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) struct ti_bandgap *bgp = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) err = ti_bandgap_save_ctxt(bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ti_bandgap_power(bgp, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) clk_disable_unprepare(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) bgp->is_suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static int bandgap_omap_cpu_notifier(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) unsigned long cmd, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct ti_bandgap *bgp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) bgp = container_of(nb, struct ti_bandgap, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) spin_lock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) case CPU_CLUSTER_PM_ENTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (bgp->is_suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ti_bandgap_save_ctxt(bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) ti_bandgap_power(bgp, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) clk_disable(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) case CPU_CLUSTER_PM_ENTER_FAILED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) case CPU_CLUSTER_PM_EXIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (bgp->is_suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) clk_enable(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) ti_bandgap_power(bgp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) ti_bandgap_restore_ctxt(bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) spin_unlock(&bgp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) static int ti_bandgap_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) struct ti_bandgap *bgp = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) clk_prepare_enable(bgp->fclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ti_bandgap_power(bgp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) bgp->is_suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return ti_bandgap_restore_ctxt(bgp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) static SIMPLE_DEV_PM_OPS(ti_bandgap_dev_pm_ops, ti_bandgap_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) ti_bandgap_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) #define DEV_PM_OPS (&ti_bandgap_dev_pm_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) #define DEV_PM_OPS NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) static const struct of_device_id of_ti_bandgap_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) #ifdef CONFIG_OMAP3_THERMAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) .compatible = "ti,omap34xx-bandgap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) .data = (void *)&omap34xx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) .compatible = "ti,omap36xx-bandgap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) .data = (void *)&omap36xx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) #ifdef CONFIG_OMAP4_THERMAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) .compatible = "ti,omap4430-bandgap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) .data = (void *)&omap4430_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) .compatible = "ti,omap4460-bandgap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) .data = (void *)&omap4460_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) .compatible = "ti,omap4470-bandgap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) .data = (void *)&omap4470_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) #ifdef CONFIG_OMAP5_THERMAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) .compatible = "ti,omap5430-bandgap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) .data = (void *)&omap5430_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) #ifdef CONFIG_DRA752_THERMAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) .compatible = "ti,dra752-bandgap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) .data = (void *)&dra752_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) /* Sentinel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) MODULE_DEVICE_TABLE(of, of_ti_bandgap_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) static struct platform_driver ti_bandgap_sensor_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) .probe = ti_bandgap_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) .remove = ti_bandgap_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) .name = "ti-soc-thermal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) .pm = DEV_PM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) .of_match_table = of_ti_bandgap_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) module_platform_driver(ti_bandgap_sensor_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) MODULE_ALIAS("platform:ti-soc-thermal");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) MODULE_AUTHOR("Texas Instrument Inc.");