Exemplo n.º 1
0
static int
omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
{
	struct temp_sensor_registers *tsr;
	u32 temp = 0, counter = 1000;

	tsr = bg_ptr->conf->sensors[id].registers;
	/* Select single conversion mode */
	if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG)) {
		temp = omap_bandgap_readl(bg_ptr, tsr->bgap_mode_ctrl);
		temp &= ~(1 << __ffs(tsr->mode_ctrl_mask));
		omap_bandgap_writel(bg_ptr, temp, tsr->bgap_mode_ctrl);
	}

	/* Start of Conversion = 1 */
	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
	temp |= 1 << __ffs(tsr->bgap_soc_mask);
	omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl);
	/* Wait until DTEMP is updated */
	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
	temp &= (tsr->bgap_dtemp_mask);
	while ((temp == 0) && --counter) {
		temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
		temp &= (tsr->bgap_dtemp_mask);
	}
	/* Start of Conversion = 0 */
	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
	temp &= ~(1 << __ffs(tsr->bgap_soc_mask));
	omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl);

	return 0;
}
Exemplo n.º 2
0
/* Talert masks. Call it only if HAS(TALERT) is set */
static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
					 u32 t_hot, u32 t_cold)
{
	struct temp_sensor_registers *tsr;
	u32 temp, reg_val;

	/* Read the current on die temperature */
	tsr = bg_ptr->conf->sensors[id].registers;
	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
	temp &= tsr->bgap_dtemp_mask;

	reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
	if (temp < t_hot)
		reg_val |= tsr->mask_hot_mask;
	else
		reg_val &= ~tsr->mask_hot_mask;

	if (t_cold < temp)
		reg_val |= tsr->mask_cold_mask;
	else
		reg_val &= ~tsr->mask_cold_mask;
	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl);

	return 0;
}
Exemplo n.º 3
0
/* Talert Thot and Tcold thresholds. Call it only if HAS(TALERT) is set */
static
int temp_sensor_init_talert_thresholds(struct omap_bandgap *bg_ptr, int id,
				       int t_hot, int t_cold)
{
	struct temp_sensor_registers *tsr;
	u32 reg_val, thresh_val;

	tsr = bg_ptr->conf->sensors[id].registers;
	thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);

	/* write the new t_cold value */
	reg_val = thresh_val & ~tsr->threshold_tcold_mask;
	reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);

	thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);

	/* write the new t_hot value */
	reg_val = thresh_val & ~tsr->threshold_thot_mask;
	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);

	reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
	reg_val |= tsr->mask_hot_mask;
	reg_val |= tsr->mask_cold_mask;
	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl);

	return 0;
}
Exemplo n.º 4
0
static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
{
	int i;

	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		struct temp_sensor_registers *tsr;
		struct temp_sensor_regval *rval;

		rval = &bg_ptr->conf->sensors[i].regval;
		tsr = bg_ptr->conf->sensors[i].registers;

		if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
			rval->bg_mode_ctrl = omap_bandgap_readl(bg_ptr,
							tsr->bgap_mode_ctrl);
		if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
			rval->bg_counter = omap_bandgap_readl(bg_ptr,
							tsr->bgap_counter);
		if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
			rval->bg_threshold = omap_bandgap_readl(bg_ptr,
							tsr->bgap_threshold);
			rval->bg_ctrl = omap_bandgap_readl(bg_ptr,
						   tsr->bgap_mask_ctrl);
		}

		if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
			rval->tshut_threshold = omap_bandgap_readl(bg_ptr,
						   tsr->tshut_threshold);
	}

	return 0;
}
Exemplo n.º 5
0
static u32 omap_bandgap_read_temp(struct omap_bandgap *bg_ptr, int id)
{
	struct temp_sensor_registers *tsr;
	u32 temp, ctrl, reg;

	tsr = bg_ptr->conf->sensors[id].registers;
	reg = tsr->temp_sensor_ctrl;

	if (OMAP_BANDGAP_HAS(bg_ptr, FREEZE_BIT)) {
		ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
		ctrl |= tsr->mask_freeze_mask;
		omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
		/*
		 * In case we cannot read from cur_dtemp / dtemp_0,
		 * then we read from the last valid temp read
		 */
		reg = tsr->ctrl_dtemp_1;
	}

	/* read temperature */
	temp = omap_bandgap_readl(bg_ptr, reg);
	temp &= tsr->bgap_dtemp_mask;

	if (OMAP_BANDGAP_HAS(bg_ptr, FREEZE_BIT)) {
		ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
		ctrl &= ~tsr->mask_freeze_mask;
		omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
	}

	return temp;
}
Exemplo n.º 6
0
static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
{
	int i;
	u32 temp = 0;

	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		struct temp_sensor_registers *tsr;
		struct temp_sensor_regval *rval;
		u32 val = 0;

		rval = &bg_ptr->conf->sensors[i].regval;
		tsr = bg_ptr->conf->sensors[i].registers;

		if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
			val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);

		if (val == 0) {
			if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
				omap_bandgap_writel(bg_ptr,
					rval->tshut_threshold,
						   tsr->tshut_threshold);
			/* Force immediate temperature measurement and update
			 * of the DTEMP field
			 */
			omap_bandgap_force_single_read(bg_ptr, i);

			if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
				omap_bandgap_writel(bg_ptr, rval->bg_counter,
							   tsr->bgap_counter);
			if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
				omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl,
							   tsr->bgap_mode_ctrl);
			if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
				omap_bandgap_writel(bg_ptr,
							   rval->bg_threshold,
							   tsr->bgap_threshold);
				omap_bandgap_writel(bg_ptr, rval->bg_ctrl,
							   tsr->bgap_mask_ctrl);
			}
		} else {
			temp = omap_bandgap_readl(bg_ptr,
						  tsr->temp_sensor_ctrl);
			temp &= (tsr->bgap_dtemp_mask);
			omap_bandgap_force_single_read(bg_ptr, i);
			if (temp == 0 && OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
				temp = omap_bandgap_readl(bg_ptr,
							  tsr->bgap_mask_ctrl);
				temp |= 1 << __ffs(tsr->mode_ctrl_mask);
				omap_bandgap_writel(bg_ptr, temp,
							   tsr->bgap_mask_ctrl);
			}
		}
	}

	return 0;
}
Exemplo n.º 7
0
/* This is the Talert handler. Call it only if HAS(TALERT) is set */
static irqreturn_t talert_irq_handler(int irq, void *data)
{
	struct omap_bandgap *bg_ptr = data;
	struct temp_sensor_registers *tsr;
	u32 t_hot = 0, t_cold = 0, temp, ctrl;
	int i;

	bg_ptr = data;
	/* Read the status of t_hot */
	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		tsr = bg_ptr->conf->sensors[i].registers;
		t_hot = omap_bandgap_readl(bg_ptr, tsr->bgap_status);
		t_hot &= tsr->status_hot_mask;

		/* Read the status of t_cold */
		t_cold = omap_bandgap_readl(bg_ptr, tsr->bgap_status);
		t_cold &= tsr->status_cold_mask;

		if (!t_cold && !t_hot)
			continue;

		ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
		/*
		 * One TALERT interrupt: Two sources
		 * If the interrupt is due to t_hot then mask t_hot and
		 * and unmask t_cold else mask t_cold and unmask t_hot
		 */
		if (t_hot) {
			ctrl &= ~tsr->mask_hot_mask;
			ctrl |= tsr->mask_cold_mask;
		} else if (t_cold) {
			ctrl &= ~tsr->mask_cold_mask;
			ctrl |= tsr->mask_hot_mask;
		}

		omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);

		dev_dbg(bg_ptr->dev,
			"%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
			__func__, bg_ptr->conf->sensors[i].domain,
			t_hot, t_cold);

		/* read temperature */
		temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
		temp &= tsr->bgap_dtemp_mask;

		/* report temperature to whom may concern */
		if (bg_ptr->conf->report_temperature)
			bg_ptr->conf->report_temperature(bg_ptr, i);
	}

	return IRQ_HANDLED;
}
Exemplo n.º 8
0
/**
 * omap_bandgap_read_update_interval() - read the sensor update interval
 * @bg_ptr - pointer to bandgap instance
 * @id - sensor id
 * @interval - resulting update interval in miliseconds
 *
 * returns 0 on success or the proper error code
 */
