static int omap_bandgap_restore_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; 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 (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); } } return 0; }
static int omap_bandgap_suspend(struct device *dev) { struct omap_bandgap *bg_ptr = dev_get_drvdata(dev); int err; err = omap_bandgap_save_ctxt(bg_ptr); omap_bandgap_power(bg_ptr, false); if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL)) clk_disable_unprepare(bg_ptr->fclock); return err; }
/** * omap_bandgap_write_update_interval() - set the update interval * @bg_ptr - pointer to bandgap instance * @id - sensor id * @interval - desired update interval in miliseconds * * returns 0 on success or the proper error code */ int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id, u32 interval) { int ret = omap_bandgap_validate(bg_ptr, id); if (ret) return ret; if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER)) return -ENOTSUPP; interval = interval * bg_ptr->clk_rate / 1000; mutex_lock(&bg_ptr->bg_mutex); configure_temp_sensor_counter(bg_ptr, id, interval); mutex_unlock(&bg_ptr->bg_mutex); return 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; }
/** * 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); time = (time & tsr->counter_mask) >> __ffs(tsr->counter_mask); time = time * 1000 / bg_ptr->clk_rate; *interval = time; return 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; }