1eb982001SEduardo Valentin /* 2eb982001SEduardo Valentin * TI Bandgap temperature sensor driver 3eb982001SEduardo Valentin * 4eb982001SEduardo Valentin * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ 5eb982001SEduardo Valentin * Author: J Keerthy <j-keerthy@ti.com> 6eb982001SEduardo Valentin * Author: Moiz Sonasath <m-sonasath@ti.com> 7eb982001SEduardo Valentin * Couple of fixes, DT and MFD adaptation: 8eb982001SEduardo Valentin * Eduardo Valentin <eduardo.valentin@ti.com> 9eb982001SEduardo Valentin * 10eb982001SEduardo Valentin * This program is free software; you can redistribute it and/or 11eb982001SEduardo Valentin * modify it under the terms of the GNU General Public License 12eb982001SEduardo Valentin * version 2 as published by the Free Software Foundation. 13eb982001SEduardo Valentin * 14eb982001SEduardo Valentin * This program is distributed in the hope that it will be useful, but 15eb982001SEduardo Valentin * WITHOUT ANY WARRANTY; without even the implied warranty of 16eb982001SEduardo Valentin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17eb982001SEduardo Valentin * General Public License for more details. 18eb982001SEduardo Valentin * 19eb982001SEduardo Valentin * You should have received a copy of the GNU General Public License 20eb982001SEduardo Valentin * along with this program; if not, write to the Free Software 21eb982001SEduardo Valentin * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22eb982001SEduardo Valentin * 02110-1301 USA 23eb982001SEduardo Valentin * 24eb982001SEduardo Valentin */ 25eb982001SEduardo Valentin 26eb982001SEduardo Valentin #include <linux/module.h> 27eb982001SEduardo Valentin #include <linux/export.h> 28eb982001SEduardo Valentin #include <linux/init.h> 29eb982001SEduardo Valentin #include <linux/kernel.h> 30eb982001SEduardo Valentin #include <linux/interrupt.h> 31eb982001SEduardo Valentin #include <linux/clk.h> 32eb982001SEduardo Valentin #include <linux/gpio.h> 33eb982001SEduardo Valentin #include <linux/platform_device.h> 34eb982001SEduardo Valentin #include <linux/err.h> 35eb982001SEduardo Valentin #include <linux/types.h> 36eb982001SEduardo Valentin #include <linux/spinlock.h> 37eb982001SEduardo Valentin #include <linux/reboot.h> 38eb982001SEduardo Valentin #include <linux/of_device.h> 39eb982001SEduardo Valentin #include <linux/of_platform.h> 40eb982001SEduardo Valentin #include <linux/of_irq.h> 4157d16171SEduardo Valentin #include <linux/of_gpio.h> 42eb982001SEduardo Valentin #include <linux/io.h> 43eb982001SEduardo Valentin 44eb982001SEduardo Valentin #include "ti-bandgap.h" 45eb982001SEduardo Valentin 46eb982001SEduardo Valentin /*** Helper functions to access registers and their bitfields ***/ 47eb982001SEduardo Valentin 48eb982001SEduardo Valentin /** 49eb982001SEduardo Valentin * ti_bandgap_readl() - simple read helper function 50eb982001SEduardo Valentin * @bgp: pointer to ti_bandgap structure 51eb982001SEduardo Valentin * @reg: desired register (offset) to be read 52eb982001SEduardo Valentin * 53eb982001SEduardo Valentin * Helper function to read bandgap registers. It uses the io remapped area. 54eb982001SEduardo Valentin * Return: the register value. 55eb982001SEduardo Valentin */ 56eb982001SEduardo Valentin static u32 ti_bandgap_readl(struct ti_bandgap *bgp, u32 reg) 57eb982001SEduardo Valentin { 58eb982001SEduardo Valentin return readl(bgp->base + reg); 59eb982001SEduardo Valentin } 60eb982001SEduardo Valentin 61eb982001SEduardo Valentin /** 62eb982001SEduardo Valentin * ti_bandgap_writel() - simple write helper function 63eb982001SEduardo Valentin * @bgp: pointer to ti_bandgap structure 64eb982001SEduardo Valentin * @val: desired register value to be written 65eb982001SEduardo Valentin * @reg: desired register (offset) to be written 66eb982001SEduardo Valentin * 67eb982001SEduardo Valentin * Helper function to write bandgap registers. It uses the io remapped area. 68eb982001SEduardo Valentin */ 69eb982001SEduardo Valentin static void ti_bandgap_writel(struct ti_bandgap *bgp, u32 val, u32 reg) 70eb982001SEduardo Valentin { 71eb982001SEduardo Valentin writel(val, bgp->base + reg); 72eb982001SEduardo Valentin } 73eb982001SEduardo Valentin 74eb982001SEduardo Valentin /** 75eb982001SEduardo Valentin * DOC: macro to update bits. 76eb982001SEduardo Valentin * 77eb982001SEduardo Valentin * RMW_BITS() - used to read, modify and update bandgap bitfields. 78eb982001SEduardo Valentin * The value passed will be shifted. 79eb982001SEduardo Valentin */ 80eb982001SEduardo Valentin #define RMW_BITS(bgp, id, reg, mask, val) \ 81eb982001SEduardo Valentin do { \ 82eb982001SEduardo Valentin struct temp_sensor_registers *t; \ 83eb982001SEduardo Valentin u32 r; \ 84eb982001SEduardo Valentin \ 85eb982001SEduardo Valentin t = bgp->conf->sensors[(id)].registers; \ 86eb982001SEduardo Valentin r = ti_bandgap_readl(bgp, t->reg); \ 87eb982001SEduardo Valentin r &= ~t->mask; \ 88eb982001SEduardo Valentin r |= (val) << __ffs(t->mask); \ 89eb982001SEduardo Valentin ti_bandgap_writel(bgp, r, t->reg); \ 90eb982001SEduardo Valentin } while (0) 91eb982001SEduardo Valentin 92eb982001SEduardo Valentin /*** Basic helper functions ***/ 93eb982001SEduardo Valentin 94eb982001SEduardo Valentin /** 95eb982001SEduardo Valentin * ti_bandgap_power() - controls the power state of a bandgap device 96eb982001SEduardo Valentin * @bgp: pointer to ti_bandgap structure 97eb982001SEduardo Valentin * @on: desired power state (1 - on, 0 - off) 98eb982001SEduardo Valentin * 99eb982001SEduardo Valentin * Used to power on/off a bandgap device instance. Only used on those 100eb982001SEduardo Valentin * that features tempsoff bit. 101eb982001SEduardo Valentin * 102eb982001SEduardo Valentin * Return: 0 on success, -ENOTSUPP if tempsoff is not supported. 103eb982001SEduardo Valentin */ 104eb982001SEduardo Valentin static int ti_bandgap_power(struct ti_bandgap *bgp, bool on) 105eb982001SEduardo Valentin { 106eb982001SEduardo Valentin int i, ret = 0; 107eb982001SEduardo Valentin 108eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH)) { 109eb982001SEduardo Valentin ret = -ENOTSUPP; 110eb982001SEduardo Valentin goto exit; 111eb982001SEduardo Valentin } 112eb982001SEduardo Valentin 113eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) 114eb982001SEduardo Valentin /* active on 0 */ 115eb982001SEduardo Valentin RMW_BITS(bgp, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on); 116eb982001SEduardo Valentin 117eb982001SEduardo Valentin exit: 118eb982001SEduardo Valentin return ret; 119eb982001SEduardo Valentin } 120eb982001SEduardo Valentin 121eb982001SEduardo Valentin /** 122eb982001SEduardo Valentin * ti_bandgap_read_temp() - helper function to read sensor temperature 123eb982001SEduardo Valentin * @bgp: pointer to ti_bandgap structure 124eb982001SEduardo Valentin * @id: bandgap sensor id 125eb982001SEduardo Valentin * 126eb982001SEduardo Valentin * Function to concentrate the steps to read sensor temperature register. 127eb982001SEduardo Valentin * This function is desired because, depending on bandgap device version, 128eb982001SEduardo Valentin * it might be needed to freeze the bandgap state machine, before fetching 129eb982001SEduardo Valentin * the register value. 130eb982001SEduardo Valentin * 131eb982001SEduardo Valentin * Return: temperature in ADC values. 132eb982001SEduardo Valentin */ 133eb982001SEduardo Valentin static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id) 134eb982001SEduardo Valentin { 135eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 136eb982001SEduardo Valentin u32 temp, reg; 137eb982001SEduardo Valentin 138eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 139eb982001SEduardo Valentin reg = tsr->temp_sensor_ctrl; 140eb982001SEduardo Valentin 141eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) { 142eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1); 143eb982001SEduardo Valentin /* 144eb982001SEduardo Valentin * In case we cannot read from cur_dtemp / dtemp_0, 145eb982001SEduardo Valentin * then we read from the last valid temp read 146eb982001SEduardo Valentin */ 147eb982001SEduardo Valentin reg = tsr->ctrl_dtemp_1; 148eb982001SEduardo Valentin } 149eb982001SEduardo Valentin 150eb982001SEduardo Valentin /* read temperature */ 151eb982001SEduardo Valentin temp = ti_bandgap_readl(bgp, reg); 152eb982001SEduardo Valentin temp &= tsr->bgap_dtemp_mask; 153eb982001SEduardo Valentin 154eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) 155eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0); 156eb982001SEduardo Valentin 157eb982001SEduardo Valentin return temp; 158eb982001SEduardo Valentin } 159eb982001SEduardo Valentin 160eb982001SEduardo Valentin /*** IRQ handlers ***/ 161eb982001SEduardo Valentin 162eb982001SEduardo Valentin /** 163eb982001SEduardo Valentin * ti_bandgap_talert_irq_handler() - handles Temperature alert IRQs 164eb982001SEduardo Valentin * @irq: IRQ number 165eb982001SEduardo Valentin * @data: private data (struct ti_bandgap *) 166eb982001SEduardo Valentin * 167eb982001SEduardo Valentin * This is the Talert handler. Use it only if bandgap device features 168eb982001SEduardo Valentin * HAS(TALERT). This handler goes over all sensors and checks their 169eb982001SEduardo Valentin * conditions and acts accordingly. In case there are events pending, 170eb982001SEduardo Valentin * it will reset the event mask to wait for the opposite event (next event). 171eb982001SEduardo Valentin * Every time there is a new event, it will be reported to thermal layer. 172eb982001SEduardo Valentin * 173eb982001SEduardo Valentin * Return: IRQ_HANDLED 174eb982001SEduardo Valentin */ 175eb982001SEduardo Valentin static irqreturn_t ti_bandgap_talert_irq_handler(int irq, void *data) 176eb982001SEduardo Valentin { 177eb982001SEduardo Valentin struct ti_bandgap *bgp = data; 178eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 179eb982001SEduardo Valentin u32 t_hot = 0, t_cold = 0, ctrl; 180eb982001SEduardo Valentin int i; 181eb982001SEduardo Valentin 182eb982001SEduardo Valentin spin_lock(&bgp->lock); 183eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 184eb982001SEduardo Valentin tsr = bgp->conf->sensors[i].registers; 185eb982001SEduardo Valentin ctrl = ti_bandgap_readl(bgp, tsr->bgap_status); 186eb982001SEduardo Valentin 187eb982001SEduardo Valentin /* Read the status of t_hot */ 188eb982001SEduardo Valentin t_hot = ctrl & tsr->status_hot_mask; 189eb982001SEduardo Valentin 190eb982001SEduardo Valentin /* Read the status of t_cold */ 191eb982001SEduardo Valentin t_cold = ctrl & tsr->status_cold_mask; 192eb982001SEduardo Valentin 193eb982001SEduardo Valentin if (!t_cold && !t_hot) 194eb982001SEduardo Valentin continue; 195eb982001SEduardo Valentin 196eb982001SEduardo Valentin ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); 197eb982001SEduardo Valentin /* 198eb982001SEduardo Valentin * One TALERT interrupt: Two sources 199eb982001SEduardo Valentin * If the interrupt is due to t_hot then mask t_hot and 200eb982001SEduardo Valentin * and unmask t_cold else mask t_cold and unmask t_hot 201eb982001SEduardo Valentin */ 202eb982001SEduardo Valentin if (t_hot) { 203eb982001SEduardo Valentin ctrl &= ~tsr->mask_hot_mask; 204eb982001SEduardo Valentin ctrl |= tsr->mask_cold_mask; 205eb982001SEduardo Valentin } else if (t_cold) { 206eb982001SEduardo Valentin ctrl &= ~tsr->mask_cold_mask; 207eb982001SEduardo Valentin ctrl |= tsr->mask_hot_mask; 208eb982001SEduardo Valentin } 209eb982001SEduardo Valentin 210eb982001SEduardo Valentin ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl); 211eb982001SEduardo Valentin 212eb982001SEduardo Valentin dev_dbg(bgp->dev, 213eb982001SEduardo Valentin "%s: IRQ from %s sensor: hotevent %d coldevent %d\n", 214eb982001SEduardo Valentin __func__, bgp->conf->sensors[i].domain, 215eb982001SEduardo Valentin t_hot, t_cold); 216eb982001SEduardo Valentin 217eb982001SEduardo Valentin /* report temperature to whom may concern */ 218eb982001SEduardo Valentin if (bgp->conf->report_temperature) 219eb982001SEduardo Valentin bgp->conf->report_temperature(bgp, i); 220eb982001SEduardo Valentin } 221eb982001SEduardo Valentin spin_unlock(&bgp->lock); 222eb982001SEduardo Valentin 223eb982001SEduardo Valentin return IRQ_HANDLED; 224eb982001SEduardo Valentin } 225eb982001SEduardo Valentin 226eb982001SEduardo Valentin /** 227eb982001SEduardo Valentin * ti_bandgap_tshut_irq_handler() - handles Temperature shutdown signal 228eb982001SEduardo Valentin * @irq: IRQ number 229eb982001SEduardo Valentin * @data: private data (unused) 230eb982001SEduardo Valentin * 231eb982001SEduardo Valentin * This is the Tshut handler. Use it only if bandgap device features 232eb982001SEduardo Valentin * HAS(TSHUT). If any sensor fires the Tshut signal, we simply shutdown 233eb982001SEduardo Valentin * the system. 234eb982001SEduardo Valentin * 235eb982001SEduardo Valentin * Return: IRQ_HANDLED 236eb982001SEduardo Valentin */ 237eb982001SEduardo Valentin static irqreturn_t ti_bandgap_tshut_irq_handler(int irq, void *data) 238eb982001SEduardo Valentin { 239eb982001SEduardo Valentin pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n", 240eb982001SEduardo Valentin __func__); 241eb982001SEduardo Valentin 242eb982001SEduardo Valentin orderly_poweroff(true); 243eb982001SEduardo Valentin 244eb982001SEduardo Valentin return IRQ_HANDLED; 245eb982001SEduardo Valentin } 246eb982001SEduardo Valentin 247eb982001SEduardo Valentin /*** Helper functions which manipulate conversion ADC <-> mi Celsius ***/ 248eb982001SEduardo Valentin 249eb982001SEduardo Valentin /** 250eb982001SEduardo Valentin * ti_bandgap_adc_to_mcelsius() - converts an ADC value to mCelsius scale 251eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 252eb982001SEduardo Valentin * @adc_val: value in ADC representation 253eb982001SEduardo Valentin * @t: address where to write the resulting temperature in mCelsius 254eb982001SEduardo Valentin * 255eb982001SEduardo Valentin * Simple conversion from ADC representation to mCelsius. In case the ADC value 256eb982001SEduardo Valentin * is out of the ADC conv table range, it returns -ERANGE, 0 on success. 257eb982001SEduardo Valentin * The conversion table is indexed by the ADC values. 258eb982001SEduardo Valentin * 259eb982001SEduardo Valentin * Return: 0 if conversion was successful, else -ERANGE in case the @adc_val 260eb982001SEduardo Valentin * argument is out of the ADC conv table range. 261eb982001SEduardo Valentin */ 262eb982001SEduardo Valentin static 263eb982001SEduardo Valentin int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t) 264eb982001SEduardo Valentin { 265eb982001SEduardo Valentin const struct ti_bandgap_data *conf = bgp->conf; 266eb982001SEduardo Valentin int ret = 0; 267eb982001SEduardo Valentin 268eb982001SEduardo Valentin /* look up for temperature in the table and return the temperature */ 269eb982001SEduardo Valentin if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val) { 270eb982001SEduardo Valentin ret = -ERANGE; 271eb982001SEduardo Valentin goto exit; 272eb982001SEduardo Valentin } 273eb982001SEduardo Valentin 274eb982001SEduardo Valentin *t = bgp->conf->conv_table[adc_val - conf->adc_start_val]; 275eb982001SEduardo Valentin 276eb982001SEduardo Valentin exit: 277eb982001SEduardo Valentin return ret; 278eb982001SEduardo Valentin } 279eb982001SEduardo Valentin 280eb982001SEduardo Valentin /** 281eb982001SEduardo Valentin * ti_bandgap_mcelsius_to_adc() - converts a mCelsius value to ADC scale 282eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 283eb982001SEduardo Valentin * @temp: value in mCelsius 284eb982001SEduardo Valentin * @adc: address where to write the resulting temperature in ADC representation 285eb982001SEduardo Valentin * 286eb982001SEduardo Valentin * Simple conversion from mCelsius to ADC values. In case the temp value 287eb982001SEduardo Valentin * is out of the ADC conv table range, it returns -ERANGE, 0 on success. 288eb982001SEduardo Valentin * The conversion table is indexed by the ADC values. 289eb982001SEduardo Valentin * 290eb982001SEduardo Valentin * Return: 0 if conversion was successful, else -ERANGE in case the @temp 291eb982001SEduardo Valentin * argument is out of the ADC conv table range. 292eb982001SEduardo Valentin */ 293eb982001SEduardo Valentin static 294eb982001SEduardo Valentin int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc) 295eb982001SEduardo Valentin { 296eb982001SEduardo Valentin const struct ti_bandgap_data *conf = bgp->conf; 297eb982001SEduardo Valentin const int *conv_table = bgp->conf->conv_table; 298eb982001SEduardo Valentin int high, low, mid, ret = 0; 299eb982001SEduardo Valentin 300eb982001SEduardo Valentin low = 0; 301eb982001SEduardo Valentin high = conf->adc_end_val - conf->adc_start_val; 302eb982001SEduardo Valentin mid = (high + low) / 2; 303eb982001SEduardo Valentin 304eb982001SEduardo Valentin if (temp < conv_table[low] || temp > conv_table[high]) { 305eb982001SEduardo Valentin ret = -ERANGE; 306eb982001SEduardo Valentin goto exit; 307eb982001SEduardo Valentin } 308eb982001SEduardo Valentin 309eb982001SEduardo Valentin while (low < high) { 310eb982001SEduardo Valentin if (temp < conv_table[mid]) 311eb982001SEduardo Valentin high = mid - 1; 312eb982001SEduardo Valentin else 313eb982001SEduardo Valentin low = mid + 1; 314eb982001SEduardo Valentin mid = (low + high) / 2; 315eb982001SEduardo Valentin } 316eb982001SEduardo Valentin 317eb982001SEduardo Valentin *adc = conf->adc_start_val + low; 318eb982001SEduardo Valentin 319eb982001SEduardo Valentin exit: 320eb982001SEduardo Valentin return ret; 321eb982001SEduardo Valentin } 322eb982001SEduardo Valentin 323eb982001SEduardo Valentin /** 324eb982001SEduardo Valentin * ti_bandgap_add_hyst() - add hysteresis (in mCelsius) to an ADC value 325eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 326eb982001SEduardo Valentin * @adc_val: temperature value in ADC representation 327eb982001SEduardo Valentin * @hyst_val: hysteresis value in mCelsius 328eb982001SEduardo Valentin * @sum: address where to write the resulting temperature (in ADC scale) 329eb982001SEduardo Valentin * 330eb982001SEduardo Valentin * Adds an hysteresis value (in mCelsius) to a ADC temperature value. 331eb982001SEduardo Valentin * 332eb982001SEduardo Valentin * Return: 0 on success, -ERANGE otherwise. 333eb982001SEduardo Valentin */ 334eb982001SEduardo Valentin static 335eb982001SEduardo Valentin int ti_bandgap_add_hyst(struct ti_bandgap *bgp, int adc_val, int hyst_val, 336eb982001SEduardo Valentin u32 *sum) 337eb982001SEduardo Valentin { 338eb982001SEduardo Valentin int temp, ret; 339eb982001SEduardo Valentin 340eb982001SEduardo Valentin /* 341eb982001SEduardo Valentin * Need to add in the mcelsius domain, so we have a temperature 342eb982001SEduardo Valentin * the conv_table range 343eb982001SEduardo Valentin */ 344eb982001SEduardo Valentin ret = ti_bandgap_adc_to_mcelsius(bgp, adc_val, &temp); 345eb982001SEduardo Valentin if (ret < 0) 346eb982001SEduardo Valentin goto exit; 347eb982001SEduardo Valentin 348eb982001SEduardo Valentin temp += hyst_val; 349eb982001SEduardo Valentin 350eb982001SEduardo Valentin ret = ti_bandgap_mcelsius_to_adc(bgp, temp, sum); 351eb982001SEduardo Valentin 352eb982001SEduardo Valentin exit: 353eb982001SEduardo Valentin return ret; 354eb982001SEduardo Valentin } 355eb982001SEduardo Valentin 356eb982001SEduardo Valentin /*** Helper functions handling device Alert/Shutdown signals ***/ 357eb982001SEduardo Valentin 358eb982001SEduardo Valentin /** 359eb982001SEduardo Valentin * ti_bandgap_unmask_interrupts() - unmasks the events of thot & tcold 360eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 361eb982001SEduardo Valentin * @id: bandgap sensor id 362eb982001SEduardo Valentin * @t_hot: hot temperature value to trigger alert signal 363eb982001SEduardo Valentin * @t_cold: cold temperature value to trigger alert signal 364eb982001SEduardo Valentin * 365eb982001SEduardo Valentin * Checks the requested t_hot and t_cold values and configures the IRQ event 366eb982001SEduardo Valentin * masks accordingly. Call this function only if bandgap features HAS(TALERT). 367eb982001SEduardo Valentin */ 368eb982001SEduardo Valentin static void ti_bandgap_unmask_interrupts(struct ti_bandgap *bgp, int id, 369eb982001SEduardo Valentin u32 t_hot, u32 t_cold) 370eb982001SEduardo Valentin { 371eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 372eb982001SEduardo Valentin u32 temp, reg_val; 373eb982001SEduardo Valentin 374eb982001SEduardo Valentin /* Read the current on die temperature */ 375eb982001SEduardo Valentin temp = ti_bandgap_read_temp(bgp, id); 376eb982001SEduardo Valentin 377eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 378eb982001SEduardo Valentin reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); 379eb982001SEduardo Valentin 380eb982001SEduardo Valentin if (temp < t_hot) 381eb982001SEduardo Valentin reg_val |= tsr->mask_hot_mask; 382eb982001SEduardo Valentin else 383eb982001SEduardo Valentin reg_val &= ~tsr->mask_hot_mask; 384eb982001SEduardo Valentin 385eb982001SEduardo Valentin if (t_cold < temp) 386eb982001SEduardo Valentin reg_val |= tsr->mask_cold_mask; 387eb982001SEduardo Valentin else 388eb982001SEduardo Valentin reg_val &= ~tsr->mask_cold_mask; 389eb982001SEduardo Valentin ti_bandgap_writel(bgp, reg_val, tsr->bgap_mask_ctrl); 390eb982001SEduardo Valentin } 391eb982001SEduardo Valentin 392eb982001SEduardo Valentin /** 393eb982001SEduardo Valentin * ti_bandgap_update_alert_threshold() - sequence to update thresholds 394eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 395eb982001SEduardo Valentin * @id: bandgap sensor id 396eb982001SEduardo Valentin * @val: value (ADC) of a new threshold 397eb982001SEduardo Valentin * @hot: desired threshold to be updated. true if threshold hot, false if 398eb982001SEduardo Valentin * threshold cold 399eb982001SEduardo Valentin * 400eb982001SEduardo Valentin * It will program the required thresholds (hot and cold) for TALERT signal. 401eb982001SEduardo Valentin * This function can be used to update t_hot or t_cold, depending on @hot value. 402eb982001SEduardo Valentin * It checks the resulting t_hot and t_cold values, based on the new passed @val 403eb982001SEduardo Valentin * and configures the thresholds so that t_hot is always greater than t_cold. 404eb982001SEduardo Valentin * Call this function only if bandgap features HAS(TALERT). 405eb982001SEduardo Valentin * 406eb982001SEduardo Valentin * Return: 0 if no error, else corresponding error 407eb982001SEduardo Valentin */ 408eb982001SEduardo Valentin static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id, 409eb982001SEduardo Valentin int val, bool hot) 410eb982001SEduardo Valentin { 411eb982001SEduardo Valentin struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data; 412eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 413eb982001SEduardo Valentin u32 thresh_val, reg_val, t_hot, t_cold; 414eb982001SEduardo Valentin int err = 0; 415eb982001SEduardo Valentin 416eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 417eb982001SEduardo Valentin 418eb982001SEduardo Valentin /* obtain the current value */ 419eb982001SEduardo Valentin thresh_val = ti_bandgap_readl(bgp, tsr->bgap_threshold); 420eb982001SEduardo Valentin t_cold = (thresh_val & tsr->threshold_tcold_mask) >> 421eb982001SEduardo Valentin __ffs(tsr->threshold_tcold_mask); 422eb982001SEduardo Valentin t_hot = (thresh_val & tsr->threshold_thot_mask) >> 423eb982001SEduardo Valentin __ffs(tsr->threshold_thot_mask); 424eb982001SEduardo Valentin if (hot) 425eb982001SEduardo Valentin t_hot = val; 426eb982001SEduardo Valentin else 427eb982001SEduardo Valentin t_cold = val; 428eb982001SEduardo Valentin 429eb982001SEduardo Valentin if (t_cold > t_hot) { 430eb982001SEduardo Valentin if (hot) 431eb982001SEduardo Valentin err = ti_bandgap_add_hyst(bgp, t_hot, 432eb982001SEduardo Valentin -ts_data->hyst_val, 433eb982001SEduardo Valentin &t_cold); 434eb982001SEduardo Valentin else 435eb982001SEduardo Valentin err = ti_bandgap_add_hyst(bgp, t_cold, 436eb982001SEduardo Valentin ts_data->hyst_val, 437eb982001SEduardo Valentin &t_hot); 438eb982001SEduardo Valentin } 439eb982001SEduardo Valentin 440eb982001SEduardo Valentin /* write the new threshold values */ 441eb982001SEduardo Valentin reg_val = thresh_val & 442eb982001SEduardo Valentin ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask); 443eb982001SEduardo Valentin reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) | 444eb982001SEduardo Valentin (t_cold << __ffs(tsr->threshold_tcold_mask)); 445eb982001SEduardo Valentin ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold); 446eb982001SEduardo Valentin 447eb982001SEduardo Valentin if (err) { 448eb982001SEduardo Valentin dev_err(bgp->dev, "failed to reprogram thot threshold\n"); 449eb982001SEduardo Valentin err = -EIO; 450eb982001SEduardo Valentin goto exit; 451eb982001SEduardo Valentin } 452eb982001SEduardo Valentin 453eb982001SEduardo Valentin ti_bandgap_unmask_interrupts(bgp, id, t_hot, t_cold); 454eb982001SEduardo Valentin exit: 455eb982001SEduardo Valentin return err; 456eb982001SEduardo Valentin } 457eb982001SEduardo Valentin 458eb982001SEduardo Valentin /** 459eb982001SEduardo Valentin * ti_bandgap_validate() - helper to check the sanity of a struct ti_bandgap 460eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 461eb982001SEduardo Valentin * @id: bandgap sensor id 462eb982001SEduardo Valentin * 463eb982001SEduardo Valentin * Checks if the bandgap pointer is valid and if the sensor id is also 464eb982001SEduardo Valentin * applicable. 465eb982001SEduardo Valentin * 466eb982001SEduardo Valentin * Return: 0 if no errors, -EINVAL for invalid @bgp pointer or -ERANGE if 467eb982001SEduardo Valentin * @id cannot index @bgp sensors. 468eb982001SEduardo Valentin */ 469eb982001SEduardo Valentin static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id) 470eb982001SEduardo Valentin { 471eb982001SEduardo Valentin int ret = 0; 472eb982001SEduardo Valentin 4730c12b5acSEduardo Valentin if (!bgp || IS_ERR(bgp)) { 474eb982001SEduardo Valentin pr_err("%s: invalid bandgap pointer\n", __func__); 475eb982001SEduardo Valentin ret = -EINVAL; 476eb982001SEduardo Valentin goto exit; 477eb982001SEduardo Valentin } 478eb982001SEduardo Valentin 479eb982001SEduardo Valentin if ((id < 0) || (id >= bgp->conf->sensor_count)) { 480eb982001SEduardo Valentin dev_err(bgp->dev, "%s: sensor id out of range (%d)\n", 481eb982001SEduardo Valentin __func__, id); 482eb982001SEduardo Valentin ret = -ERANGE; 483eb982001SEduardo Valentin } 484eb982001SEduardo Valentin 485eb982001SEduardo Valentin exit: 486eb982001SEduardo Valentin return ret; 487eb982001SEduardo Valentin } 488eb982001SEduardo Valentin 489eb982001SEduardo Valentin /** 490eb982001SEduardo Valentin * _ti_bandgap_write_threshold() - helper to update TALERT t_cold or t_hot 491eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 492eb982001SEduardo Valentin * @id: bandgap sensor id 493eb982001SEduardo Valentin * @val: value (mCelsius) of a new threshold 494eb982001SEduardo Valentin * @hot: desired threshold to be updated. true if threshold hot, false if 495eb982001SEduardo Valentin * threshold cold 496eb982001SEduardo Valentin * 497eb982001SEduardo Valentin * It will update the required thresholds (hot and cold) for TALERT signal. 498eb982001SEduardo Valentin * This function can be used to update t_hot or t_cold, depending on @hot value. 499eb982001SEduardo Valentin * Validates the mCelsius range and update the requested threshold. 500eb982001SEduardo Valentin * Call this function only if bandgap features HAS(TALERT). 501eb982001SEduardo Valentin * 502eb982001SEduardo Valentin * Return: 0 if no error, else corresponding error value. 503eb982001SEduardo Valentin */ 504eb982001SEduardo Valentin static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val, 505eb982001SEduardo Valentin bool hot) 506eb982001SEduardo Valentin { 507eb982001SEduardo Valentin struct temp_sensor_data *ts_data; 508eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 509eb982001SEduardo Valentin u32 adc_val; 510eb982001SEduardo Valentin int ret; 511eb982001SEduardo Valentin 512eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 513eb982001SEduardo Valentin if (ret) 514eb982001SEduardo Valentin goto exit; 515eb982001SEduardo Valentin 516eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, TALERT)) { 517eb982001SEduardo Valentin ret = -ENOTSUPP; 518eb982001SEduardo Valentin goto exit; 519eb982001SEduardo Valentin } 520eb982001SEduardo Valentin 521eb982001SEduardo Valentin ts_data = bgp->conf->sensors[id].ts_data; 522eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 523eb982001SEduardo Valentin if (hot) { 524eb982001SEduardo Valentin if (val < ts_data->min_temp + ts_data->hyst_val) 525eb982001SEduardo Valentin ret = -EINVAL; 526eb982001SEduardo Valentin } else { 527eb982001SEduardo Valentin if (val > ts_data->max_temp + ts_data->hyst_val) 528eb982001SEduardo Valentin ret = -EINVAL; 529eb982001SEduardo Valentin } 530eb982001SEduardo Valentin 531eb982001SEduardo Valentin if (ret) 532eb982001SEduardo Valentin goto exit; 533eb982001SEduardo Valentin 534eb982001SEduardo Valentin ret = ti_bandgap_mcelsius_to_adc(bgp, val, &adc_val); 535eb982001SEduardo Valentin if (ret < 0) 536eb982001SEduardo Valentin goto exit; 537eb982001SEduardo Valentin 538eb982001SEduardo Valentin spin_lock(&bgp->lock); 539eb982001SEduardo Valentin ret = ti_bandgap_update_alert_threshold(bgp, id, adc_val, hot); 540eb982001SEduardo Valentin spin_unlock(&bgp->lock); 541eb982001SEduardo Valentin 542eb982001SEduardo Valentin exit: 543eb982001SEduardo Valentin return ret; 544eb982001SEduardo Valentin } 545eb982001SEduardo Valentin 546eb982001SEduardo Valentin /** 547eb982001SEduardo Valentin * _ti_bandgap_read_threshold() - helper to read TALERT t_cold or t_hot 548eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 549eb982001SEduardo Valentin * @id: bandgap sensor id 550eb982001SEduardo Valentin * @val: value (mCelsius) of a threshold 551eb982001SEduardo Valentin * @hot: desired threshold to be read. true if threshold hot, false if 552eb982001SEduardo Valentin * threshold cold 553eb982001SEduardo Valentin * 554eb982001SEduardo Valentin * It will fetch the required thresholds (hot and cold) for TALERT signal. 555eb982001SEduardo Valentin * This function can be used to read t_hot or t_cold, depending on @hot value. 556eb982001SEduardo Valentin * Call this function only if bandgap features HAS(TALERT). 557eb982001SEduardo Valentin * 558eb982001SEduardo Valentin * Return: 0 if no error, -ENOTSUPP if it has no TALERT support, or the 559eb982001SEduardo Valentin * corresponding error value if some operation fails. 560eb982001SEduardo Valentin */ 561eb982001SEduardo Valentin static int _ti_bandgap_read_threshold(struct ti_bandgap *bgp, int id, 562eb982001SEduardo Valentin int *val, bool hot) 563eb982001SEduardo Valentin { 564eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 565eb982001SEduardo Valentin u32 temp, mask; 566eb982001SEduardo Valentin int ret = 0; 567eb982001SEduardo Valentin 568eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 569eb982001SEduardo Valentin if (ret) 570eb982001SEduardo Valentin goto exit; 571eb982001SEduardo Valentin 572eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, TALERT)) { 573eb982001SEduardo Valentin ret = -ENOTSUPP; 574eb982001SEduardo Valentin goto exit; 575eb982001SEduardo Valentin } 576eb982001SEduardo Valentin 577eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 578eb982001SEduardo Valentin if (hot) 579eb982001SEduardo Valentin mask = tsr->threshold_thot_mask; 580eb982001SEduardo Valentin else 581eb982001SEduardo Valentin mask = tsr->threshold_tcold_mask; 582eb982001SEduardo Valentin 583eb982001SEduardo Valentin temp = ti_bandgap_readl(bgp, tsr->bgap_threshold); 584eb982001SEduardo Valentin temp = (temp & mask) >> __ffs(mask); 585eb982001SEduardo Valentin ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp); 586eb982001SEduardo Valentin if (ret) { 587eb982001SEduardo Valentin dev_err(bgp->dev, "failed to read thot\n"); 588eb982001SEduardo Valentin ret = -EIO; 589eb982001SEduardo Valentin goto exit; 590eb982001SEduardo Valentin } 591eb982001SEduardo Valentin 592eb982001SEduardo Valentin *val = temp; 593eb982001SEduardo Valentin 594eb982001SEduardo Valentin exit: 595eb982001SEduardo Valentin return ret; 596eb982001SEduardo Valentin } 597eb982001SEduardo Valentin 598eb982001SEduardo Valentin /*** Exposed APIs ***/ 599eb982001SEduardo Valentin 600eb982001SEduardo Valentin /** 601eb982001SEduardo Valentin * ti_bandgap_read_thot() - reads sensor current thot 602eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 603eb982001SEduardo Valentin * @id: sensor id 604eb982001SEduardo Valentin * @thot: resulting current thot value 605eb982001SEduardo Valentin * 606eb982001SEduardo Valentin * Return: 0 on success or the proper error code 607eb982001SEduardo Valentin */ 608eb982001SEduardo Valentin int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot) 609eb982001SEduardo Valentin { 610eb982001SEduardo Valentin return _ti_bandgap_read_threshold(bgp, id, thot, true); 611eb982001SEduardo Valentin } 612eb982001SEduardo Valentin 613eb982001SEduardo Valentin /** 614eb982001SEduardo Valentin * ti_bandgap_write_thot() - sets sensor current thot 615eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 616eb982001SEduardo Valentin * @id: sensor id 617eb982001SEduardo Valentin * @val: desired thot value 618eb982001SEduardo Valentin * 619eb982001SEduardo Valentin * Return: 0 on success or the proper error code 620eb982001SEduardo Valentin */ 621eb982001SEduardo Valentin int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val) 622eb982001SEduardo Valentin { 623eb982001SEduardo Valentin return _ti_bandgap_write_threshold(bgp, id, val, true); 624eb982001SEduardo Valentin } 625eb982001SEduardo Valentin 626eb982001SEduardo Valentin /** 627eb982001SEduardo Valentin * ti_bandgap_read_tcold() - reads sensor current tcold 628eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 629eb982001SEduardo Valentin * @id: sensor id 630eb982001SEduardo Valentin * @tcold: resulting current tcold value 631eb982001SEduardo Valentin * 632eb982001SEduardo Valentin * Return: 0 on success or the proper error code 633eb982001SEduardo Valentin */ 634eb982001SEduardo Valentin int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold) 635eb982001SEduardo Valentin { 636eb982001SEduardo Valentin return _ti_bandgap_read_threshold(bgp, id, tcold, false); 637eb982001SEduardo Valentin } 638eb982001SEduardo Valentin 639eb982001SEduardo Valentin /** 640eb982001SEduardo Valentin * ti_bandgap_write_tcold() - sets the sensor tcold 641eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 642eb982001SEduardo Valentin * @id: sensor id 643eb982001SEduardo Valentin * @val: desired tcold value 644eb982001SEduardo Valentin * 645eb982001SEduardo Valentin * Return: 0 on success or the proper error code 646eb982001SEduardo Valentin */ 647eb982001SEduardo Valentin int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val) 648eb982001SEduardo Valentin { 649eb982001SEduardo Valentin return _ti_bandgap_write_threshold(bgp, id, val, false); 650eb982001SEduardo Valentin } 651eb982001SEduardo Valentin 652eb982001SEduardo Valentin /** 653eb982001SEduardo Valentin * ti_bandgap_read_counter() - read the sensor counter 654eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 655eb982001SEduardo Valentin * @id: sensor id 656eb982001SEduardo Valentin * @interval: resulting update interval in miliseconds 657eb982001SEduardo Valentin */ 658eb982001SEduardo Valentin static void ti_bandgap_read_counter(struct ti_bandgap *bgp, int id, 659eb982001SEduardo Valentin int *interval) 660eb982001SEduardo Valentin { 661eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 662eb982001SEduardo Valentin int time; 663eb982001SEduardo Valentin 664eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 665eb982001SEduardo Valentin time = ti_bandgap_readl(bgp, tsr->bgap_counter); 666eb982001SEduardo Valentin time = (time & tsr->counter_mask) >> 667eb982001SEduardo Valentin __ffs(tsr->counter_mask); 668eb982001SEduardo Valentin time = time * 1000 / bgp->clk_rate; 669eb982001SEduardo Valentin *interval = time; 670eb982001SEduardo Valentin } 671eb982001SEduardo Valentin 672eb982001SEduardo Valentin /** 673eb982001SEduardo Valentin * ti_bandgap_read_counter_delay() - read the sensor counter delay 674eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 675eb982001SEduardo Valentin * @id: sensor id 676eb982001SEduardo Valentin * @interval: resulting update interval in miliseconds 677eb982001SEduardo Valentin */ 678eb982001SEduardo Valentin static void ti_bandgap_read_counter_delay(struct ti_bandgap *bgp, int id, 679eb982001SEduardo Valentin int *interval) 680eb982001SEduardo Valentin { 681eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 682eb982001SEduardo Valentin int reg_val; 683eb982001SEduardo Valentin 684eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 685eb982001SEduardo Valentin 686eb982001SEduardo Valentin reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); 687eb982001SEduardo Valentin reg_val = (reg_val & tsr->mask_counter_delay_mask) >> 688eb982001SEduardo Valentin __ffs(tsr->mask_counter_delay_mask); 689eb982001SEduardo Valentin switch (reg_val) { 690eb982001SEduardo Valentin case 0: 691eb982001SEduardo Valentin *interval = 0; 692eb982001SEduardo Valentin break; 693eb982001SEduardo Valentin case 1: 694eb982001SEduardo Valentin *interval = 1; 695eb982001SEduardo Valentin break; 696eb982001SEduardo Valentin case 2: 697eb982001SEduardo Valentin *interval = 10; 698eb982001SEduardo Valentin break; 699eb982001SEduardo Valentin case 3: 700eb982001SEduardo Valentin *interval = 100; 701eb982001SEduardo Valentin break; 702eb982001SEduardo Valentin case 4: 703eb982001SEduardo Valentin *interval = 250; 704eb982001SEduardo Valentin break; 705eb982001SEduardo Valentin case 5: 706eb982001SEduardo Valentin *interval = 500; 707eb982001SEduardo Valentin break; 708eb982001SEduardo Valentin default: 709eb982001SEduardo Valentin dev_warn(bgp->dev, "Wrong counter delay value read from register %X", 710eb982001SEduardo Valentin reg_val); 711eb982001SEduardo Valentin } 712eb982001SEduardo Valentin } 713eb982001SEduardo Valentin 714eb982001SEduardo Valentin /** 715eb982001SEduardo Valentin * ti_bandgap_read_update_interval() - read the sensor update interval 716eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 717eb982001SEduardo Valentin * @id: sensor id 718eb982001SEduardo Valentin * @interval: resulting update interval in miliseconds 719eb982001SEduardo Valentin * 720eb982001SEduardo Valentin * Return: 0 on success or the proper error code 721eb982001SEduardo Valentin */ 722eb982001SEduardo Valentin int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id, 723eb982001SEduardo Valentin int *interval) 724eb982001SEduardo Valentin { 725eb982001SEduardo Valentin int ret = 0; 726eb982001SEduardo Valentin 727eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 728eb982001SEduardo Valentin if (ret) 729eb982001SEduardo Valentin goto exit; 730eb982001SEduardo Valentin 731eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, COUNTER) && 732eb982001SEduardo Valentin !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) { 733eb982001SEduardo Valentin ret = -ENOTSUPP; 734eb982001SEduardo Valentin goto exit; 735eb982001SEduardo Valentin } 736eb982001SEduardo Valentin 737eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) { 738eb982001SEduardo Valentin ti_bandgap_read_counter(bgp, id, interval); 739eb982001SEduardo Valentin goto exit; 740eb982001SEduardo Valentin } 741eb982001SEduardo Valentin 742eb982001SEduardo Valentin ti_bandgap_read_counter_delay(bgp, id, interval); 743eb982001SEduardo Valentin exit: 744eb982001SEduardo Valentin return ret; 745eb982001SEduardo Valentin } 746eb982001SEduardo Valentin 747eb982001SEduardo Valentin /** 748eb982001SEduardo Valentin * ti_bandgap_write_counter_delay() - set the counter_delay 749eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 750eb982001SEduardo Valentin * @id: sensor id 751eb982001SEduardo Valentin * @interval: desired update interval in miliseconds 752eb982001SEduardo Valentin * 753eb982001SEduardo Valentin * Return: 0 on success or the proper error code 754eb982001SEduardo Valentin */ 755eb982001SEduardo Valentin static int ti_bandgap_write_counter_delay(struct ti_bandgap *bgp, int id, 756eb982001SEduardo Valentin u32 interval) 757eb982001SEduardo Valentin { 758eb982001SEduardo Valentin int rval; 759eb982001SEduardo Valentin 760eb982001SEduardo Valentin switch (interval) { 761eb982001SEduardo Valentin case 0: /* Immediate conversion */ 762eb982001SEduardo Valentin rval = 0x0; 763eb982001SEduardo Valentin break; 764eb982001SEduardo Valentin case 1: /* Conversion after ever 1ms */ 765eb982001SEduardo Valentin rval = 0x1; 766eb982001SEduardo Valentin break; 767eb982001SEduardo Valentin case 10: /* Conversion after ever 10ms */ 768eb982001SEduardo Valentin rval = 0x2; 769eb982001SEduardo Valentin break; 770eb982001SEduardo Valentin case 100: /* Conversion after ever 100ms */ 771eb982001SEduardo Valentin rval = 0x3; 772eb982001SEduardo Valentin break; 773eb982001SEduardo Valentin case 250: /* Conversion after ever 250ms */ 774eb982001SEduardo Valentin rval = 0x4; 775eb982001SEduardo Valentin break; 776eb982001SEduardo Valentin case 500: /* Conversion after ever 500ms */ 777eb982001SEduardo Valentin rval = 0x5; 778eb982001SEduardo Valentin break; 779eb982001SEduardo Valentin default: 780eb982001SEduardo Valentin dev_warn(bgp->dev, "Delay %d ms is not supported\n", interval); 781eb982001SEduardo Valentin return -EINVAL; 782eb982001SEduardo Valentin } 783eb982001SEduardo Valentin 784eb982001SEduardo Valentin spin_lock(&bgp->lock); 785eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_counter_delay_mask, rval); 786eb982001SEduardo Valentin spin_unlock(&bgp->lock); 787eb982001SEduardo Valentin 788eb982001SEduardo Valentin return 0; 789eb982001SEduardo Valentin } 790eb982001SEduardo Valentin 791eb982001SEduardo Valentin /** 792eb982001SEduardo Valentin * ti_bandgap_write_counter() - set the bandgap sensor counter 793eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 794eb982001SEduardo Valentin * @id: sensor id 795eb982001SEduardo Valentin * @interval: desired update interval in miliseconds 796eb982001SEduardo Valentin */ 797eb982001SEduardo Valentin static void ti_bandgap_write_counter(struct ti_bandgap *bgp, int id, 798eb982001SEduardo Valentin u32 interval) 799eb982001SEduardo Valentin { 800eb982001SEduardo Valentin interval = interval * bgp->clk_rate / 1000; 801eb982001SEduardo Valentin spin_lock(&bgp->lock); 802eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_counter, counter_mask, interval); 803eb982001SEduardo Valentin spin_unlock(&bgp->lock); 804eb982001SEduardo Valentin } 805eb982001SEduardo Valentin 806eb982001SEduardo Valentin /** 807eb982001SEduardo Valentin * ti_bandgap_write_update_interval() - set the update interval 808eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 809eb982001SEduardo Valentin * @id: sensor id 810eb982001SEduardo Valentin * @interval: desired update interval in miliseconds 811eb982001SEduardo Valentin * 812eb982001SEduardo Valentin * Return: 0 on success or the proper error code 813eb982001SEduardo Valentin */ 814eb982001SEduardo Valentin int ti_bandgap_write_update_interval(struct ti_bandgap *bgp, 815eb982001SEduardo Valentin int id, u32 interval) 816eb982001SEduardo Valentin { 817eb982001SEduardo Valentin int ret = ti_bandgap_validate(bgp, id); 818eb982001SEduardo Valentin if (ret) 819eb982001SEduardo Valentin goto exit; 820eb982001SEduardo Valentin 821eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, COUNTER) && 822eb982001SEduardo Valentin !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) { 823eb982001SEduardo Valentin ret = -ENOTSUPP; 824eb982001SEduardo Valentin goto exit; 825eb982001SEduardo Valentin } 826eb982001SEduardo Valentin 827eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) { 828eb982001SEduardo Valentin ti_bandgap_write_counter(bgp, id, interval); 829eb982001SEduardo Valentin goto exit; 830eb982001SEduardo Valentin } 831eb982001SEduardo Valentin 832eb982001SEduardo Valentin ret = ti_bandgap_write_counter_delay(bgp, id, interval); 833eb982001SEduardo Valentin exit: 834eb982001SEduardo Valentin return ret; 835eb982001SEduardo Valentin } 836eb982001SEduardo Valentin 837eb982001SEduardo Valentin /** 838eb982001SEduardo Valentin * ti_bandgap_read_temperature() - report current temperature 839eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 840eb982001SEduardo Valentin * @id: sensor id 841eb982001SEduardo Valentin * @temperature: resulting temperature 842eb982001SEduardo Valentin * 843eb982001SEduardo Valentin * Return: 0 on success or the proper error code 844eb982001SEduardo Valentin */ 845eb982001SEduardo Valentin int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id, 846eb982001SEduardo Valentin int *temperature) 847eb982001SEduardo Valentin { 848eb982001SEduardo Valentin u32 temp; 849eb982001SEduardo Valentin int ret; 850eb982001SEduardo Valentin 851eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 852eb982001SEduardo Valentin if (ret) 853eb982001SEduardo Valentin return ret; 854eb982001SEduardo Valentin 855eb982001SEduardo Valentin spin_lock(&bgp->lock); 856eb982001SEduardo Valentin temp = ti_bandgap_read_temp(bgp, id); 857eb982001SEduardo Valentin spin_unlock(&bgp->lock); 858eb982001SEduardo Valentin 859eb982001SEduardo Valentin ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp); 860eb982001SEduardo Valentin if (ret) 861eb982001SEduardo Valentin return -EIO; 862eb982001SEduardo Valentin 863eb982001SEduardo Valentin *temperature = temp; 864eb982001SEduardo Valentin 865eb982001SEduardo Valentin return 0; 866eb982001SEduardo Valentin } 867eb982001SEduardo Valentin 868eb982001SEduardo Valentin /** 869eb982001SEduardo Valentin * ti_bandgap_set_sensor_data() - helper function to store thermal 870eb982001SEduardo Valentin * framework related data. 871eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 872eb982001SEduardo Valentin * @id: sensor id 873eb982001SEduardo Valentin * @data: thermal framework related data to be stored 874eb982001SEduardo Valentin * 875eb982001SEduardo Valentin * Return: 0 on success or the proper error code 876eb982001SEduardo Valentin */ 877eb982001SEduardo Valentin int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data) 878eb982001SEduardo Valentin { 879eb982001SEduardo Valentin int ret = ti_bandgap_validate(bgp, id); 880eb982001SEduardo Valentin if (ret) 881eb982001SEduardo Valentin return ret; 882eb982001SEduardo Valentin 883eb982001SEduardo Valentin bgp->regval[id].data = data; 884eb982001SEduardo Valentin 885eb982001SEduardo Valentin return 0; 886eb982001SEduardo Valentin } 887eb982001SEduardo Valentin 888eb982001SEduardo Valentin /** 889eb982001SEduardo Valentin * ti_bandgap_get_sensor_data() - helper function to get thermal 890eb982001SEduardo Valentin * framework related data. 891eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 892eb982001SEduardo Valentin * @id: sensor id 893eb982001SEduardo Valentin * 894eb982001SEduardo Valentin * Return: data stored by set function with sensor id on success or NULL 895eb982001SEduardo Valentin */ 896eb982001SEduardo Valentin void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id) 897eb982001SEduardo Valentin { 898eb982001SEduardo Valentin int ret = ti_bandgap_validate(bgp, id); 899eb982001SEduardo Valentin if (ret) 900eb982001SEduardo Valentin return ERR_PTR(ret); 901eb982001SEduardo Valentin 902eb982001SEduardo Valentin return bgp->regval[id].data; 903eb982001SEduardo Valentin } 904eb982001SEduardo Valentin 905eb982001SEduardo Valentin /*** Helper functions used during device initialization ***/ 906eb982001SEduardo Valentin 907eb982001SEduardo Valentin /** 908eb982001SEduardo Valentin * ti_bandgap_force_single_read() - executes 1 single ADC conversion 909eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 910eb982001SEduardo Valentin * @id: sensor id which it is desired to read 1 temperature 911eb982001SEduardo Valentin * 912eb982001SEduardo Valentin * Used to initialize the conversion state machine and set it to a valid 913eb982001SEduardo Valentin * state. Called during device initialization and context restore events. 914eb982001SEduardo Valentin * 915eb982001SEduardo Valentin * Return: 0 916eb982001SEduardo Valentin */ 917eb982001SEduardo Valentin static int 918eb982001SEduardo Valentin ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id) 919eb982001SEduardo Valentin { 920eb982001SEduardo Valentin u32 temp = 0, counter = 1000; 921eb982001SEduardo Valentin 922eb982001SEduardo Valentin /* Select single conversion mode */ 923eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, MODE_CONFIG)) 924eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_mode_ctrl, mode_ctrl_mask, 0); 925eb982001SEduardo Valentin 926eb982001SEduardo Valentin /* Start of Conversion = 1 */ 927eb982001SEduardo Valentin RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 1); 928eb982001SEduardo Valentin /* Wait until DTEMP is updated */ 929eb982001SEduardo Valentin temp = ti_bandgap_read_temp(bgp, id); 930eb982001SEduardo Valentin 931eb982001SEduardo Valentin while ((temp == 0) && --counter) 932eb982001SEduardo Valentin temp = ti_bandgap_read_temp(bgp, id); 933eb982001SEduardo Valentin /* REVISIT: Check correct condition for end of conversion */ 934eb982001SEduardo Valentin 935eb982001SEduardo Valentin /* Start of Conversion = 0 */ 936eb982001SEduardo Valentin RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 0); 937eb982001SEduardo Valentin 938eb982001SEduardo Valentin return 0; 939eb982001SEduardo Valentin } 940eb982001SEduardo Valentin 941eb982001SEduardo Valentin /** 942eb982001SEduardo Valentin * ti_bandgap_set_continous_mode() - One time enabling of continuous mode 943eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 944eb982001SEduardo Valentin * 945eb982001SEduardo Valentin * Call this function only if HAS(MODE_CONFIG) is set. As this driver may 946eb982001SEduardo Valentin * be used for junction temperature monitoring, it is desirable that the 947eb982001SEduardo Valentin * sensors are operational all the time, so that alerts are generated 948eb982001SEduardo Valentin * properly. 949eb982001SEduardo Valentin * 950eb982001SEduardo Valentin * Return: 0 951eb982001SEduardo Valentin */ 952eb982001SEduardo Valentin static int ti_bandgap_set_continuous_mode(struct ti_bandgap *bgp) 953eb982001SEduardo Valentin { 954eb982001SEduardo Valentin int i; 955eb982001SEduardo Valentin 956eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 957eb982001SEduardo Valentin /* Perform a single read just before enabling continuous */ 958eb982001SEduardo Valentin ti_bandgap_force_single_read(bgp, i); 959eb982001SEduardo Valentin RMW_BITS(bgp, i, bgap_mode_ctrl, mode_ctrl_mask, 1); 960eb982001SEduardo Valentin } 961eb982001SEduardo Valentin 962eb982001SEduardo Valentin return 0; 963eb982001SEduardo Valentin } 964eb982001SEduardo Valentin 965eb982001SEduardo Valentin /** 966eb982001SEduardo Valentin * ti_bandgap_get_trend() - To fetch the temperature trend of a sensor 967eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 968eb982001SEduardo Valentin * @id: id of the individual sensor 969eb982001SEduardo Valentin * @trend: Pointer to trend. 970eb982001SEduardo Valentin * 971eb982001SEduardo Valentin * This function needs to be called to fetch the temperature trend of a 972eb982001SEduardo Valentin * Particular sensor. The function computes the difference in temperature 973eb982001SEduardo Valentin * w.r.t time. For the bandgaps with built in history buffer the temperatures 974eb982001SEduardo Valentin * are read from the buffer and for those without the Buffer -ENOTSUPP is 975eb982001SEduardo Valentin * returned. 976eb982001SEduardo Valentin * 977eb982001SEduardo Valentin * Return: 0 if no error, else return corresponding error. If no 978eb982001SEduardo Valentin * error then the trend value is passed on to trend parameter 979eb982001SEduardo Valentin */ 980eb982001SEduardo Valentin int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend) 981eb982001SEduardo Valentin { 982eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 983eb982001SEduardo Valentin u32 temp1, temp2, reg1, reg2; 984eb982001SEduardo Valentin int t1, t2, interval, ret = 0; 985eb982001SEduardo Valentin 986eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 987eb982001SEduardo Valentin if (ret) 988eb982001SEduardo Valentin goto exit; 989eb982001SEduardo Valentin 990eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, HISTORY_BUFFER) || 991eb982001SEduardo Valentin !TI_BANDGAP_HAS(bgp, FREEZE_BIT)) { 992eb982001SEduardo Valentin ret = -ENOTSUPP; 993eb982001SEduardo Valentin goto exit; 994eb982001SEduardo Valentin } 995eb982001SEduardo Valentin 996ba0049eaSEduardo Valentin spin_lock(&bgp->lock); 997ba0049eaSEduardo Valentin 998eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 999eb982001SEduardo Valentin 1000eb982001SEduardo Valentin /* Freeze and read the last 2 valid readings */ 1001ba0049eaSEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1); 1002eb982001SEduardo Valentin reg1 = tsr->ctrl_dtemp_1; 1003eb982001SEduardo Valentin reg2 = tsr->ctrl_dtemp_2; 1004eb982001SEduardo Valentin 1005eb982001SEduardo Valentin /* read temperature from history buffer */ 1006eb982001SEduardo Valentin temp1 = ti_bandgap_readl(bgp, reg1); 1007eb982001SEduardo Valentin temp1 &= tsr->bgap_dtemp_mask; 1008eb982001SEduardo Valentin 1009eb982001SEduardo Valentin temp2 = ti_bandgap_readl(bgp, reg2); 1010eb982001SEduardo Valentin temp2 &= tsr->bgap_dtemp_mask; 1011eb982001SEduardo Valentin 1012eb982001SEduardo Valentin /* Convert from adc values to mCelsius temperature */ 1013eb982001SEduardo Valentin ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1); 1014eb982001SEduardo Valentin if (ret) 1015ba0049eaSEduardo Valentin goto unfreeze; 1016eb982001SEduardo Valentin 1017eb982001SEduardo Valentin ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2); 1018eb982001SEduardo Valentin if (ret) 1019ba0049eaSEduardo Valentin goto unfreeze; 1020eb982001SEduardo Valentin 1021eb982001SEduardo Valentin /* Fetch the update interval */ 1022eb982001SEduardo Valentin ret = ti_bandgap_read_update_interval(bgp, id, &interval); 1023e838ff81SRanganath Krishnan if (ret) 1024ba0049eaSEduardo Valentin goto unfreeze; 1025eb982001SEduardo Valentin 1026e838ff81SRanganath Krishnan /* Set the interval to 1 ms if bandgap counter delay is not set */ 1027e838ff81SRanganath Krishnan if (interval == 0) 1028e838ff81SRanganath Krishnan interval = 1; 1029e838ff81SRanganath Krishnan 1030eb982001SEduardo Valentin *trend = (t1 - t2) / interval; 1031eb982001SEduardo Valentin 1032eb982001SEduardo Valentin dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n", 1033eb982001SEduardo Valentin t1, t2, *trend); 1034eb982001SEduardo Valentin 1035ba0049eaSEduardo Valentin unfreeze: 1036ba0049eaSEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0); 1037ba0049eaSEduardo Valentin spin_unlock(&bgp->lock); 1038eb982001SEduardo Valentin exit: 1039eb982001SEduardo Valentin return ret; 1040eb982001SEduardo Valentin } 1041eb982001SEduardo Valentin 1042eb982001SEduardo Valentin /** 1043eb982001SEduardo Valentin * ti_bandgap_tshut_init() - setup and initialize tshut handling 1044eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 1045eb982001SEduardo Valentin * @pdev: pointer to device struct platform_device 1046eb982001SEduardo Valentin * 1047eb982001SEduardo Valentin * Call this function only in case the bandgap features HAS(TSHUT). 1048eb982001SEduardo Valentin * In this case, the driver needs to handle the TSHUT signal as an IRQ. 1049eb982001SEduardo Valentin * The IRQ is wired as a GPIO, and for this purpose, it is required 1050eb982001SEduardo Valentin * to specify which GPIO line is used. TSHUT IRQ is fired anytime 1051eb982001SEduardo Valentin * one of the bandgap sensors violates the TSHUT high/hot threshold. 1052eb982001SEduardo Valentin * And in that case, the system must go off. 1053eb982001SEduardo Valentin * 1054eb982001SEduardo Valentin * Return: 0 if no error, else error status 1055eb982001SEduardo Valentin */ 1056eb982001SEduardo Valentin static int ti_bandgap_tshut_init(struct ti_bandgap *bgp, 1057eb982001SEduardo Valentin struct platform_device *pdev) 1058eb982001SEduardo Valentin { 1059eb982001SEduardo Valentin int gpio_nr = bgp->tshut_gpio; 1060eb982001SEduardo Valentin int status; 1061eb982001SEduardo Valentin 1062eb982001SEduardo Valentin /* Request for gpio_86 line */ 1063eb982001SEduardo Valentin status = gpio_request(gpio_nr, "tshut"); 1064eb982001SEduardo Valentin if (status < 0) { 1065eb982001SEduardo Valentin dev_err(bgp->dev, "Could not request for TSHUT GPIO:%i\n", 86); 1066eb982001SEduardo Valentin return status; 1067eb982001SEduardo Valentin } 1068eb982001SEduardo Valentin status = gpio_direction_input(gpio_nr); 1069eb982001SEduardo Valentin if (status) { 1070eb982001SEduardo Valentin dev_err(bgp->dev, "Cannot set input TSHUT GPIO %d\n", gpio_nr); 1071eb982001SEduardo Valentin return status; 1072eb982001SEduardo Valentin } 1073eb982001SEduardo Valentin 1074eb982001SEduardo Valentin status = request_irq(gpio_to_irq(gpio_nr), ti_bandgap_tshut_irq_handler, 1075eb982001SEduardo Valentin IRQF_TRIGGER_RISING, "tshut", NULL); 1076eb982001SEduardo Valentin if (status) { 1077eb982001SEduardo Valentin gpio_free(gpio_nr); 1078eb982001SEduardo Valentin dev_err(bgp->dev, "request irq failed for TSHUT"); 1079eb982001SEduardo Valentin } 1080eb982001SEduardo Valentin 1081eb982001SEduardo Valentin return 0; 1082eb982001SEduardo Valentin } 1083eb982001SEduardo Valentin 1084eb982001SEduardo Valentin /** 1085eb982001SEduardo Valentin * ti_bandgap_alert_init() - setup and initialize talert handling 1086eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 1087eb982001SEduardo Valentin * @pdev: pointer to device struct platform_device 1088eb982001SEduardo Valentin * 1089eb982001SEduardo Valentin * Call this function only in case the bandgap features HAS(TALERT). 1090eb982001SEduardo Valentin * In this case, the driver needs to handle the TALERT signals as an IRQs. 1091eb982001SEduardo Valentin * TALERT is a normal IRQ and it is fired any time thresholds (hot or cold) 1092eb982001SEduardo Valentin * are violated. In these situation, the driver must reprogram the thresholds, 1093eb982001SEduardo Valentin * accordingly to specified policy. 1094eb982001SEduardo Valentin * 1095eb982001SEduardo Valentin * Return: 0 if no error, else return corresponding error. 1096eb982001SEduardo Valentin */ 1097eb982001SEduardo Valentin static int ti_bandgap_talert_init(struct ti_bandgap *bgp, 1098eb982001SEduardo Valentin struct platform_device *pdev) 1099eb982001SEduardo Valentin { 1100eb982001SEduardo Valentin int ret; 1101eb982001SEduardo Valentin 1102eb982001SEduardo Valentin bgp->irq = platform_get_irq(pdev, 0); 1103eb982001SEduardo Valentin if (bgp->irq < 0) { 1104eb982001SEduardo Valentin dev_err(&pdev->dev, "get_irq failed\n"); 1105eb982001SEduardo Valentin return bgp->irq; 1106eb982001SEduardo Valentin } 1107eb982001SEduardo Valentin ret = request_threaded_irq(bgp->irq, NULL, 1108eb982001SEduardo Valentin ti_bandgap_talert_irq_handler, 1109eb982001SEduardo Valentin IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 1110eb982001SEduardo Valentin "talert", bgp); 1111eb982001SEduardo Valentin if (ret) { 1112eb982001SEduardo Valentin dev_err(&pdev->dev, "Request threaded irq failed.\n"); 1113eb982001SEduardo Valentin return ret; 1114eb982001SEduardo Valentin } 1115eb982001SEduardo Valentin 1116eb982001SEduardo Valentin return 0; 1117eb982001SEduardo Valentin } 1118eb982001SEduardo Valentin 1119eb982001SEduardo Valentin static const struct of_device_id of_ti_bandgap_match[]; 1120eb982001SEduardo Valentin /** 1121eb982001SEduardo Valentin * ti_bandgap_build() - parse DT and setup a struct ti_bandgap 1122eb982001SEduardo Valentin * @pdev: pointer to device struct platform_device 1123eb982001SEduardo Valentin * 1124eb982001SEduardo Valentin * Used to read the device tree properties accordingly to the bandgap 1125eb982001SEduardo Valentin * matching version. Based on bandgap version and its capabilities it 1126eb982001SEduardo Valentin * will build a struct ti_bandgap out of the required DT entries. 1127eb982001SEduardo Valentin * 1128eb982001SEduardo Valentin * Return: valid bandgap structure if successful, else returns ERR_PTR 1129eb982001SEduardo Valentin * return value must be verified with IS_ERR. 1130eb982001SEduardo Valentin */ 1131eb982001SEduardo Valentin static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) 1132eb982001SEduardo Valentin { 1133eb982001SEduardo Valentin struct device_node *node = pdev->dev.of_node; 1134eb982001SEduardo Valentin const struct of_device_id *of_id; 1135eb982001SEduardo Valentin struct ti_bandgap *bgp; 1136eb982001SEduardo Valentin struct resource *res; 1137eb982001SEduardo Valentin int i; 1138eb982001SEduardo Valentin 1139eb982001SEduardo Valentin /* just for the sake */ 1140eb982001SEduardo Valentin if (!node) { 1141eb982001SEduardo Valentin dev_err(&pdev->dev, "no platform information available\n"); 1142eb982001SEduardo Valentin return ERR_PTR(-EINVAL); 1143eb982001SEduardo Valentin } 1144eb982001SEduardo Valentin 1145eb982001SEduardo Valentin bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL); 1146eb982001SEduardo Valentin if (!bgp) { 1147eb982001SEduardo Valentin dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n"); 1148eb982001SEduardo Valentin return ERR_PTR(-ENOMEM); 1149eb982001SEduardo Valentin } 1150eb982001SEduardo Valentin 1151eb982001SEduardo Valentin of_id = of_match_device(of_ti_bandgap_match, &pdev->dev); 1152eb982001SEduardo Valentin if (of_id) 1153eb982001SEduardo Valentin bgp->conf = of_id->data; 1154eb982001SEduardo Valentin 1155eb982001SEduardo Valentin /* register shadow for context save and restore */ 1156eb982001SEduardo Valentin bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) * 1157eb982001SEduardo Valentin bgp->conf->sensor_count, GFP_KERNEL); 1158eb982001SEduardo Valentin if (!bgp) { 1159eb982001SEduardo Valentin dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n"); 1160eb982001SEduardo Valentin return ERR_PTR(-ENOMEM); 1161eb982001SEduardo Valentin } 1162eb982001SEduardo Valentin 1163eb982001SEduardo Valentin i = 0; 1164eb982001SEduardo Valentin do { 1165eb982001SEduardo Valentin void __iomem *chunk; 1166eb982001SEduardo Valentin 1167eb982001SEduardo Valentin res = platform_get_resource(pdev, IORESOURCE_MEM, i); 1168eb982001SEduardo Valentin if (!res) 1169eb982001SEduardo Valentin break; 1170eb982001SEduardo Valentin chunk = devm_ioremap_resource(&pdev->dev, res); 1171eb982001SEduardo Valentin if (i == 0) 1172eb982001SEduardo Valentin bgp->base = chunk; 1173eb982001SEduardo Valentin if (IS_ERR(chunk)) 1174eb982001SEduardo Valentin return ERR_CAST(chunk); 1175eb982001SEduardo Valentin 1176eb982001SEduardo Valentin i++; 1177eb982001SEduardo Valentin } while (res); 1178eb982001SEduardo Valentin 1179eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TSHUT)) { 118057d16171SEduardo Valentin bgp->tshut_gpio = of_get_gpio(node, 0); 1181eb982001SEduardo Valentin if (!gpio_is_valid(bgp->tshut_gpio)) { 1182eb982001SEduardo Valentin dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n", 1183eb982001SEduardo Valentin bgp->tshut_gpio); 1184eb982001SEduardo Valentin return ERR_PTR(-EINVAL); 1185eb982001SEduardo Valentin } 1186eb982001SEduardo Valentin } 1187eb982001SEduardo Valentin 1188eb982001SEduardo Valentin return bgp; 1189eb982001SEduardo Valentin } 1190eb982001SEduardo Valentin 1191eb982001SEduardo Valentin /*** Device driver call backs ***/ 1192eb982001SEduardo Valentin 1193eb982001SEduardo Valentin static 1194eb982001SEduardo Valentin int ti_bandgap_probe(struct platform_device *pdev) 1195eb982001SEduardo Valentin { 1196eb982001SEduardo Valentin struct ti_bandgap *bgp; 1197eb982001SEduardo Valentin int clk_rate, ret = 0, i; 1198eb982001SEduardo Valentin 1199eb982001SEduardo Valentin bgp = ti_bandgap_build(pdev); 12000c12b5acSEduardo Valentin if (IS_ERR(bgp)) { 1201eb982001SEduardo Valentin dev_err(&pdev->dev, "failed to fetch platform data\n"); 1202eb982001SEduardo Valentin return PTR_ERR(bgp); 1203eb982001SEduardo Valentin } 1204eb982001SEduardo Valentin bgp->dev = &pdev->dev; 1205eb982001SEduardo Valentin 1206eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1207eb982001SEduardo Valentin ret = ti_bandgap_tshut_init(bgp, pdev); 1208eb982001SEduardo Valentin if (ret) { 1209eb982001SEduardo Valentin dev_err(&pdev->dev, 1210eb982001SEduardo Valentin "failed to initialize system tshut IRQ\n"); 1211eb982001SEduardo Valentin return ret; 1212eb982001SEduardo Valentin } 1213eb982001SEduardo Valentin } 1214eb982001SEduardo Valentin 1215eb982001SEduardo Valentin bgp->fclock = clk_get(NULL, bgp->conf->fclock_name); 12160c12b5acSEduardo Valentin ret = IS_ERR(bgp->fclock); 1217eb982001SEduardo Valentin if (ret) { 1218eb982001SEduardo Valentin dev_err(&pdev->dev, "failed to request fclock reference\n"); 12190c12b5acSEduardo Valentin ret = PTR_ERR(bgp->fclock); 1220eb982001SEduardo Valentin goto free_irqs; 1221eb982001SEduardo Valentin } 1222eb982001SEduardo Valentin 1223eb982001SEduardo Valentin bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name); 12240c12b5acSEduardo Valentin ret = IS_ERR(bgp->div_clk); 1225eb982001SEduardo Valentin if (ret) { 1226eb982001SEduardo Valentin dev_err(&pdev->dev, 1227eb982001SEduardo Valentin "failed to request div_ts_ck clock ref\n"); 12280c12b5acSEduardo Valentin ret = PTR_ERR(bgp->div_clk); 1229eb982001SEduardo Valentin goto free_irqs; 1230eb982001SEduardo Valentin } 1231eb982001SEduardo Valentin 1232eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 1233eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 1234eb982001SEduardo Valentin u32 val; 1235eb982001SEduardo Valentin 1236eb982001SEduardo Valentin tsr = bgp->conf->sensors[i].registers; 1237eb982001SEduardo Valentin /* 1238eb982001SEduardo Valentin * check if the efuse has a non-zero value if not 1239eb982001SEduardo Valentin * it is an untrimmed sample and the temperatures 1240eb982001SEduardo Valentin * may not be accurate 1241eb982001SEduardo Valentin */ 1242eb982001SEduardo Valentin val = ti_bandgap_readl(bgp, tsr->bgap_efuse); 1243eb982001SEduardo Valentin if (ret || !val) 1244eb982001SEduardo Valentin dev_info(&pdev->dev, 1245eb982001SEduardo Valentin "Non-trimmed BGAP, Temp not accurate\n"); 1246eb982001SEduardo Valentin } 1247eb982001SEduardo Valentin 1248eb982001SEduardo Valentin clk_rate = clk_round_rate(bgp->div_clk, 1249eb982001SEduardo Valentin bgp->conf->sensors[0].ts_data->max_freq); 1250eb982001SEduardo Valentin if (clk_rate < bgp->conf->sensors[0].ts_data->min_freq || 1251eb982001SEduardo Valentin clk_rate == 0xffffffff) { 1252eb982001SEduardo Valentin ret = -ENODEV; 1253eb982001SEduardo Valentin dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate); 1254eb982001SEduardo Valentin goto put_clks; 1255eb982001SEduardo Valentin } 1256eb982001SEduardo Valentin 1257eb982001SEduardo Valentin ret = clk_set_rate(bgp->div_clk, clk_rate); 1258eb982001SEduardo Valentin if (ret) 1259eb982001SEduardo Valentin dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n"); 1260eb982001SEduardo Valentin 1261eb982001SEduardo Valentin bgp->clk_rate = clk_rate; 1262eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, CLK_CTRL)) 1263eb982001SEduardo Valentin clk_prepare_enable(bgp->fclock); 1264eb982001SEduardo Valentin 1265eb982001SEduardo Valentin 1266eb982001SEduardo Valentin spin_lock_init(&bgp->lock); 1267eb982001SEduardo Valentin bgp->dev = &pdev->dev; 1268eb982001SEduardo Valentin platform_set_drvdata(pdev, bgp); 1269eb982001SEduardo Valentin 1270eb982001SEduardo Valentin ti_bandgap_power(bgp, true); 1271eb982001SEduardo Valentin 1272eb982001SEduardo Valentin /* Set default counter to 1 for now */ 1273eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) 1274eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) 1275eb982001SEduardo Valentin RMW_BITS(bgp, i, bgap_counter, counter_mask, 1); 1276eb982001SEduardo Valentin 1277eb982001SEduardo Valentin /* Set default thresholds for alert and shutdown */ 1278eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 1279eb982001SEduardo Valentin struct temp_sensor_data *ts_data; 1280eb982001SEduardo Valentin 1281eb982001SEduardo Valentin ts_data = bgp->conf->sensors[i].ts_data; 1282eb982001SEduardo Valentin 1283eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TALERT)) { 1284eb982001SEduardo Valentin /* Set initial Talert thresholds */ 1285eb982001SEduardo Valentin RMW_BITS(bgp, i, bgap_threshold, 1286eb982001SEduardo Valentin threshold_tcold_mask, ts_data->t_cold); 1287eb982001SEduardo Valentin RMW_BITS(bgp, i, bgap_threshold, 1288eb982001SEduardo Valentin threshold_thot_mask, ts_data->t_hot); 1289eb982001SEduardo Valentin /* Enable the alert events */ 1290eb982001SEduardo Valentin RMW_BITS(bgp, i, bgap_mask_ctrl, mask_hot_mask, 1); 1291eb982001SEduardo Valentin RMW_BITS(bgp, i, bgap_mask_ctrl, mask_cold_mask, 1); 1292eb982001SEduardo Valentin } 1293eb982001SEduardo Valentin 1294eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) { 1295eb982001SEduardo Valentin /* Set initial Tshut thresholds */ 1296eb982001SEduardo Valentin RMW_BITS(bgp, i, tshut_threshold, 1297eb982001SEduardo Valentin tshut_hot_mask, ts_data->tshut_hot); 1298eb982001SEduardo Valentin RMW_BITS(bgp, i, tshut_threshold, 1299eb982001SEduardo Valentin tshut_cold_mask, ts_data->tshut_cold); 1300eb982001SEduardo Valentin } 1301eb982001SEduardo Valentin } 1302eb982001SEduardo Valentin 1303eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, MODE_CONFIG)) 1304eb982001SEduardo Valentin ti_bandgap_set_continuous_mode(bgp); 1305eb982001SEduardo Valentin 1306eb982001SEduardo Valentin /* Set .250 seconds time as default counter */ 1307eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) 1308eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) 1309eb982001SEduardo Valentin RMW_BITS(bgp, i, bgap_counter, counter_mask, 1310eb982001SEduardo Valentin bgp->clk_rate / 4); 1311eb982001SEduardo Valentin 1312eb982001SEduardo Valentin /* Every thing is good? Then expose the sensors */ 1313eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 1314eb982001SEduardo Valentin char *domain; 1315eb982001SEduardo Valentin 1316eb982001SEduardo Valentin if (bgp->conf->sensors[i].register_cooling) { 1317eb982001SEduardo Valentin ret = bgp->conf->sensors[i].register_cooling(bgp, i); 1318eb982001SEduardo Valentin if (ret) 1319eb982001SEduardo Valentin goto remove_sensors; 1320eb982001SEduardo Valentin } 1321eb982001SEduardo Valentin 1322eb982001SEduardo Valentin if (bgp->conf->expose_sensor) { 1323eb982001SEduardo Valentin domain = bgp->conf->sensors[i].domain; 1324eb982001SEduardo Valentin ret = bgp->conf->expose_sensor(bgp, i, domain); 1325eb982001SEduardo Valentin if (ret) 1326eb982001SEduardo Valentin goto remove_last_cooling; 1327eb982001SEduardo Valentin } 1328eb982001SEduardo Valentin } 1329eb982001SEduardo Valentin 1330eb982001SEduardo Valentin /* 1331eb982001SEduardo Valentin * Enable the Interrupts once everything is set. Otherwise irq handler 1332eb982001SEduardo Valentin * might be called as soon as it is enabled where as rest of framework 1333eb982001SEduardo Valentin * is still getting initialised. 1334eb982001SEduardo Valentin */ 1335eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TALERT)) { 1336eb982001SEduardo Valentin ret = ti_bandgap_talert_init(bgp, pdev); 1337eb982001SEduardo Valentin if (ret) { 1338eb982001SEduardo Valentin dev_err(&pdev->dev, "failed to initialize Talert IRQ\n"); 1339eb982001SEduardo Valentin i = bgp->conf->sensor_count; 1340eb982001SEduardo Valentin goto disable_clk; 1341eb982001SEduardo Valentin } 1342eb982001SEduardo Valentin } 1343eb982001SEduardo Valentin 1344eb982001SEduardo Valentin return 0; 1345eb982001SEduardo Valentin 1346eb982001SEduardo Valentin remove_last_cooling: 1347eb982001SEduardo Valentin if (bgp->conf->sensors[i].unregister_cooling) 1348eb982001SEduardo Valentin bgp->conf->sensors[i].unregister_cooling(bgp, i); 1349eb982001SEduardo Valentin remove_sensors: 1350eb982001SEduardo Valentin for (i--; i >= 0; i--) { 1351eb982001SEduardo Valentin if (bgp->conf->sensors[i].unregister_cooling) 1352eb982001SEduardo Valentin bgp->conf->sensors[i].unregister_cooling(bgp, i); 1353eb982001SEduardo Valentin if (bgp->conf->remove_sensor) 1354eb982001SEduardo Valentin bgp->conf->remove_sensor(bgp, i); 1355eb982001SEduardo Valentin } 1356eb982001SEduardo Valentin ti_bandgap_power(bgp, false); 1357eb982001SEduardo Valentin disable_clk: 1358eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, CLK_CTRL)) 1359eb982001SEduardo Valentin clk_disable_unprepare(bgp->fclock); 1360eb982001SEduardo Valentin put_clks: 1361eb982001SEduardo Valentin clk_put(bgp->fclock); 1362eb982001SEduardo Valentin clk_put(bgp->div_clk); 1363eb982001SEduardo Valentin free_irqs: 1364eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1365eb982001SEduardo Valentin free_irq(gpio_to_irq(bgp->tshut_gpio), NULL); 1366eb982001SEduardo Valentin gpio_free(bgp->tshut_gpio); 1367eb982001SEduardo Valentin } 1368eb982001SEduardo Valentin 1369eb982001SEduardo Valentin return ret; 1370eb982001SEduardo Valentin } 1371eb982001SEduardo Valentin 1372eb982001SEduardo Valentin static 1373eb982001SEduardo Valentin int ti_bandgap_remove(struct platform_device *pdev) 1374eb982001SEduardo Valentin { 1375eb982001SEduardo Valentin struct ti_bandgap *bgp = platform_get_drvdata(pdev); 1376eb982001SEduardo Valentin int i; 1377eb982001SEduardo Valentin 1378eb982001SEduardo Valentin /* First thing is to remove sensor interfaces */ 1379eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 1380eb982001SEduardo Valentin if (bgp->conf->sensors[i].unregister_cooling) 1381eb982001SEduardo Valentin bgp->conf->sensors[i].unregister_cooling(bgp, i); 1382eb982001SEduardo Valentin 1383eb982001SEduardo Valentin if (bgp->conf->remove_sensor) 1384eb982001SEduardo Valentin bgp->conf->remove_sensor(bgp, i); 1385eb982001SEduardo Valentin } 1386eb982001SEduardo Valentin 1387eb982001SEduardo Valentin ti_bandgap_power(bgp, false); 1388eb982001SEduardo Valentin 1389eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, CLK_CTRL)) 1390eb982001SEduardo Valentin clk_disable_unprepare(bgp->fclock); 1391eb982001SEduardo Valentin clk_put(bgp->fclock); 1392eb982001SEduardo Valentin clk_put(bgp->div_clk); 1393eb982001SEduardo Valentin 1394eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TALERT)) 1395eb982001SEduardo Valentin free_irq(bgp->irq, bgp); 1396eb982001SEduardo Valentin 1397eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1398eb982001SEduardo Valentin free_irq(gpio_to_irq(bgp->tshut_gpio), NULL); 1399eb982001SEduardo Valentin gpio_free(bgp->tshut_gpio); 1400eb982001SEduardo Valentin } 1401eb982001SEduardo Valentin 1402eb982001SEduardo Valentin return 0; 1403eb982001SEduardo Valentin } 1404eb982001SEduardo Valentin 1405eb982001SEduardo Valentin #ifdef CONFIG_PM 1406eb982001SEduardo Valentin static int ti_bandgap_save_ctxt(struct ti_bandgap *bgp) 1407eb982001SEduardo Valentin { 1408eb982001SEduardo Valentin int i; 1409eb982001SEduardo Valentin 1410eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 1411eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 1412eb982001SEduardo Valentin struct temp_sensor_regval *rval; 1413eb982001SEduardo Valentin 1414eb982001SEduardo Valentin rval = &bgp->regval[i]; 1415eb982001SEduardo Valentin tsr = bgp->conf->sensors[i].registers; 1416eb982001SEduardo Valentin 1417eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, MODE_CONFIG)) 1418eb982001SEduardo Valentin rval->bg_mode_ctrl = ti_bandgap_readl(bgp, 1419eb982001SEduardo Valentin tsr->bgap_mode_ctrl); 1420eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) 1421eb982001SEduardo Valentin rval->bg_counter = ti_bandgap_readl(bgp, 1422eb982001SEduardo Valentin tsr->bgap_counter); 1423eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TALERT)) { 1424eb982001SEduardo Valentin rval->bg_threshold = ti_bandgap_readl(bgp, 1425eb982001SEduardo Valentin tsr->bgap_threshold); 1426eb982001SEduardo Valentin rval->bg_ctrl = ti_bandgap_readl(bgp, 1427eb982001SEduardo Valentin tsr->bgap_mask_ctrl); 1428eb982001SEduardo Valentin } 1429eb982001SEduardo Valentin 1430eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) 1431eb982001SEduardo Valentin rval->tshut_threshold = ti_bandgap_readl(bgp, 1432eb982001SEduardo Valentin tsr->tshut_threshold); 1433eb982001SEduardo Valentin } 1434eb982001SEduardo Valentin 1435eb982001SEduardo Valentin return 0; 1436eb982001SEduardo Valentin } 1437eb982001SEduardo Valentin 1438eb982001SEduardo Valentin static int ti_bandgap_restore_ctxt(struct ti_bandgap *bgp) 1439eb982001SEduardo Valentin { 1440eb982001SEduardo Valentin int i; 1441eb982001SEduardo Valentin 1442eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 1443eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 1444eb982001SEduardo Valentin struct temp_sensor_regval *rval; 1445eb982001SEduardo Valentin u32 val = 0; 1446eb982001SEduardo Valentin 1447eb982001SEduardo Valentin rval = &bgp->regval[i]; 1448eb982001SEduardo Valentin tsr = bgp->conf->sensors[i].registers; 1449eb982001SEduardo Valentin 1450eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) 1451eb982001SEduardo Valentin val = ti_bandgap_readl(bgp, tsr->bgap_counter); 1452eb982001SEduardo Valentin 1453eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) 1454eb982001SEduardo Valentin ti_bandgap_writel(bgp, rval->tshut_threshold, 1455eb982001SEduardo Valentin tsr->tshut_threshold); 1456eb982001SEduardo Valentin /* Force immediate temperature measurement and update 1457eb982001SEduardo Valentin * of the DTEMP field 1458eb982001SEduardo Valentin */ 1459eb982001SEduardo Valentin ti_bandgap_force_single_read(bgp, i); 1460eb982001SEduardo Valentin 1461eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) 1462eb982001SEduardo Valentin ti_bandgap_writel(bgp, rval->bg_counter, 1463eb982001SEduardo Valentin tsr->bgap_counter); 1464eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, MODE_CONFIG)) 1465eb982001SEduardo Valentin ti_bandgap_writel(bgp, rval->bg_mode_ctrl, 1466eb982001SEduardo Valentin tsr->bgap_mode_ctrl); 1467eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TALERT)) { 1468eb982001SEduardo Valentin ti_bandgap_writel(bgp, rval->bg_threshold, 1469eb982001SEduardo Valentin tsr->bgap_threshold); 1470eb982001SEduardo Valentin ti_bandgap_writel(bgp, rval->bg_ctrl, 1471eb982001SEduardo Valentin tsr->bgap_mask_ctrl); 1472eb982001SEduardo Valentin } 1473eb982001SEduardo Valentin } 1474eb982001SEduardo Valentin 1475eb982001SEduardo Valentin return 0; 1476eb982001SEduardo Valentin } 1477eb982001SEduardo Valentin 1478eb982001SEduardo Valentin static int ti_bandgap_suspend(struct device *dev) 1479eb982001SEduardo Valentin { 1480eb982001SEduardo Valentin struct ti_bandgap *bgp = dev_get_drvdata(dev); 1481eb982001SEduardo Valentin int err; 1482eb982001SEduardo Valentin 1483eb982001SEduardo Valentin err = ti_bandgap_save_ctxt(bgp); 1484eb982001SEduardo Valentin ti_bandgap_power(bgp, false); 1485eb982001SEduardo Valentin 1486eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, CLK_CTRL)) 1487eb982001SEduardo Valentin clk_disable_unprepare(bgp->fclock); 1488eb982001SEduardo Valentin 1489eb982001SEduardo Valentin return err; 1490eb982001SEduardo Valentin } 1491eb982001SEduardo Valentin 1492eb982001SEduardo Valentin static int ti_bandgap_resume(struct device *dev) 1493eb982001SEduardo Valentin { 1494eb982001SEduardo Valentin struct ti_bandgap *bgp = dev_get_drvdata(dev); 1495eb982001SEduardo Valentin 1496eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, CLK_CTRL)) 1497eb982001SEduardo Valentin clk_prepare_enable(bgp->fclock); 1498eb982001SEduardo Valentin 1499eb982001SEduardo Valentin ti_bandgap_power(bgp, true); 1500eb982001SEduardo Valentin 1501eb982001SEduardo Valentin return ti_bandgap_restore_ctxt(bgp); 1502eb982001SEduardo Valentin } 1503eb982001SEduardo Valentin static const struct dev_pm_ops ti_bandgap_dev_pm_ops = { 1504eb982001SEduardo Valentin SET_SYSTEM_SLEEP_PM_OPS(ti_bandgap_suspend, 1505eb982001SEduardo Valentin ti_bandgap_resume) 1506eb982001SEduardo Valentin }; 1507eb982001SEduardo Valentin 1508eb982001SEduardo Valentin #define DEV_PM_OPS (&ti_bandgap_dev_pm_ops) 1509eb982001SEduardo Valentin #else 1510eb982001SEduardo Valentin #define DEV_PM_OPS NULL 1511eb982001SEduardo Valentin #endif 1512eb982001SEduardo Valentin 1513eb982001SEduardo Valentin static const struct of_device_id of_ti_bandgap_match[] = { 1514eb982001SEduardo Valentin #ifdef CONFIG_OMAP4_THERMAL 1515eb982001SEduardo Valentin { 1516eb982001SEduardo Valentin .compatible = "ti,omap4430-bandgap", 1517eb982001SEduardo Valentin .data = (void *)&omap4430_data, 1518eb982001SEduardo Valentin }, 1519eb982001SEduardo Valentin { 1520eb982001SEduardo Valentin .compatible = "ti,omap4460-bandgap", 1521eb982001SEduardo Valentin .data = (void *)&omap4460_data, 1522eb982001SEduardo Valentin }, 1523eb982001SEduardo Valentin { 1524eb982001SEduardo Valentin .compatible = "ti,omap4470-bandgap", 1525eb982001SEduardo Valentin .data = (void *)&omap4470_data, 1526eb982001SEduardo Valentin }, 1527eb982001SEduardo Valentin #endif 1528eb982001SEduardo Valentin #ifdef CONFIG_OMAP5_THERMAL 1529eb982001SEduardo Valentin { 1530eb982001SEduardo Valentin .compatible = "ti,omap5430-bandgap", 1531eb982001SEduardo Valentin .data = (void *)&omap5430_data, 1532eb982001SEduardo Valentin }, 1533eb982001SEduardo Valentin #endif 153425870e62SEduardo Valentin #ifdef CONFIG_DRA752_THERMAL 153525870e62SEduardo Valentin { 153625870e62SEduardo Valentin .compatible = "ti,dra752-bandgap", 153725870e62SEduardo Valentin .data = (void *)&dra752_data, 153825870e62SEduardo Valentin }, 153925870e62SEduardo Valentin #endif 1540eb982001SEduardo Valentin /* Sentinel */ 1541eb982001SEduardo Valentin { }, 1542eb982001SEduardo Valentin }; 1543eb982001SEduardo Valentin MODULE_DEVICE_TABLE(of, of_ti_bandgap_match); 1544eb982001SEduardo Valentin 1545eb982001SEduardo Valentin static struct platform_driver ti_bandgap_sensor_driver = { 1546eb982001SEduardo Valentin .probe = ti_bandgap_probe, 1547eb982001SEduardo Valentin .remove = ti_bandgap_remove, 1548eb982001SEduardo Valentin .driver = { 1549eb982001SEduardo Valentin .name = "ti-soc-thermal", 1550eb982001SEduardo Valentin .pm = DEV_PM_OPS, 1551eb982001SEduardo Valentin .of_match_table = of_ti_bandgap_match, 1552eb982001SEduardo Valentin }, 1553eb982001SEduardo Valentin }; 1554eb982001SEduardo Valentin 1555eb982001SEduardo Valentin module_platform_driver(ti_bandgap_sensor_driver); 1556eb982001SEduardo Valentin 1557eb982001SEduardo Valentin MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver"); 1558eb982001SEduardo Valentin MODULE_LICENSE("GPL v2"); 1559eb982001SEduardo Valentin MODULE_ALIAS("platform:ti-soc-thermal"); 1560eb982001SEduardo Valentin MODULE_AUTHOR("Texas Instrument Inc."); 1561