int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
					 int *interval)
{
	struct temp_sensor_registers *tsr;
	u32 time;
	int ret;

	ret = omap_bandgap_validate(bg_ptr, id);
	if (ret)
		return ret;

	if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
		return -ENOTSUPP;

	tsr = bg_ptr->conf->sensors[id].registers;
	time = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
	if (ret)
		return ret;
	time = (time & tsr->counter_mask) >> __ffs(tsr->counter_mask);
	time = time * 1000 / bg_ptr->clk_rate;

	*interval = time;

	return 0;
}
Exemplo n.º 9
0
/**
 * omap_bandgap_read_tcold() - reads sensor current tcold
 * @bg_ptr - pointer to bandgap instance
 * @id - sensor id
 * @tcold - resulting current tcold value
 *
 * returns 0 on success or the proper error code
 */
int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id,
			       int *tcold)
{
	struct temp_sensor_registers *tsr;
	u32 temp;
	int ret;

	ret = omap_bandgap_validate(bg_ptr, id);
	if (ret)
		return ret;

	if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
		return -ENOTSUPP;

	tsr = bg_ptr->conf->sensors[id].registers;
	temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
	temp = (temp & tsr->threshold_tcold_mask)
	    >> __ffs(tsr->threshold_tcold_mask);
	ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
	if (ret)
		return -EIO;

	*tcold = temp;

	return 0;
}
Exemplo n.º 10
0
/* Talert Thot threshold. Call it only if HAS(TALERT) is set */
static
int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot)
{
	struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
	struct temp_sensor_registers *tsr;
	u32 thresh_val, reg_val;
	int cold, err = 0;

	tsr = bg_ptr->conf->sensors[id].registers;

	/* obtain the T cold value */
	thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
	cold = (thresh_val & tsr->threshold_tcold_mask) >>
	    __ffs(tsr->threshold_tcold_mask);
	if (t_hot <= cold) {
		/* change the t_cold to t_hot - 5000 millidegrees */
		err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id, &cold);
		/* write the new t_cold value */
		reg_val = thresh_val & (~tsr->threshold_tcold_mask);
		reg_val |= cold << __ffs(tsr->threshold_tcold_mask);
		omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
		thresh_val = reg_val;
	}

	/* write the new t_hot value */
	reg_val = thresh_val & ~tsr->threshold_thot_mask;
	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
	if (err) {
		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
		return -EIO;
	}

	return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold);
}
Exemplo n.º 11
0
/* This is counter config. Call it only if HAS(COUNTER) is set */
static int configure_temp_sensor_counter(struct omap_bandgap *bg_ptr, int id,
					 u32 counter)
{
	struct temp_sensor_registers *tsr;
	u32 val;

	tsr = bg_ptr->conf->sensors[id].registers;
	val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
	val &= ~tsr->counter_mask;
	val |= counter << __ffs(tsr->counter_mask);
	omap_bandgap_writel(bg_ptr, val, tsr->bgap_counter);

	return 0;
}
Exemplo n.º 12
0
/* This is Tshut Tcold config. Call it only if HAS(TSHUT_CONFIG) is set */
static int temp_sensor_configure_tshut_cold(struct omap_bandgap *bg_ptr,
					    int id, int tshut_cold)
{
	struct temp_sensor_registers *tsr;
	u32 reg_val;

	tsr = bg_ptr->conf->sensors[id].registers;
	reg_val = omap_bandgap_readl(bg_ptr, tsr->tshut_threshold);
	reg_val &= ~tsr->tshut_cold_mask;
	reg_val |= tshut_cold << __ffs(tsr->tshut_cold_mask);
	omap_bandgap_writel(bg_ptr, reg_val, tsr->tshut_threshold);

	return 0;
}
Exemplo n.º 13
0
/**
 * enable_continuous_mode() - One time enabling of continuous conversion mode
 * @bg_ptr - pointer to scm instance
 *
 * Call this function only if HAS(MODE_CONFIG) is set
 */
