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> 41eb982001SEduardo Valentin #include <linux/io.h> 42eb982001SEduardo Valentin 43eb982001SEduardo Valentin #include "ti-bandgap.h" 44eb982001SEduardo Valentin 45eb982001SEduardo Valentin /*** Helper functions to access registers and their bitfields ***/ 46eb982001SEduardo Valentin 47eb982001SEduardo Valentin /** 48eb982001SEduardo Valentin * ti_bandgap_readl() - simple read helper function 49eb982001SEduardo Valentin * @bgp: pointer to ti_bandgap structure 50eb982001SEduardo Valentin * @reg: desired register (offset) to be read 51eb982001SEduardo Valentin * 52eb982001SEduardo Valentin * Helper function to read bandgap registers. It uses the io remapped area. 53eb982001SEduardo Valentin * Return: the register value. 54eb982001SEduardo Valentin */ 55eb982001SEduardo Valentin static u32 ti_bandgap_readl(struct ti_bandgap *bgp, u32 reg) 56eb982001SEduardo Valentin { 57eb982001SEduardo Valentin return readl(bgp->base + reg); 58eb982001SEduardo Valentin } 59eb982001SEduardo Valentin 60eb982001SEduardo Valentin /** 61eb982001SEduardo Valentin * ti_bandgap_writel() - simple write helper function 62eb982001SEduardo Valentin * @bgp: pointer to ti_bandgap structure 63eb982001SEduardo Valentin * @val: desired register value to be written 64eb982001SEduardo Valentin * @reg: desired register (offset) to be written 65eb982001SEduardo Valentin * 66eb982001SEduardo Valentin * Helper function to write bandgap registers. It uses the io remapped area. 67eb982001SEduardo Valentin */ 68eb982001SEduardo Valentin static void ti_bandgap_writel(struct ti_bandgap *bgp, u32 val, u32 reg) 69eb982001SEduardo Valentin { 70eb982001SEduardo Valentin writel(val, bgp->base + reg); 71eb982001SEduardo Valentin } 72eb982001SEduardo Valentin 73eb982001SEduardo Valentin /** 74eb982001SEduardo Valentin * DOC: macro to update bits. 75eb982001SEduardo Valentin * 76eb982001SEduardo Valentin * RMW_BITS() - used to read, modify and update bandgap bitfields. 77eb982001SEduardo Valentin * The value passed will be shifted. 78eb982001SEduardo Valentin */ 79eb982001SEduardo Valentin #define RMW_BITS(bgp, id, reg, mask, val) \ 80eb982001SEduardo Valentin do { \ 81eb982001SEduardo Valentin struct temp_sensor_registers *t; \ 82eb982001SEduardo Valentin u32 r; \ 83eb982001SEduardo Valentin \ 84eb982001SEduardo Valentin t = bgp->conf->sensors[(id)].registers; \ 85eb982001SEduardo Valentin r = ti_bandgap_readl(bgp, t->reg); \ 86eb982001SEduardo Valentin r &= ~t->mask; \ 87eb982001SEduardo Valentin r |= (val) << __ffs(t->mask); \ 88eb982001SEduardo Valentin ti_bandgap_writel(bgp, r, t->reg); \ 89eb982001SEduardo Valentin } while (0) 90eb982001SEduardo Valentin 91eb982001SEduardo Valentin /*** Basic helper functions ***/ 92eb982001SEduardo Valentin 93eb982001SEduardo Valentin /** 94eb982001SEduardo Valentin * ti_bandgap_power() - controls the power state of a bandgap device 95eb982001SEduardo Valentin * @bgp: pointer to ti_bandgap structure 96eb982001SEduardo Valentin * @on: desired power state (1 - on, 0 - off) 97eb982001SEduardo Valentin * 98eb982001SEduardo Valentin * Used to power on/off a bandgap device instance. Only used on those 99eb982001SEduardo Valentin * that features tempsoff bit. 100eb982001SEduardo Valentin * 101eb982001SEduardo Valentin * Return: 0 on success, -ENOTSUPP if tempsoff is not supported. 102eb982001SEduardo Valentin */ 103eb982001SEduardo Valentin static int ti_bandgap_power(struct ti_bandgap *bgp, bool on) 104eb982001SEduardo Valentin { 105eb982001SEduardo Valentin int i, ret = 0; 106eb982001SEduardo Valentin 107eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH)) { 108eb982001SEduardo Valentin ret = -ENOTSUPP; 109eb982001SEduardo Valentin goto exit; 110eb982001SEduardo Valentin } 111eb982001SEduardo Valentin 112eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) 113eb982001SEduardo Valentin /* active on 0 */ 114eb982001SEduardo Valentin RMW_BITS(bgp, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on); 115eb982001SEduardo Valentin 116eb982001SEduardo Valentin exit: 117eb982001SEduardo Valentin return ret; 118eb982001SEduardo Valentin } 119eb982001SEduardo Valentin 120eb982001SEduardo Valentin /** 121eb982001SEduardo Valentin * ti_bandgap_read_temp() - helper function to read sensor temperature 122eb982001SEduardo Valentin * @bgp: pointer to ti_bandgap structure 123eb982001SEduardo Valentin * @id: bandgap sensor id 124eb982001SEduardo Valentin * 125eb982001SEduardo Valentin * Function to concentrate the steps to read sensor temperature register. 126eb982001SEduardo Valentin * This function is desired because, depending on bandgap device version, 127eb982001SEduardo Valentin * it might be needed to freeze the bandgap state machine, before fetching 128eb982001SEduardo Valentin * the register value. 129eb982001SEduardo Valentin * 130eb982001SEduardo Valentin * Return: temperature in ADC values. 131eb982001SEduardo Valentin */ 132eb982001SEduardo Valentin static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id) 133eb982001SEduardo Valentin { 134eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 135eb982001SEduardo Valentin u32 temp, reg; 136eb982001SEduardo Valentin 137eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 138eb982001SEduardo Valentin reg = tsr->temp_sensor_ctrl; 139eb982001SEduardo Valentin 140eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) { 141eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1); 142eb982001SEduardo Valentin /* 143eb982001SEduardo Valentin * In case we cannot read from cur_dtemp / dtemp_0, 144eb982001SEduardo Valentin * then we read from the last valid temp read 145eb982001SEduardo Valentin */ 146eb982001SEduardo Valentin reg = tsr->ctrl_dtemp_1; 147eb982001SEduardo Valentin } 148eb982001SEduardo Valentin 149eb982001SEduardo Valentin /* read temperature */ 150eb982001SEduardo Valentin temp = ti_bandgap_readl(bgp, reg); 151eb982001SEduardo Valentin temp &= tsr->bgap_dtemp_mask; 152eb982001SEduardo Valentin 153eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) 154eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0); 155eb982001SEduardo Valentin 156eb982001SEduardo Valentin return temp; 157eb982001SEduardo Valentin } 158eb982001SEduardo Valentin 159eb982001SEduardo Valentin /*** IRQ handlers ***/ 160eb982001SEduardo Valentin 161eb982001SEduardo Valentin /** 162eb982001SEduardo Valentin * ti_bandgap_talert_irq_handler() - handles Temperature alert IRQs 163eb982001SEduardo Valentin * @irq: IRQ number 164eb982001SEduardo Valentin * @data: private data (struct ti_bandgap *) 165eb982001SEduardo Valentin * 166eb982001SEduardo Valentin * This is the Talert handler. Use it only if bandgap device features 167eb982001SEduardo Valentin * HAS(TALERT). This handler goes over all sensors and checks their 168eb982001SEduardo Valentin * conditions and acts accordingly. In case there are events pending, 169eb982001SEduardo Valentin * it will reset the event mask to wait for the opposite event (next event). 170eb982001SEduardo Valentin * Every time there is a new event, it will be reported to thermal layer. 171eb982001SEduardo Valentin * 172eb982001SEduardo Valentin * Return: IRQ_HANDLED 173eb982001SEduardo Valentin */ 174eb982001SEduardo Valentin static irqreturn_t ti_bandgap_talert_irq_handler(int irq, void *data) 175eb982001SEduardo Valentin { 176eb982001SEduardo Valentin struct ti_bandgap *bgp = data; 177eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 178eb982001SEduardo Valentin u32 t_hot = 0, t_cold = 0, ctrl; 179eb982001SEduardo Valentin int i; 180eb982001SEduardo Valentin 181eb982001SEduardo Valentin spin_lock(&bgp->lock); 182eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 183eb982001SEduardo Valentin tsr = bgp->conf->sensors[i].registers; 184eb982001SEduardo Valentin ctrl = ti_bandgap_readl(bgp, tsr->bgap_status); 185eb982001SEduardo Valentin 186eb982001SEduardo Valentin /* Read the status of t_hot */ 187eb982001SEduardo Valentin t_hot = ctrl & tsr->status_hot_mask; 188eb982001SEduardo Valentin 189eb982001SEduardo Valentin /* Read the status of t_cold */ 190eb982001SEduardo Valentin t_cold = ctrl & tsr->status_cold_mask; 191eb982001SEduardo Valentin 192eb982001SEduardo Valentin if (!t_cold && !t_hot) 193eb982001SEduardo Valentin continue; 194eb982001SEduardo Valentin 195eb982001SEduardo Valentin ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); 196eb982001SEduardo Valentin /* 197eb982001SEduardo Valentin * One TALERT interrupt: Two sources 198eb982001SEduardo Valentin * If the interrupt is due to t_hot then mask t_hot and 199eb982001SEduardo Valentin * and unmask t_cold else mask t_cold and unmask t_hot 200eb982001SEduardo Valentin */ 201eb982001SEduardo Valentin if (t_hot) { 202eb982001SEduardo Valentin ctrl &= ~tsr->mask_hot_mask; 203eb982001SEduardo Valentin ctrl |= tsr->mask_cold_mask; 204eb982001SEduardo Valentin } else if (t_cold) { 205eb982001SEduardo Valentin ctrl &= ~tsr->mask_cold_mask; 206eb982001SEduardo Valentin ctrl |= tsr->mask_hot_mask; 207eb982001SEduardo Valentin } 208eb982001SEduardo Valentin 209eb982001SEduardo Valentin ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl); 210eb982001SEduardo Valentin 211eb982001SEduardo Valentin dev_dbg(bgp->dev, 212eb982001SEduardo Valentin "%s: IRQ from %s sensor: hotevent %d coldevent %d\n", 213eb982001SEduardo Valentin __func__, bgp->conf->sensors[i].domain, 214eb982001SEduardo Valentin t_hot, t_cold); 215eb982001SEduardo Valentin 216eb982001SEduardo Valentin /* report temperature to whom may concern */ 217eb982001SEduardo Valentin if (bgp->conf->report_temperature) 218eb982001SEduardo Valentin bgp->conf->report_temperature(bgp, i); 219eb982001SEduardo Valentin } 220eb982001SEduardo Valentin spin_unlock(&bgp->lock); 221eb982001SEduardo Valentin 222eb982001SEduardo Valentin return IRQ_HANDLED; 223eb982001SEduardo Valentin } 224eb982001SEduardo Valentin 225eb982001SEduardo Valentin /** 226eb982001SEduardo Valentin * ti_bandgap_tshut_irq_handler() - handles Temperature shutdown signal 227eb982001SEduardo Valentin * @irq: IRQ number 228eb982001SEduardo Valentin * @data: private data (unused) 229eb982001SEduardo Valentin * 230eb982001SEduardo Valentin * This is the Tshut handler. Use it only if bandgap device features 231eb982001SEduardo Valentin * HAS(TSHUT). If any sensor fires the Tshut signal, we simply shutdown 232eb982001SEduardo Valentin * the system. 233eb982001SEduardo Valentin * 234eb982001SEduardo Valentin * Return: IRQ_HANDLED 235eb982001SEduardo Valentin */ 236eb982001SEduardo Valentin static irqreturn_t ti_bandgap_tshut_irq_handler(int irq, void *data) 237eb982001SEduardo Valentin { 238eb982001SEduardo Valentin pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n", 239eb982001SEduardo Valentin __func__); 240eb982001SEduardo Valentin 241eb982001SEduardo Valentin orderly_poweroff(true); 242eb982001SEduardo Valentin 243eb982001SEduardo Valentin return IRQ_HANDLED; 244eb982001SEduardo Valentin } 245eb982001SEduardo Valentin 246eb982001SEduardo Valentin /*** Helper functions which manipulate conversion ADC <-> mi Celsius ***/ 247eb982001SEduardo Valentin 248eb982001SEduardo Valentin /** 249eb982001SEduardo Valentin * ti_bandgap_adc_to_mcelsius() - converts an ADC value to mCelsius scale 250eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 251eb982001SEduardo Valentin * @adc_val: value in ADC representation 252eb982001SEduardo Valentin * @t: address where to write the resulting temperature in mCelsius 253eb982001SEduardo Valentin * 254eb982001SEduardo Valentin * Simple conversion from ADC representation to mCelsius. In case the ADC value 255eb982001SEduardo Valentin * is out of the ADC conv table range, it returns -ERANGE, 0 on success. 256eb982001SEduardo Valentin * The conversion table is indexed by the ADC values. 257eb982001SEduardo Valentin * 258eb982001SEduardo Valentin * Return: 0 if conversion was successful, else -ERANGE in case the @adc_val 259eb982001SEduardo Valentin * argument is out of the ADC conv table range. 260eb982001SEduardo Valentin */ 261eb982001SEduardo Valentin static 262eb982001SEduardo Valentin int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t) 263eb982001SEduardo Valentin { 264eb982001SEduardo Valentin const struct ti_bandgap_data *conf = bgp->conf; 265eb982001SEduardo Valentin int ret = 0; 266eb982001SEduardo Valentin 267eb982001SEduardo Valentin /* look up for temperature in the table and return the temperature */ 268eb982001SEduardo Valentin if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val) { 269eb982001SEduardo Valentin ret = -ERANGE; 270eb982001SEduardo Valentin goto exit; 271eb982001SEduardo Valentin } 272eb982001SEduardo Valentin 273eb982001SEduardo Valentin *t = bgp->conf->conv_table[adc_val - conf->adc_start_val]; 274eb982001SEduardo Valentin 275eb982001SEduardo Valentin exit: 276eb982001SEduardo Valentin return ret; 277eb982001SEduardo Valentin } 278eb982001SEduardo Valentin 279eb982001SEduardo Valentin /** 280eb982001SEduardo Valentin * ti_bandgap_mcelsius_to_adc() - converts a mCelsius value to ADC scale 281eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 282eb982001SEduardo Valentin * @temp: value in mCelsius 283eb982001SEduardo Valentin * @adc: address where to write the resulting temperature in ADC representation 284eb982001SEduardo Valentin * 285eb982001SEduardo Valentin * Simple conversion from mCelsius to ADC values. In case the temp value 286eb982001SEduardo Valentin * is out of the ADC conv table range, it returns -ERANGE, 0 on success. 287eb982001SEduardo Valentin * The conversion table is indexed by the ADC values. 288eb982001SEduardo Valentin * 289eb982001SEduardo Valentin * Return: 0 if conversion was successful, else -ERANGE in case the @temp 290eb982001SEduardo Valentin * argument is out of the ADC conv table range. 291eb982001SEduardo Valentin */ 292eb982001SEduardo Valentin static 293eb982001SEduardo Valentin int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc) 294eb982001SEduardo Valentin { 295eb982001SEduardo Valentin const struct ti_bandgap_data *conf = bgp->conf; 296eb982001SEduardo Valentin const int *conv_table = bgp->conf->conv_table; 297eb982001SEduardo Valentin int high, low, mid, ret = 0; 298eb982001SEduardo Valentin 299eb982001SEduardo Valentin low = 0; 300eb982001SEduardo Valentin high = conf->adc_end_val - conf->adc_start_val; 301eb982001SEduardo Valentin mid = (high + low) / 2; 302eb982001SEduardo Valentin 303eb982001SEduardo Valentin if (temp < conv_table[low] || temp > conv_table[high]) { 304eb982001SEduardo Valentin ret = -ERANGE; 305eb982001SEduardo Valentin goto exit; 306eb982001SEduardo Valentin } 307eb982001SEduardo Valentin 308eb982001SEduardo Valentin while (low < high) { 309eb982001SEduardo Valentin if (temp < conv_table[mid]) 310eb982001SEduardo Valentin high = mid - 1; 311eb982001SEduardo Valentin else 312eb982001SEduardo Valentin low = mid + 1; 313eb982001SEduardo Valentin mid = (low + high) / 2; 314eb982001SEduardo Valentin } 315eb982001SEduardo Valentin 316eb982001SEduardo Valentin *adc = conf->adc_start_val + low; 317eb982001SEduardo Valentin 318eb982001SEduardo Valentin exit: 319eb982001SEduardo Valentin return ret; 320eb982001SEduardo Valentin } 321eb982001SEduardo Valentin 322eb982001SEduardo Valentin /** 323eb982001SEduardo Valentin * ti_bandgap_add_hyst() - add hysteresis (in mCelsius) to an ADC value 324eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 325eb982001SEduardo Valentin * @adc_val: temperature value in ADC representation 326eb982001SEduardo Valentin * @hyst_val: hysteresis value in mCelsius 327eb982001SEduardo Valentin * @sum: address where to write the resulting temperature (in ADC scale) 328eb982001SEduardo Valentin * 329eb982001SEduardo Valentin * Adds an hysteresis value (in mCelsius) to a ADC temperature value. 330eb982001SEduardo Valentin * 331eb982001SEduardo Valentin * Return: 0 on success, -ERANGE otherwise. 332eb982001SEduardo Valentin */ 333eb982001SEduardo Valentin static 334eb982001SEduardo Valentin int ti_bandgap_add_hyst(struct ti_bandgap *bgp, int adc_val, int hyst_val, 335eb982001SEduardo Valentin u32 *sum) 336eb982001SEduardo Valentin { 337eb982001SEduardo Valentin int temp, ret; 338eb982001SEduardo Valentin 339eb982001SEduardo Valentin /* 340eb982001SEduardo Valentin * Need to add in the mcelsius domain, so we have a temperature 341eb982001SEduardo Valentin * the conv_table range 342eb982001SEduardo Valentin */ 343eb982001SEduardo Valentin ret = ti_bandgap_adc_to_mcelsius(bgp, adc_val, &temp); 344eb982001SEduardo Valentin if (ret < 0) 345eb982001SEduardo Valentin goto exit; 346eb982001SEduardo Valentin 347eb982001SEduardo Valentin temp += hyst_val; 348eb982001SEduardo Valentin 349eb982001SEduardo Valentin ret = ti_bandgap_mcelsius_to_adc(bgp, temp, sum); 350eb982001SEduardo Valentin 351eb982001SEduardo Valentin exit: 352eb982001SEduardo Valentin return ret; 353eb982001SEduardo Valentin } 354eb982001SEduardo Valentin 355eb982001SEduardo Valentin /*** Helper functions handling device Alert/Shutdown signals ***/ 356eb982001SEduardo Valentin 357eb982001SEduardo Valentin /** 358eb982001SEduardo Valentin * ti_bandgap_unmask_interrupts() - unmasks the events of thot & tcold 359eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 360eb982001SEduardo Valentin * @id: bandgap sensor id 361eb982001SEduardo Valentin * @t_hot: hot temperature value to trigger alert signal 362eb982001SEduardo Valentin * @t_cold: cold temperature value to trigger alert signal 363eb982001SEduardo Valentin * 364eb982001SEduardo Valentin * Checks the requested t_hot and t_cold values and configures the IRQ event 365eb982001SEduardo Valentin * masks accordingly. Call this function only if bandgap features HAS(TALERT). 366eb982001SEduardo Valentin */ 367eb982001SEduardo Valentin static void ti_bandgap_unmask_interrupts(struct ti_bandgap *bgp, int id, 368eb982001SEduardo Valentin u32 t_hot, u32 t_cold) 369eb982001SEduardo Valentin { 370eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 371eb982001SEduardo Valentin u32 temp, reg_val; 372eb982001SEduardo Valentin 373eb982001SEduardo Valentin /* Read the current on die temperature */ 374eb982001SEduardo Valentin temp = ti_bandgap_read_temp(bgp, id); 375eb982001SEduardo Valentin 376eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 377eb982001SEduardo Valentin reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); 378eb982001SEduardo Valentin 379eb982001SEduardo Valentin if (temp < t_hot) 380eb982001SEduardo Valentin reg_val |= tsr->mask_hot_mask; 381eb982001SEduardo Valentin else 382eb982001SEduardo Valentin reg_val &= ~tsr->mask_hot_mask; 383eb982001SEduardo Valentin 384eb982001SEduardo Valentin if (t_cold < temp) 385eb982001SEduardo Valentin reg_val |= tsr->mask_cold_mask; 386eb982001SEduardo Valentin else 387eb982001SEduardo Valentin reg_val &= ~tsr->mask_cold_mask; 388eb982001SEduardo Valentin ti_bandgap_writel(bgp, reg_val, tsr->bgap_mask_ctrl); 389eb982001SEduardo Valentin } 390eb982001SEduardo Valentin 391eb982001SEduardo Valentin /** 392eb982001SEduardo Valentin * ti_bandgap_update_alert_threshold() - sequence to update thresholds 393eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 394eb982001SEduardo Valentin * @id: bandgap sensor id 395eb982001SEduardo Valentin * @val: value (ADC) of a new threshold 396eb982001SEduardo Valentin * @hot: desired threshold to be updated. true if threshold hot, false if 397eb982001SEduardo Valentin * threshold cold 398eb982001SEduardo Valentin * 399eb982001SEduardo Valentin * It will program the required thresholds (hot and cold) for TALERT signal. 400eb982001SEduardo Valentin * This function can be used to update t_hot or t_cold, depending on @hot value. 401eb982001SEduardo Valentin * It checks the resulting t_hot and t_cold values, based on the new passed @val 402eb982001SEduardo Valentin * and configures the thresholds so that t_hot is always greater than t_cold. 403eb982001SEduardo Valentin * Call this function only if bandgap features HAS(TALERT). 404eb982001SEduardo Valentin * 405eb982001SEduardo Valentin * Return: 0 if no error, else corresponding error 406eb982001SEduardo Valentin */ 407eb982001SEduardo Valentin static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id, 408eb982001SEduardo Valentin int val, bool hot) 409eb982001SEduardo Valentin { 410eb982001SEduardo Valentin struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data; 411eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 412eb982001SEduardo Valentin u32 thresh_val, reg_val, t_hot, t_cold; 413eb982001SEduardo Valentin int err = 0; 414eb982001SEduardo Valentin 415eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 416eb982001SEduardo Valentin 417eb982001SEduardo Valentin /* obtain the current value */ 418eb982001SEduardo Valentin thresh_val = ti_bandgap_readl(bgp, tsr->bgap_threshold); 419eb982001SEduardo Valentin t_cold = (thresh_val & tsr->threshold_tcold_mask) >> 420eb982001SEduardo Valentin __ffs(tsr->threshold_tcold_mask); 421eb982001SEduardo Valentin t_hot = (thresh_val & tsr->threshold_thot_mask) >> 422eb982001SEduardo Valentin __ffs(tsr->threshold_thot_mask); 423eb982001SEduardo Valentin if (hot) 424eb982001SEduardo Valentin t_hot = val; 425eb982001SEduardo Valentin else 426eb982001SEduardo Valentin t_cold = val; 427eb982001SEduardo Valentin 428eb982001SEduardo Valentin if (t_cold > t_hot) { 429eb982001SEduardo Valentin if (hot) 430eb982001SEduardo Valentin err = ti_bandgap_add_hyst(bgp, t_hot, 431eb982001SEduardo Valentin -ts_data->hyst_val, 432eb982001SEduardo Valentin &t_cold); 433eb982001SEduardo Valentin else 434eb982001SEduardo Valentin err = ti_bandgap_add_hyst(bgp, t_cold, 435eb982001SEduardo Valentin ts_data->hyst_val, 436eb982001SEduardo Valentin &t_hot); 437eb982001SEduardo Valentin } 438eb982001SEduardo Valentin 439eb982001SEduardo Valentin /* write the new threshold values */ 440eb982001SEduardo Valentin reg_val = thresh_val & 441eb982001SEduardo Valentin ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask); 442eb982001SEduardo Valentin reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) | 443eb982001SEduardo Valentin (t_cold << __ffs(tsr->threshold_tcold_mask)); 444eb982001SEduardo Valentin ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold); 445eb982001SEduardo Valentin 446eb982001SEduardo Valentin if (err) { 447eb982001SEduardo Valentin dev_err(bgp->dev, "failed to reprogram thot threshold\n"); 448eb982001SEduardo Valentin err = -EIO; 449eb982001SEduardo Valentin goto exit; 450eb982001SEduardo Valentin } 451eb982001SEduardo Valentin 452eb982001SEduardo Valentin ti_bandgap_unmask_interrupts(bgp, id, t_hot, t_cold); 453eb982001SEduardo Valentin exit: 454eb982001SEduardo Valentin return err; 455eb982001SEduardo Valentin } 456eb982001SEduardo Valentin 457eb982001SEduardo Valentin /** 458eb982001SEduardo Valentin * ti_bandgap_validate() - helper to check the sanity of a struct ti_bandgap 459eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 460eb982001SEduardo Valentin * @id: bandgap sensor id 461eb982001SEduardo Valentin * 462eb982001SEduardo Valentin * Checks if the bandgap pointer is valid and if the sensor id is also 463eb982001SEduardo Valentin * applicable. 464eb982001SEduardo Valentin * 465eb982001SEduardo Valentin * Return: 0 if no errors, -EINVAL for invalid @bgp pointer or -ERANGE if 466eb982001SEduardo Valentin * @id cannot index @bgp sensors. 467eb982001SEduardo Valentin */ 468eb982001SEduardo Valentin static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id) 469eb982001SEduardo Valentin { 470eb982001SEduardo Valentin int ret = 0; 471eb982001SEduardo Valentin 4720c12b5acSEduardo Valentin if (!bgp || IS_ERR(bgp)) { 473eb982001SEduardo Valentin pr_err("%s: invalid bandgap pointer\n", __func__); 474eb982001SEduardo Valentin ret = -EINVAL; 475eb982001SEduardo Valentin goto exit; 476eb982001SEduardo Valentin } 477eb982001SEduardo Valentin 478eb982001SEduardo Valentin if ((id < 0) || (id >= bgp->conf->sensor_count)) { 479eb982001SEduardo Valentin dev_err(bgp->dev, "%s: sensor id out of range (%d)\n", 480eb982001SEduardo Valentin __func__, id); 481eb982001SEduardo Valentin ret = -ERANGE; 482eb982001SEduardo Valentin } 483eb982001SEduardo Valentin 484eb982001SEduardo Valentin exit: 485eb982001SEduardo Valentin return ret; 486eb982001SEduardo Valentin } 487eb982001SEduardo Valentin 488eb982001SEduardo Valentin /** 489eb982001SEduardo Valentin * _ti_bandgap_write_threshold() - helper to update TALERT t_cold or t_hot 490eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 491eb982001SEduardo Valentin * @id: bandgap sensor id 492eb982001SEduardo Valentin * @val: value (mCelsius) of a new threshold 493eb982001SEduardo Valentin * @hot: desired threshold to be updated. true if threshold hot, false if 494eb982001SEduardo Valentin * threshold cold 495eb982001SEduardo Valentin * 496eb982001SEduardo Valentin * It will update the required thresholds (hot and cold) for TALERT signal. 497eb982001SEduardo Valentin * This function can be used to update t_hot or t_cold, depending on @hot value. 498eb982001SEduardo Valentin * Validates the mCelsius range and update the requested threshold. 499eb982001SEduardo Valentin * Call this function only if bandgap features HAS(TALERT). 500eb982001SEduardo Valentin * 501eb982001SEduardo Valentin * Return: 0 if no error, else corresponding error value. 502eb982001SEduardo Valentin */ 503eb982001SEduardo Valentin static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val, 504eb982001SEduardo Valentin bool hot) 505eb982001SEduardo Valentin { 506eb982001SEduardo Valentin struct temp_sensor_data *ts_data; 507eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 508eb982001SEduardo Valentin u32 adc_val; 509eb982001SEduardo Valentin int ret; 510eb982001SEduardo Valentin 511eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 512eb982001SEduardo Valentin if (ret) 513eb982001SEduardo Valentin goto exit; 514eb982001SEduardo Valentin 515eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, TALERT)) { 516eb982001SEduardo Valentin ret = -ENOTSUPP; 517eb982001SEduardo Valentin goto exit; 518eb982001SEduardo Valentin } 519eb982001SEduardo Valentin 520eb982001SEduardo Valentin ts_data = bgp->conf->sensors[id].ts_data; 521eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 522eb982001SEduardo Valentin if (hot) { 523eb982001SEduardo Valentin if (val < ts_data->min_temp + ts_data->hyst_val) 524eb982001SEduardo Valentin ret = -EINVAL; 525eb982001SEduardo Valentin } else { 526eb982001SEduardo Valentin if (val > ts_data->max_temp + ts_data->hyst_val) 527eb982001SEduardo Valentin ret = -EINVAL; 528eb982001SEduardo Valentin } 529eb982001SEduardo Valentin 530eb982001SEduardo Valentin if (ret) 531eb982001SEduardo Valentin goto exit; 532eb982001SEduardo Valentin 533eb982001SEduardo Valentin ret = ti_bandgap_mcelsius_to_adc(bgp, val, &adc_val); 534eb982001SEduardo Valentin if (ret < 0) 535eb982001SEduardo Valentin goto exit; 536eb982001SEduardo Valentin 537eb982001SEduardo Valentin spin_lock(&bgp->lock); 538eb982001SEduardo Valentin ret = ti_bandgap_update_alert_threshold(bgp, id, adc_val, hot); 539eb982001SEduardo Valentin spin_unlock(&bgp->lock); 540eb982001SEduardo Valentin 541eb982001SEduardo Valentin exit: 542eb982001SEduardo Valentin return ret; 543eb982001SEduardo Valentin } 544eb982001SEduardo Valentin 545eb982001SEduardo Valentin /** 546eb982001SEduardo Valentin * _ti_bandgap_read_threshold() - helper to read TALERT t_cold or t_hot 547eb982001SEduardo Valentin * @bgp: struct ti_bandgap pointer 548eb982001SEduardo Valentin * @id: bandgap sensor id 549eb982001SEduardo Valentin * @val: value (mCelsius) of a threshold 550eb982001SEduardo Valentin * @hot: desired threshold to be read. true if threshold hot, false if 551eb982001SEduardo Valentin * threshold cold 552eb982001SEduardo Valentin * 553eb982001SEduardo Valentin * It will fetch the required thresholds (hot and cold) for TALERT signal. 554eb982001SEduardo Valentin * This function can be used to read t_hot or t_cold, depending on @hot value. 555eb982001SEduardo Valentin * Call this function only if bandgap features HAS(TALERT). 556eb982001SEduardo Valentin * 557eb982001SEduardo Valentin * Return: 0 if no error, -ENOTSUPP if it has no TALERT support, or the 558eb982001SEduardo Valentin * corresponding error value if some operation fails. 559eb982001SEduardo Valentin */ 560eb982001SEduardo Valentin static int _ti_bandgap_read_threshold(struct ti_bandgap *bgp, int id, 561eb982001SEduardo Valentin int *val, bool hot) 562eb982001SEduardo Valentin { 563eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 564eb982001SEduardo Valentin u32 temp, mask; 565eb982001SEduardo Valentin int ret = 0; 566eb982001SEduardo Valentin 567eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 568eb982001SEduardo Valentin if (ret) 569eb982001SEduardo Valentin goto exit; 570eb982001SEduardo Valentin 571eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, TALERT)) { 572eb982001SEduardo Valentin ret = -ENOTSUPP; 573eb982001SEduardo Valentin goto exit; 574eb982001SEduardo Valentin } 575eb982001SEduardo Valentin 576eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 577eb982001SEduardo Valentin if (hot) 578eb982001SEduardo Valentin mask = tsr->threshold_thot_mask; 579eb982001SEduardo Valentin else 580eb982001SEduardo Valentin mask = tsr->threshold_tcold_mask; 581eb982001SEduardo Valentin 582eb982001SEduardo Valentin temp = ti_bandgap_readl(bgp, tsr->bgap_threshold); 583eb982001SEduardo Valentin temp = (temp & mask) >> __ffs(mask); 584eb982001SEduardo Valentin ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp); 585eb982001SEduardo Valentin if (ret) { 586eb982001SEduardo Valentin dev_err(bgp->dev, "failed to read thot\n"); 587eb982001SEduardo Valentin ret = -EIO; 588eb982001SEduardo Valentin goto exit; 589eb982001SEduardo Valentin } 590eb982001SEduardo Valentin 591eb982001SEduardo Valentin *val = temp; 592eb982001SEduardo Valentin 593eb982001SEduardo Valentin exit: 594eb982001SEduardo Valentin return ret; 595eb982001SEduardo Valentin } 596eb982001SEduardo Valentin 597eb982001SEduardo Valentin /*** Exposed APIs ***/ 598eb982001SEduardo Valentin 599eb982001SEduardo Valentin /** 600eb982001SEduardo Valentin * ti_bandgap_read_thot() - reads sensor current thot 601eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 602eb982001SEduardo Valentin * @id: sensor id 603eb982001SEduardo Valentin * @thot: resulting current thot value 604eb982001SEduardo Valentin * 605eb982001SEduardo Valentin * Return: 0 on success or the proper error code 606eb982001SEduardo Valentin */ 607eb982001SEduardo Valentin int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot) 608eb982001SEduardo Valentin { 609eb982001SEduardo Valentin return _ti_bandgap_read_threshold(bgp, id, thot, true); 610eb982001SEduardo Valentin } 611eb982001SEduardo Valentin 612eb982001SEduardo Valentin /** 613eb982001SEduardo Valentin * ti_bandgap_write_thot() - sets sensor current thot 614eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 615eb982001SEduardo Valentin * @id: sensor id 616eb982001SEduardo Valentin * @val: desired thot value 617eb982001SEduardo Valentin * 618eb982001SEduardo Valentin * Return: 0 on success or the proper error code 619eb982001SEduardo Valentin */ 620eb982001SEduardo Valentin int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val) 621eb982001SEduardo Valentin { 622eb982001SEduardo Valentin return _ti_bandgap_write_threshold(bgp, id, val, true); 623eb982001SEduardo Valentin } 624eb982001SEduardo Valentin 625eb982001SEduardo Valentin /** 626eb982001SEduardo Valentin * ti_bandgap_read_tcold() - reads sensor current tcold 627eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 628eb982001SEduardo Valentin * @id: sensor id 629eb982001SEduardo Valentin * @tcold: resulting current tcold value 630eb982001SEduardo Valentin * 631eb982001SEduardo Valentin * Return: 0 on success or the proper error code 632eb982001SEduardo Valentin */ 633eb982001SEduardo Valentin int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold) 634eb982001SEduardo Valentin { 635eb982001SEduardo Valentin return _ti_bandgap_read_threshold(bgp, id, tcold, false); 636eb982001SEduardo Valentin } 637eb982001SEduardo Valentin 638eb982001SEduardo Valentin /** 639eb982001SEduardo Valentin * ti_bandgap_write_tcold() - sets the sensor tcold 640eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 641eb982001SEduardo Valentin * @id: sensor id 642eb982001SEduardo Valentin * @val: desired tcold value 643eb982001SEduardo Valentin * 644eb982001SEduardo Valentin * Return: 0 on success or the proper error code 645eb982001SEduardo Valentin */ 646eb982001SEduardo Valentin int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val) 647eb982001SEduardo Valentin { 648eb982001SEduardo Valentin return _ti_bandgap_write_threshold(bgp, id, val, false); 649eb982001SEduardo Valentin } 650eb982001SEduardo Valentin 651eb982001SEduardo Valentin /** 652eb982001SEduardo Valentin * ti_bandgap_read_counter() - read the sensor counter 653eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 654eb982001SEduardo Valentin * @id: sensor id 655eb982001SEduardo Valentin * @interval: resulting update interval in miliseconds 656eb982001SEduardo Valentin */ 657eb982001SEduardo Valentin static void ti_bandgap_read_counter(struct ti_bandgap *bgp, int id, 658eb982001SEduardo Valentin int *interval) 659eb982001SEduardo Valentin { 660eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 661eb982001SEduardo Valentin int time; 662eb982001SEduardo Valentin 663eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 664eb982001SEduardo Valentin time = ti_bandgap_readl(bgp, tsr->bgap_counter); 665eb982001SEduardo Valentin time = (time & tsr->counter_mask) >> 666eb982001SEduardo Valentin __ffs(tsr->counter_mask); 667eb982001SEduardo Valentin time = time * 1000 / bgp->clk_rate; 668eb982001SEduardo Valentin *interval = time; 669eb982001SEduardo Valentin } 670eb982001SEduardo Valentin 671eb982001SEduardo Valentin /** 672eb982001SEduardo Valentin * ti_bandgap_read_counter_delay() - read the sensor counter delay 673eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 674eb982001SEduardo Valentin * @id: sensor id 675eb982001SEduardo Valentin * @interval: resulting update interval in miliseconds 676eb982001SEduardo Valentin */ 677eb982001SEduardo Valentin static void ti_bandgap_read_counter_delay(struct ti_bandgap *bgp, int id, 678eb982001SEduardo Valentin int *interval) 679eb982001SEduardo Valentin { 680eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 681eb982001SEduardo Valentin int reg_val; 682eb982001SEduardo Valentin 683eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 684eb982001SEduardo Valentin 685eb982001SEduardo Valentin reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl); 686eb982001SEduardo Valentin reg_val = (reg_val & tsr->mask_counter_delay_mask) >> 687eb982001SEduardo Valentin __ffs(tsr->mask_counter_delay_mask); 688eb982001SEduardo Valentin switch (reg_val) { 689eb982001SEduardo Valentin case 0: 690eb982001SEduardo Valentin *interval = 0; 691eb982001SEduardo Valentin break; 692eb982001SEduardo Valentin case 1: 693eb982001SEduardo Valentin *interval = 1; 694eb982001SEduardo Valentin break; 695eb982001SEduardo Valentin case 2: 696eb982001SEduardo Valentin *interval = 10; 697eb982001SEduardo Valentin break; 698eb982001SEduardo Valentin case 3: 699eb982001SEduardo Valentin *interval = 100; 700eb982001SEduardo Valentin break; 701eb982001SEduardo Valentin case 4: 702eb982001SEduardo Valentin *interval = 250; 703eb982001SEduardo Valentin break; 704eb982001SEduardo Valentin case 5: 705eb982001SEduardo Valentin *interval = 500; 706eb982001SEduardo Valentin break; 707eb982001SEduardo Valentin default: 708eb982001SEduardo Valentin dev_warn(bgp->dev, "Wrong counter delay value read from register %X", 709eb982001SEduardo Valentin reg_val); 710eb982001SEduardo Valentin } 711eb982001SEduardo Valentin } 712eb982001SEduardo Valentin 713eb982001SEduardo Valentin /** 714eb982001SEduardo Valentin * ti_bandgap_read_update_interval() - read the sensor update interval 715eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 716eb982001SEduardo Valentin * @id: sensor id 717eb982001SEduardo Valentin * @interval: resulting update interval in miliseconds 718eb982001SEduardo Valentin * 719eb982001SEduardo Valentin * Return: 0 on success or the proper error code 720eb982001SEduardo Valentin */ 721eb982001SEduardo Valentin int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id, 722eb982001SEduardo Valentin int *interval) 723eb982001SEduardo Valentin { 724eb982001SEduardo Valentin int ret = 0; 725eb982001SEduardo Valentin 726eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 727eb982001SEduardo Valentin if (ret) 728eb982001SEduardo Valentin goto exit; 729eb982001SEduardo Valentin 730eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, COUNTER) && 731eb982001SEduardo Valentin !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) { 732eb982001SEduardo Valentin ret = -ENOTSUPP; 733eb982001SEduardo Valentin goto exit; 734eb982001SEduardo Valentin } 735eb982001SEduardo Valentin 736eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) { 737eb982001SEduardo Valentin ti_bandgap_read_counter(bgp, id, interval); 738eb982001SEduardo Valentin goto exit; 739eb982001SEduardo Valentin } 740eb982001SEduardo Valentin 741eb982001SEduardo Valentin ti_bandgap_read_counter_delay(bgp, id, interval); 742eb982001SEduardo Valentin exit: 743eb982001SEduardo Valentin return ret; 744eb982001SEduardo Valentin } 745eb982001SEduardo Valentin 746eb982001SEduardo Valentin /** 747eb982001SEduardo Valentin * ti_bandgap_write_counter_delay() - set the counter_delay 748eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 749eb982001SEduardo Valentin * @id: sensor id 750eb982001SEduardo Valentin * @interval: desired update interval in miliseconds 751eb982001SEduardo Valentin * 752eb982001SEduardo Valentin * Return: 0 on success or the proper error code 753eb982001SEduardo Valentin */ 754eb982001SEduardo Valentin static int ti_bandgap_write_counter_delay(struct ti_bandgap *bgp, int id, 755eb982001SEduardo Valentin u32 interval) 756eb982001SEduardo Valentin { 757eb982001SEduardo Valentin int rval; 758eb982001SEduardo Valentin 759eb982001SEduardo Valentin switch (interval) { 760eb982001SEduardo Valentin case 0: /* Immediate conversion */ 761eb982001SEduardo Valentin rval = 0x0; 762eb982001SEduardo Valentin break; 763eb982001SEduardo Valentin case 1: /* Conversion after ever 1ms */ 764eb982001SEduardo Valentin rval = 0x1; 765eb982001SEduardo Valentin break; 766eb982001SEduardo Valentin case 10: /* Conversion after ever 10ms */ 767eb982001SEduardo Valentin rval = 0x2; 768eb982001SEduardo Valentin break; 769eb982001SEduardo Valentin case 100: /* Conversion after ever 100ms */ 770eb982001SEduardo Valentin rval = 0x3; 771eb982001SEduardo Valentin break; 772eb982001SEduardo Valentin case 250: /* Conversion after ever 250ms */ 773eb982001SEduardo Valentin rval = 0x4; 774eb982001SEduardo Valentin break; 775eb982001SEduardo Valentin case 500: /* Conversion after ever 500ms */ 776eb982001SEduardo Valentin rval = 0x5; 777eb982001SEduardo Valentin break; 778eb982001SEduardo Valentin default: 779eb982001SEduardo Valentin dev_warn(bgp->dev, "Delay %d ms is not supported\n", interval); 780eb982001SEduardo Valentin return -EINVAL; 781eb982001SEduardo Valentin } 782eb982001SEduardo Valentin 783eb982001SEduardo Valentin spin_lock(&bgp->lock); 784eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_counter_delay_mask, rval); 785eb982001SEduardo Valentin spin_unlock(&bgp->lock); 786eb982001SEduardo Valentin 787eb982001SEduardo Valentin return 0; 788eb982001SEduardo Valentin } 789eb982001SEduardo Valentin 790eb982001SEduardo Valentin /** 791eb982001SEduardo Valentin * ti_bandgap_write_counter() - set the bandgap sensor counter 792eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 793eb982001SEduardo Valentin * @id: sensor id 794eb982001SEduardo Valentin * @interval: desired update interval in miliseconds 795eb982001SEduardo Valentin */ 796eb982001SEduardo Valentin static void ti_bandgap_write_counter(struct ti_bandgap *bgp, int id, 797eb982001SEduardo Valentin u32 interval) 798eb982001SEduardo Valentin { 799eb982001SEduardo Valentin interval = interval * bgp->clk_rate / 1000; 800eb982001SEduardo Valentin spin_lock(&bgp->lock); 801eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_counter, counter_mask, interval); 802eb982001SEduardo Valentin spin_unlock(&bgp->lock); 803eb982001SEduardo Valentin } 804eb982001SEduardo Valentin 805eb982001SEduardo Valentin /** 806eb982001SEduardo Valentin * ti_bandgap_write_update_interval() - set the update interval 807eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 808eb982001SEduardo Valentin * @id: sensor id 809eb982001SEduardo Valentin * @interval: desired update interval in miliseconds 810eb982001SEduardo Valentin * 811eb982001SEduardo Valentin * Return: 0 on success or the proper error code 812eb982001SEduardo Valentin */ 813eb982001SEduardo Valentin int ti_bandgap_write_update_interval(struct ti_bandgap *bgp, 814eb982001SEduardo Valentin int id, u32 interval) 815eb982001SEduardo Valentin { 816eb982001SEduardo Valentin int ret = ti_bandgap_validate(bgp, id); 817eb982001SEduardo Valentin if (ret) 818eb982001SEduardo Valentin goto exit; 819eb982001SEduardo Valentin 820eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, COUNTER) && 821eb982001SEduardo Valentin !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) { 822eb982001SEduardo Valentin ret = -ENOTSUPP; 823eb982001SEduardo Valentin goto exit; 824eb982001SEduardo Valentin } 825eb982001SEduardo Valentin 826eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, COUNTER)) { 827eb982001SEduardo Valentin ti_bandgap_write_counter(bgp, id, interval); 828eb982001SEduardo Valentin goto exit; 829eb982001SEduardo Valentin } 830eb982001SEduardo Valentin 831eb982001SEduardo Valentin ret = ti_bandgap_write_counter_delay(bgp, id, interval); 832eb982001SEduardo Valentin exit: 833eb982001SEduardo Valentin return ret; 834eb982001SEduardo Valentin } 835eb982001SEduardo Valentin 836eb982001SEduardo Valentin /** 837eb982001SEduardo Valentin * ti_bandgap_read_temperature() - report current temperature 838eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 839eb982001SEduardo Valentin * @id: sensor id 840eb982001SEduardo Valentin * @temperature: resulting temperature 841eb982001SEduardo Valentin * 842eb982001SEduardo Valentin * Return: 0 on success or the proper error code 843eb982001SEduardo Valentin */ 844eb982001SEduardo Valentin int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id, 845eb982001SEduardo Valentin int *temperature) 846eb982001SEduardo Valentin { 847eb982001SEduardo Valentin u32 temp; 848eb982001SEduardo Valentin int ret; 849eb982001SEduardo Valentin 850eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 851eb982001SEduardo Valentin if (ret) 852eb982001SEduardo Valentin return ret; 853eb982001SEduardo Valentin 854eb982001SEduardo Valentin spin_lock(&bgp->lock); 855eb982001SEduardo Valentin temp = ti_bandgap_read_temp(bgp, id); 856eb982001SEduardo Valentin spin_unlock(&bgp->lock); 857eb982001SEduardo Valentin 858eb982001SEduardo Valentin ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp); 859eb982001SEduardo Valentin if (ret) 860eb982001SEduardo Valentin return -EIO; 861eb982001SEduardo Valentin 862eb982001SEduardo Valentin *temperature = temp; 863eb982001SEduardo Valentin 864eb982001SEduardo Valentin return 0; 865eb982001SEduardo Valentin } 866eb982001SEduardo Valentin 867eb982001SEduardo Valentin /** 868eb982001SEduardo Valentin * ti_bandgap_set_sensor_data() - helper function to store thermal 869eb982001SEduardo Valentin * framework related data. 870eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 871eb982001SEduardo Valentin * @id: sensor id 872eb982001SEduardo Valentin * @data: thermal framework related data to be stored 873eb982001SEduardo Valentin * 874eb982001SEduardo Valentin * Return: 0 on success or the proper error code 875eb982001SEduardo Valentin */ 876eb982001SEduardo Valentin int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data) 877eb982001SEduardo Valentin { 878eb982001SEduardo Valentin int ret = ti_bandgap_validate(bgp, id); 879eb982001SEduardo Valentin if (ret) 880eb982001SEduardo Valentin return ret; 881eb982001SEduardo Valentin 882eb982001SEduardo Valentin bgp->regval[id].data = data; 883eb982001SEduardo Valentin 884eb982001SEduardo Valentin return 0; 885eb982001SEduardo Valentin } 886eb982001SEduardo Valentin 887eb982001SEduardo Valentin /** 888eb982001SEduardo Valentin * ti_bandgap_get_sensor_data() - helper function to get thermal 889eb982001SEduardo Valentin * framework related data. 890eb982001SEduardo Valentin * @bgp: pointer to bandgap instance 891eb982001SEduardo Valentin * @id: sensor id 892eb982001SEduardo Valentin * 893eb982001SEduardo Valentin * Return: data stored by set function with sensor id on success or NULL 894eb982001SEduardo Valentin */ 895eb982001SEduardo Valentin void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id) 896eb982001SEduardo Valentin { 897eb982001SEduardo Valentin int ret = ti_bandgap_validate(bgp, id); 898eb982001SEduardo Valentin if (ret) 899eb982001SEduardo Valentin return ERR_PTR(ret); 900eb982001SEduardo Valentin 901eb982001SEduardo Valentin return bgp->regval[id].data; 902eb982001SEduardo Valentin } 903eb982001SEduardo Valentin 904eb982001SEduardo Valentin /*** Helper functions used during device initialization ***/ 905eb982001SEduardo Valentin 906eb982001SEduardo Valentin /** 907eb982001SEduardo Valentin * ti_bandgap_force_single_read() - executes 1 single ADC conversion 908eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 909eb982001SEduardo Valentin * @id: sensor id which it is desired to read 1 temperature 910eb982001SEduardo Valentin * 911eb982001SEduardo Valentin * Used to initialize the conversion state machine and set it to a valid 912eb982001SEduardo Valentin * state. Called during device initialization and context restore events. 913eb982001SEduardo Valentin * 914eb982001SEduardo Valentin * Return: 0 915eb982001SEduardo Valentin */ 916eb982001SEduardo Valentin static int 917eb982001SEduardo Valentin ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id) 918eb982001SEduardo Valentin { 919eb982001SEduardo Valentin u32 temp = 0, counter = 1000; 920eb982001SEduardo Valentin 921eb982001SEduardo Valentin /* Select single conversion mode */ 922eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, MODE_CONFIG)) 923eb982001SEduardo Valentin RMW_BITS(bgp, id, bgap_mode_ctrl, mode_ctrl_mask, 0); 924eb982001SEduardo Valentin 925eb982001SEduardo Valentin /* Start of Conversion = 1 */ 926eb982001SEduardo Valentin RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 1); 927eb982001SEduardo Valentin /* Wait until DTEMP is updated */ 928eb982001SEduardo Valentin temp = ti_bandgap_read_temp(bgp, id); 929eb982001SEduardo Valentin 930eb982001SEduardo Valentin while ((temp == 0) && --counter) 931eb982001SEduardo Valentin temp = ti_bandgap_read_temp(bgp, id); 932eb982001SEduardo Valentin /* REVISIT: Check correct condition for end of conversion */ 933eb982001SEduardo Valentin 934eb982001SEduardo Valentin /* Start of Conversion = 0 */ 935eb982001SEduardo Valentin RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 0); 936eb982001SEduardo Valentin 937eb982001SEduardo Valentin return 0; 938eb982001SEduardo Valentin } 939eb982001SEduardo Valentin 940eb982001SEduardo Valentin /** 941eb982001SEduardo Valentin * ti_bandgap_set_continous_mode() - One time enabling of continuous mode 942eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 943eb982001SEduardo Valentin * 944eb982001SEduardo Valentin * Call this function only if HAS(MODE_CONFIG) is set. As this driver may 945eb982001SEduardo Valentin * be used for junction temperature monitoring, it is desirable that the 946eb982001SEduardo Valentin * sensors are operational all the time, so that alerts are generated 947eb982001SEduardo Valentin * properly. 948eb982001SEduardo Valentin * 949eb982001SEduardo Valentin * Return: 0 950eb982001SEduardo Valentin */ 951eb982001SEduardo Valentin static int ti_bandgap_set_continuous_mode(struct ti_bandgap *bgp) 952eb982001SEduardo Valentin { 953eb982001SEduardo Valentin int i; 954eb982001SEduardo Valentin 955eb982001SEduardo Valentin for (i = 0; i < bgp->conf->sensor_count; i++) { 956eb982001SEduardo Valentin /* Perform a single read just before enabling continuous */ 957eb982001SEduardo Valentin ti_bandgap_force_single_read(bgp, i); 958eb982001SEduardo Valentin RMW_BITS(bgp, i, bgap_mode_ctrl, mode_ctrl_mask, 1); 959eb982001SEduardo Valentin } 960eb982001SEduardo Valentin 961eb982001SEduardo Valentin return 0; 962eb982001SEduardo Valentin } 963eb982001SEduardo Valentin 964eb982001SEduardo Valentin /** 965eb982001SEduardo Valentin * ti_bandgap_get_trend() - To fetch the temperature trend of a sensor 966eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 967eb982001SEduardo Valentin * @id: id of the individual sensor 968eb982001SEduardo Valentin * @trend: Pointer to trend. 969eb982001SEduardo Valentin * 970eb982001SEduardo Valentin * This function needs to be called to fetch the temperature trend of a 971eb982001SEduardo Valentin * Particular sensor. The function computes the difference in temperature 972eb982001SEduardo Valentin * w.r.t time. For the bandgaps with built in history buffer the temperatures 973eb982001SEduardo Valentin * are read from the buffer and for those without the Buffer -ENOTSUPP is 974eb982001SEduardo Valentin * returned. 975eb982001SEduardo Valentin * 976eb982001SEduardo Valentin * Return: 0 if no error, else return corresponding error. If no 977eb982001SEduardo Valentin * error then the trend value is passed on to trend parameter 978eb982001SEduardo Valentin */ 979eb982001SEduardo Valentin int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend) 980eb982001SEduardo Valentin { 981eb982001SEduardo Valentin struct temp_sensor_registers *tsr; 982eb982001SEduardo Valentin u32 temp1, temp2, reg1, reg2; 983eb982001SEduardo Valentin int t1, t2, interval, ret = 0; 984eb982001SEduardo Valentin 985eb982001SEduardo Valentin ret = ti_bandgap_validate(bgp, id); 986eb982001SEduardo Valentin if (ret) 987eb982001SEduardo Valentin goto exit; 988eb982001SEduardo Valentin 989eb982001SEduardo Valentin if (!TI_BANDGAP_HAS(bgp, HISTORY_BUFFER) || 990eb982001SEduardo Valentin !TI_BANDGAP_HAS(bgp, FREEZE_BIT)) { 991eb982001SEduardo Valentin ret = -ENOTSUPP; 992eb982001SEduardo Valentin goto exit; 993eb982001SEduardo Valentin } 994eb982001SEduardo Valentin 995ba0049eaSEduardo Valentin spin_lock(&bgp->lock); 996ba0049eaSEduardo Valentin 997eb982001SEduardo Valentin tsr = bgp->conf->sensors[id].registers; 998eb982001SEduardo Valentin 999eb982001SEduardo Valentin /* Freeze and read the last 2 valid readings */ 1000ba0049eaSEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1); 1001eb982001SEduardo Valentin reg1 = tsr->ctrl_dtemp_1; 1002eb982001SEduardo Valentin reg2 = tsr->ctrl_dtemp_2; 1003eb982001SEduardo Valentin 1004eb982001SEduardo Valentin /* read temperature from history buffer */ 1005eb982001SEduardo Valentin temp1 = ti_bandgap_readl(bgp, reg1); 1006eb982001SEduardo Valentin temp1 &= tsr->bgap_dtemp_mask; 1007eb982001SEduardo Valentin 1008eb982001SEduardo Valentin temp2 = ti_bandgap_readl(bgp, reg2); 1009eb982001SEduardo Valentin temp2 &= tsr->bgap_dtemp_mask; 1010eb982001SEduardo Valentin 1011eb982001SEduardo Valentin /* Convert from adc values to mCelsius temperature */ 1012eb982001SEduardo Valentin ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1); 1013eb982001SEduardo Valentin if (ret) 1014ba0049eaSEduardo Valentin goto unfreeze; 1015eb982001SEduardo Valentin 1016eb982001SEduardo Valentin ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2); 1017eb982001SEduardo Valentin if (ret) 1018ba0049eaSEduardo Valentin goto unfreeze; 1019eb982001SEduardo Valentin 1020eb982001SEduardo Valentin /* Fetch the update interval */ 1021eb982001SEduardo Valentin ret = ti_bandgap_read_update_interval(bgp, id, &interval); 1022eb982001SEduardo Valentin if (ret || !interval) 1023ba0049eaSEduardo Valentin goto unfreeze; 1024eb982001SEduardo Valentin 1025eb982001SEduardo Valentin *trend = (t1 - t2) / interval; 1026eb982001SEduardo Valentin 1027eb982001SEduardo Valentin dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n", 1028eb982001SEduardo Valentin t1, t2, *trend); 1029eb982001SEduardo Valentin 1030ba0049eaSEduardo Valentin unfreeze: 1031ba0049eaSEduardo Valentin RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0); 1032ba0049eaSEduardo Valentin spin_unlock(&bgp->lock); 1033eb982001SEduardo Valentin exit: 1034eb982001SEduardo Valentin return ret; 1035eb982001SEduardo Valentin } 1036eb982001SEduardo Valentin 1037eb982001SEduardo Valentin /** 1038eb982001SEduardo Valentin * ti_bandgap_tshut_init() - setup and initialize tshut handling 1039eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 1040eb982001SEduardo Valentin * @pdev: pointer to device struct platform_device 1041eb982001SEduardo Valentin * 1042eb982001SEduardo Valentin * Call this function only in case the bandgap features HAS(TSHUT). 1043eb982001SEduardo Valentin * In this case, the driver needs to handle the TSHUT signal as an IRQ. 1044eb982001SEduardo Valentin * The IRQ is wired as a GPIO, and for this purpose, it is required 1045eb982001SEduardo Valentin * to specify which GPIO line is used. TSHUT IRQ is fired anytime 1046eb982001SEduardo Valentin * one of the bandgap sensors violates the TSHUT high/hot threshold. 1047eb982001SEduardo Valentin * And in that case, the system must go off. 1048eb982001SEduardo Valentin * 1049eb982001SEduardo Valentin * Return: 0 if no error, else error status 1050eb982001SEduardo Valentin */ 1051eb982001SEduardo Valentin static int ti_bandgap_tshut_init(struct ti_bandgap *bgp, 1052eb982001SEduardo Valentin struct platform_device *pdev) 1053eb982001SEduardo Valentin { 1054eb982001SEduardo Valentin int gpio_nr = bgp->tshut_gpio; 1055eb982001SEduardo Valentin int status; 1056eb982001SEduardo Valentin 1057eb982001SEduardo Valentin /* Request for gpio_86 line */ 1058eb982001SEduardo Valentin status = gpio_request(gpio_nr, "tshut"); 1059eb982001SEduardo Valentin if (status < 0) { 1060eb982001SEduardo Valentin dev_err(bgp->dev, "Could not request for TSHUT GPIO:%i\n", 86); 1061eb982001SEduardo Valentin return status; 1062eb982001SEduardo Valentin } 1063eb982001SEduardo Valentin status = gpio_direction_input(gpio_nr); 1064eb982001SEduardo Valentin if (status) { 1065eb982001SEduardo Valentin dev_err(bgp->dev, "Cannot set input TSHUT GPIO %d\n", gpio_nr); 1066eb982001SEduardo Valentin return status; 1067eb982001SEduardo Valentin } 1068eb982001SEduardo Valentin 1069eb982001SEduardo Valentin status = request_irq(gpio_to_irq(gpio_nr), ti_bandgap_tshut_irq_handler, 1070eb982001SEduardo Valentin IRQF_TRIGGER_RISING, "tshut", NULL); 1071eb982001SEduardo Valentin if (status) { 1072eb982001SEduardo Valentin gpio_free(gpio_nr); 1073eb982001SEduardo Valentin dev_err(bgp->dev, "request irq failed for TSHUT"); 1074eb982001SEduardo Valentin } 1075eb982001SEduardo Valentin 1076eb982001SEduardo Valentin return 0; 1077eb982001SEduardo Valentin } 1078eb982001SEduardo Valentin 1079eb982001SEduardo Valentin /** 1080eb982001SEduardo Valentin * ti_bandgap_alert_init() - setup and initialize talert handling 1081eb982001SEduardo Valentin * @bgp: pointer to struct ti_bandgap 1082eb982001SEduardo Valentin * @pdev: pointer to device struct platform_device 1083eb982001SEduardo Valentin * 1084eb982001SEduardo Valentin * Call this function only in case the bandgap features HAS(TALERT). 1085eb982001SEduardo Valentin * In this case, the driver needs to handle the TALERT signals as an IRQs. 1086eb982001SEduardo Valentin * TALERT is a normal IRQ and it is fired any time thresholds (hot or cold) 1087eb982001SEduardo Valentin * are violated. In these situation, the driver must reprogram the thresholds, 1088eb982001SEduardo Valentin * accordingly to specified policy. 1089eb982001SEduardo Valentin * 1090eb982001SEduardo Valentin * Return: 0 if no error, else return corresponding error. 1091eb982001SEduardo Valentin */ 1092eb982001SEduardo Valentin static int ti_bandgap_talert_init(struct ti_bandgap *bgp, 1093eb982001SEduardo Valentin struct platform_device *pdev) 1094eb982001SEduardo Valentin { 1095eb982001SEduardo Valentin int ret; 1096eb982001SEduardo Valentin 1097eb982001SEduardo Valentin bgp->irq = platform_get_irq(pdev, 0); 1098eb982001SEduardo Valentin if (bgp->irq < 0) { 1099eb982001SEduardo Valentin dev_err(&pdev->dev, "get_irq failed\n"); 1100eb982001SEduardo Valentin return bgp->irq; 1101eb982001SEduardo Valentin } 1102eb982001SEduardo Valentin ret = request_threaded_irq(bgp->irq, NULL, 1103eb982001SEduardo Valentin ti_bandgap_talert_irq_handler, 1104eb982001SEduardo Valentin IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 1105eb982001SEduardo Valentin "talert", bgp); 1106eb982001SEduardo Valentin if (ret) { 1107eb982001SEduardo Valentin dev_err(&pdev->dev, "Request threaded irq failed.\n"); 1108eb982001SEduardo Valentin return ret; 1109eb982001SEduardo Valentin } 1110eb982001SEduardo Valentin 1111eb982001SEduardo Valentin return 0; 1112eb982001SEduardo Valentin } 1113eb982001SEduardo Valentin 1114eb982001SEduardo Valentin static const struct of_device_id of_ti_bandgap_match[]; 1115eb982001SEduardo Valentin /** 1116eb982001SEduardo Valentin * ti_bandgap_build() - parse DT and setup a struct ti_bandgap 1117eb982001SEduardo Valentin * @pdev: pointer to device struct platform_device 1118eb982001SEduardo Valentin * 1119eb982001SEduardo Valentin * Used to read the device tree properties accordingly to the bandgap 1120eb982001SEduardo Valentin * matching version. Based on bandgap version and its capabilities it 1121eb982001SEduardo Valentin * will build a struct ti_bandgap out of the required DT entries. 1122eb982001SEduardo Valentin * 1123eb982001SEduardo Valentin * Return: valid bandgap structure if successful, else returns ERR_PTR 1124eb982001SEduardo Valentin * return value must be verified with IS_ERR. 1125eb982001SEduardo Valentin */ 1126eb982001SEduardo Valentin static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) 1127eb982001SEduardo Valentin { 1128eb982001SEduardo Valentin struct device_node *node = pdev->dev.of_node; 1129eb982001SEduardo Valentin const struct of_device_id *of_id; 1130eb982001SEduardo Valentin struct ti_bandgap *bgp; 1131eb982001SEduardo Valentin struct resource *res; 1132eb982001SEduardo Valentin u32 prop; 1133eb982001SEduardo Valentin int i; 1134eb982001SEduardo Valentin 1135eb982001SEduardo Valentin /* just for the sake */ 1136eb982001SEduardo Valentin if (!node) { 1137eb982001SEduardo Valentin dev_err(&pdev->dev, "no platform information available\n"); 1138eb982001SEduardo Valentin return ERR_PTR(-EINVAL); 1139eb982001SEduardo Valentin } 1140eb982001SEduardo Valentin 1141eb982001SEduardo Valentin bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL); 1142eb982001SEduardo Valentin if (!bgp) { 1143eb982001SEduardo Valentin dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n"); 1144eb982001SEduardo Valentin return ERR_PTR(-ENOMEM); 1145eb982001SEduardo Valentin } 1146eb982001SEduardo Valentin 1147eb982001SEduardo Valentin of_id = of_match_device(of_ti_bandgap_match, &pdev->dev); 1148eb982001SEduardo Valentin if (of_id) 1149eb982001SEduardo Valentin bgp->conf = of_id->data; 1150eb982001SEduardo Valentin 1151eb982001SEduardo Valentin /* register shadow for context save and restore */ 1152eb982001SEduardo Valentin bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) * 1153eb982001SEduardo Valentin bgp->conf->sensor_count, GFP_KERNEL); 1154eb982001SEduardo Valentin if (!bgp) { 1155eb982001SEduardo Valentin dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n"); 1156eb982001SEduardo Valentin return ERR_PTR(-ENOMEM); 1157eb982001SEduardo Valentin } 1158eb982001SEduardo Valentin 1159eb982001SEduardo Valentin i = 0; 1160eb982001SEduardo Valentin do { 1161eb982001SEduardo Valentin void __iomem *chunk; 1162eb982001SEduardo Valentin 1163eb982001SEduardo Valentin res = platform_get_resource(pdev, IORESOURCE_MEM, i); 1164eb982001SEduardo Valentin if (!res) 1165eb982001SEduardo Valentin break; 1166eb982001SEduardo Valentin chunk = devm_ioremap_resource(&pdev->dev, res); 1167eb982001SEduardo Valentin if (i == 0) 1168eb982001SEduardo Valentin bgp->base = chunk; 1169eb982001SEduardo Valentin if (IS_ERR(chunk)) 1170eb982001SEduardo Valentin return ERR_CAST(chunk); 1171eb982001SEduardo Valentin 1172eb982001SEduardo Valentin i++; 1173eb982001SEduardo Valentin } while (res); 1174eb982001SEduardo Valentin 1175eb982001SEduardo Valentin if (TI_BANDGAP_HAS(bgp, TSHUT)) { 1176eb982001SEduardo Valentin if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) { 1177eb982001SEduardo Valentin dev_err(&pdev->dev, "missing tshut gpio in device tree\n"); 1178eb982001SEduardo Valentin return ERR_PTR(-EINVAL); 1179eb982001SEduardo Valentin } 1180eb982001SEduardo Valentin bgp->tshut_gpio = prop; 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 1534eb982001SEduardo Valentin /* Sentinel */ 1535eb982001SEduardo Valentin { }, 1536eb982001SEduardo Valentin }; 1537eb982001SEduardo Valentin MODULE_DEVICE_TABLE(of, of_ti_bandgap_match); 1538eb982001SEduardo Valentin 1539eb982001SEduardo Valentin static struct platform_driver ti_bandgap_sensor_driver = { 1540eb982001SEduardo Valentin .probe = ti_bandgap_probe, 1541eb982001SEduardo Valentin .remove = ti_bandgap_remove, 1542eb982001SEduardo Valentin .driver = { 1543eb982001SEduardo Valentin .name = "ti-soc-thermal", 1544eb982001SEduardo Valentin .pm = DEV_PM_OPS, 1545eb982001SEduardo Valentin .of_match_table = of_ti_bandgap_match, 1546eb982001SEduardo Valentin }, 1547eb982001SEduardo Valentin }; 1548eb982001SEduardo Valentin 1549eb982001SEduardo Valentin module_platform_driver(ti_bandgap_sensor_driver); 1550eb982001SEduardo Valentin 1551eb982001SEduardo Valentin MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver"); 1552eb982001SEduardo Valentin MODULE_LICENSE("GPL v2"); 1553eb982001SEduardo Valentin MODULE_ALIAS("platform:ti-soc-thermal"); 1554eb982001SEduardo Valentin MODULE_AUTHOR("Texas Instrument Inc."); 1555