static int enable_continuous_mode(struct omap_bandgap *bg_ptr)
{
	struct temp_sensor_registers *tsr;
	int i;
	u32 val;

	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		/* Perform a single read just before enabling continuous */
		omap_bandgap_force_single_read(bg_ptr, i);
		tsr = bg_ptr->conf->sensors[i].registers;
		val = omap_bandgap_readl(bg_ptr, tsr->bgap_mode_ctrl);
		val |= 1 << __ffs(tsr->mode_ctrl_mask);
		omap_bandgap_writel(bg_ptr, val, tsr->bgap_mode_ctrl);
	}

	return 0;
}
Exemplo n.º 14
0
static int omap_bandgap_power(struct omap_bandgap *bg_ptr, bool on)
{
	struct temp_sensor_registers *tsr;
	int i;
	u32 ctrl;

	if (!OMAP_BANDGAP_HAS(bg_ptr, POWER_SWITCH))
		return 0;

	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		tsr = bg_ptr->conf->sensors[i].registers;
		ctrl = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
		ctrl &= ~tsr->bgap_tempsoff_mask;
		/* active on 0 */
		ctrl |= !on << __ffs(tsr->bgap_tempsoff_mask);

		/* write BGAP_TEMPSOFF should be reset to 0 */
		omap_bandgap_writel(bg_ptr, ctrl, tsr->temp_sensor_ctrl);
	}

	return 0;
}
Exemplo n.º 15
0
/**
 * omap_bandgap_read_temperature() - report current temperature
 * @bg_ptr - pointer to bandgap instance
 * @id - sensor id
 * @temperature - resulting temperature
 *
 * returns 0 on success or the proper error code
 */
int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
				     int *temperature)
{
	struct temp_sensor_registers *tsr;
	u32 temp;
	int ret;

	ret = omap_bandgap_validate(bg_ptr, id);
	if (ret)
		return ret;

	tsr = bg_ptr->conf->sensors[id].registers;
	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
	temp &= tsr->bgap_dtemp_mask;

	ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
	if (ret)
		return -EIO;

	*temperature = temp;

	return 0;
}
Exemplo n.º 16
0
static
int __devinit omap_bandgap_probe(struct platform_device *pdev)
{
	struct omap_bandgap *bg_ptr;
	int clk_rate, ret = 0, i;

	bg_ptr = omap_bandgap_build(pdev);
	if (IS_ERR_OR_NULL(bg_ptr)) {
		dev_err(&pdev->dev, "failed to fetch platform data\n");
		return PTR_ERR(bg_ptr);
	}
	bg_ptr->dev = &pdev->dev;

	if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
		ret = omap_bandgap_tshut_init(bg_ptr, pdev);
		if (ret) {
			dev_err(&pdev->dev,
				"failed to initialize system tshut IRQ\n");
			return ret;
		}
	}

	bg_ptr->fclock = clk_get(NULL, bg_ptr->conf->fclock_name);
	ret = IS_ERR_OR_NULL(bg_ptr->fclock);
	if (ret) {
		dev_err(&pdev->dev, "failed to request fclock reference\n");
		goto free_irqs;
	}

	bg_ptr->div_clk = clk_get(NULL,  bg_ptr->conf->div_ck_name);
	ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
	if (ret) {
		dev_err(&pdev->dev,
			"failed to request div_ts_ck clock ref\n");
		goto free_irqs;
	}

	bg_ptr->conv_table = bg_ptr->conf->conv_table;
	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		struct temp_sensor_registers *tsr;
		u32 val;

		tsr = bg_ptr->conf->sensors[i].registers;
		/*
		 * check if the efuse has a non-zero value if not
		 * it is an untrimmed sample and the temperatures
		 * may not be accurate
		 */
		val = omap_bandgap_readl(bg_ptr, tsr->bgap_efuse);
		if (ret || !val)
			dev_info(&pdev->dev,
				 "Non-trimmed BGAP, Temp not accurate\n");
	}

	clk_rate = clk_round_rate(bg_ptr->div_clk,
				  bg_ptr->conf->sensors[0].ts_data->max_freq);
	if (clk_rate < bg_ptr->conf->sensors[0].ts_data->min_freq ||
	    clk_rate == 0xffffffff) {
		ret = -ENODEV;
		dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
		goto put_clks;
	}

	ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
	if (ret)
		dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");

	bg_ptr->clk_rate = clk_rate;
	clk_enable(bg_ptr->fclock);

	mutex_init(&bg_ptr->bg_mutex);
	bg_ptr->dev = &pdev->dev;
	platform_set_drvdata(pdev, bg_ptr);

	omap_bandgap_power(bg_ptr, true);

	/* Set default counter to 1 for now */
	if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
		for (i = 0; i < bg_ptr->conf->sensor_count; i++)
			configure_temp_sensor_counter(bg_ptr, i, 1);

	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		struct temp_sensor_data *ts_data;

		ts_data = bg_ptr->conf->sensors[i].ts_data;

		if (OMAP_BANDGAP_HAS(bg_ptr, TALERT))
			temp_sensor_init_talert_thresholds(bg_ptr, i,
							   ts_data->t_hot,
							   ts_data->t_cold);
		if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) {
			temp_sensor_configure_tshut_hot(bg_ptr, i,
							ts_data->tshut_hot);
			temp_sensor_configure_tshut_cold(bg_ptr, i,
							 ts_data->tshut_cold);
		}
	}

	if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
		enable_continuous_mode(bg_ptr);

	/* Set .250 seconds time as default counter */
	if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
		for (i = 0; i < bg_ptr->conf->sensor_count; i++)
			configure_temp_sensor_counter(bg_ptr, i,
						      bg_ptr->clk_rate / 4);

	/* Every thing is good? Then expose the sensors */
	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
		char *domain;

		if (bg_ptr->conf->sensors[i].register_cooling)
			bg_ptr->conf->sensors[i].register_cooling(bg_ptr, i);

		domain = bg_ptr->conf->sensors[i].domain;
		if (bg_ptr->conf->expose_sensor)
			bg_ptr->conf->expose_sensor(bg_ptr, i, domain);
	}

	/*
	 * Enable the Interrupts once everything is set. Otherwise irq handler
	 * might be called as soon as it is enabled where as rest of framework
	 * is still getting initialised.
	 */
	if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
		ret = omap_bandgap_talert_init(bg_ptr, pdev);
		if (ret) {
			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
			i = bg_ptr->conf->sensor_count;
			goto disable_clk;
		}
	}

	return 0;

disable_clk:
	clk_disable(bg_ptr->fclock);
put_clks:
	clk_put(bg_ptr->fclock);
	clk_put(bg_ptr->div_clk);
free_irqs:
	if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
		free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
		gpio_free(bg_ptr->tshut_gpio);
	}

	return ret;
}