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; }
int omap4460plus_temp_sensor_init(struct scm *scm_ptr) { struct omap_temp_sensor_registers *reg_ptr; struct omap4460plus_temp_sensor_data *ts_ptr; struct scm_regval *regval_ptr; int clk_rate, ret, i; scm_ptr->registers = kzalloc(sizeof(reg_ptr) * scm_ptr->cnt, GFP_KERNEL); if (!scm_ptr->registers) { pr_err("Unable to allocate mem for scm registers\n"); return -ENOMEM; } scm_ptr->ts_data = kzalloc(sizeof(ts_ptr) * scm_ptr->cnt, GFP_KERNEL); if (!scm_ptr->ts_data) { pr_err("Unable to allocate memory for ts data\n"); ret = -ENOMEM; goto fail_alloc; } scm_ptr->regval = kzalloc(sizeof(regval_ptr) * scm_ptr->cnt, GFP_KERNEL); if (!scm_ptr->regval) { pr_err("Unable to allocate memory for regval\n"); ret = -ENOMEM; goto fail_alloc; } #ifdef CONFIG_THERMAL_FRAMEWORK scm_ptr->therm_fw = kzalloc(sizeof(struct thermal_dev *) * scm_ptr->cnt, GFP_KERNEL); if (!scm_ptr->therm_fw) { pr_err("Unable to allocate memory for ts data\n"); return -ENOMEM; } #elif defined(CONFIG_CPU_THERMAL) scm_ptr->cpu_therm = kzalloc(sizeof(struct thermal_sensor_conf) * scm_ptr->cnt, GFP_KERNEL); if (!scm_ptr->cpu_therm) { pr_err("Unable to allocate memory for ts data\n"); goto clk_err; } #endif for (i = 0; i < scm_ptr->cnt; i++) { #ifdef CONFIG_THERMAL_FRAMEWORK scm_ptr->therm_fw[i] = kzalloc(sizeof(struct thermal_dev), GFP_KERNEL); #endif scm_ptr->regval[i] = kzalloc(sizeof(struct scm_regval), GFP_KERNEL); } if (scm_ptr->rev == 1) { scm_ptr->registers[0] = &omap4460_mpu_temp_sensor_registers; scm_ptr->ts_data[0] = &omap4460_mpu_temp_sensor_data; scm_ptr->conv_table = omap4460_adc_to_temp; /* * check if the efuse has a non-zero value if not * it is an untrimmed sample and the temperatures * may not be accurate */ if (!omap4plus_scm_readl(scm_ptr, scm_ptr->registers[0]->bgap_efuse)) pr_info("Non-trimmed BGAP, Temp not accurate\n"); #ifdef CONFIG_THERMAL_FRAMEWORK if (scm_ptr->therm_fw) { scm_ptr->therm_fw[0]->name = "omap_ondie_sensor"; scm_ptr->therm_fw[0]->domain_name = "cpu"; scm_ptr->therm_fw[0]->dev = scm_ptr->dev; scm_ptr->therm_fw[0]->dev_ops = &omap_sensor_ops; scm_ptr->therm_fw[0]->sen_id = 0; scm_ptr->therm_fw[0]->slope = 376; scm_ptr->therm_fw[0]->constant_offset = -16000; thermal_sensor_dev_register(scm_ptr->therm_fw[0]); } else { pr_err("%s:Cannot alloc memory for thermal fw\n", __func__); ret = -ENOMEM; } #elif defined(CONFIG_CPU_THERMAL) strncpy(scm_ptr->cpu_therm[0].name, "omap_ondie_sensor", SENSOR_NAME_LEN); scm_ptr->cpu_therm[0].private_data = scm_ptr; scm_ptr->cpu_therm[0].read_temperature = omap_read_temp; if (omap4_has_mpu_1_5ghz()) scm_ptr->cpu_therm[0].sensor_data = &omap4_1500mhz_bandgap_data; else scm_ptr->cpu_therm[0].sensor_data = &omap4_1200mhz_bandgap_data; omap_zones[0] = omap4_register_thermal(scm_ptr->cpu_therm); #endif } else if (scm_ptr->rev == 2) { scm_ptr->registers[0] = &omap5430_mpu_temp_sensor_registers; scm_ptr->ts_data[0] = &omap5430_mpu_temp_sensor_data; scm_ptr->registers[1] = &omap5430_gpu_temp_sensor_registers; scm_ptr->ts_data[1] = &omap5430_gpu_temp_sensor_data; scm_ptr->registers[2] = &omap5430_core_temp_sensor_registers; scm_ptr->ts_data[2] = &omap5430_core_temp_sensor_data; scm_ptr->conv_table = omap5430_adc_to_temp; #ifdef CONFIG_THERMAL_FRAMEWORK if (scm_ptr->therm_fw) { scm_ptr->therm_fw[0]->name = "omap_ondie_mpu_sensor"; scm_ptr->therm_fw[0]->domain_name = "cpu"; scm_ptr->therm_fw[0]->dev = scm_ptr->dev; scm_ptr->therm_fw[0]->dev_ops = &omap_sensor_ops; scm_ptr->therm_fw[0]->sen_id = 0; scm_ptr->therm_fw[0]->slope = 196; scm_ptr->therm_fw[0]->constant_offset = -6822; thermal_sensor_dev_register(scm_ptr->therm_fw[0]); scm_ptr->therm_fw[1]->name = "omap_ondie_gpu_sensor"; scm_ptr->therm_fw[1]->domain_name = "gpu"; scm_ptr->therm_fw[1]->dev = scm_ptr->dev; scm_ptr->therm_fw[1]->dev_ops = &omap_sensor_ops; scm_ptr->therm_fw[1]->sen_id = 1; scm_ptr->therm_fw[1]->slope = 0; scm_ptr->therm_fw[1]->constant_offset = 7000; thermal_sensor_dev_register(scm_ptr->therm_fw[1]); scm_ptr->therm_fw[2]->name = "omap_ondie_core_sensor"; scm_ptr->therm_fw[2]->domain_name = "core"; scm_ptr->therm_fw[2]->dev = scm_ptr->dev; scm_ptr->therm_fw[2]->dev_ops = &omap_sensor_ops; scm_ptr->therm_fw[2]->sen_id = 2; scm_ptr->therm_fw[2]->slope = 0; scm_ptr->therm_fw[2]->constant_offset = 0; thermal_sensor_dev_register(scm_ptr->therm_fw[2]); /*TO DO: Add for GPU and core */ } else { pr_err("%s:Cannot alloc memory for thermal fw\n", __func__); ret = -ENOMEM; } #elif defined(CONFIG_CPU_THERMAL) strncpy(scm_ptr->cpu_therm[0].name, "omap_ondie_sensor", SENSOR_NAME_LEN); scm_ptr->cpu_therm[0].private_data = scm_ptr; scm_ptr->cpu_therm[0].read_temperature = omap_read_temp; scm_ptr->cpu_therm[0].sensor_data = &omap5_1500mhz_bandgap_data; omap_zones[0] = omap4_register_thermal(&scm_ptr->cpu_therm[0]); strncpy(scm_ptr->cpu_therm[1].name, "omap_ondie_gpu_sensor", SENSOR_NAME_LEN); scm_ptr->cpu_therm[1].private_data = scm_ptr; scm_ptr->cpu_therm[1].read_temperature = omap_read_temp; scm_ptr->cpu_therm[1].sensor_data = &omap5_1500mhz_bandgap_data; strncpy(scm_ptr->cpu_therm[2].name, "omap_ondie_core_sensor", SENSOR_NAME_LEN); scm_ptr->cpu_therm[2].private_data = scm_ptr; scm_ptr->cpu_therm[2].read_temperature = omap_read_temp; scm_ptr->cpu_therm[2].sensor_data = &omap5_1500mhz_bandgap_data; #endif } if (scm_ptr->rev == 1) { clk_rate = clk_round_rate(scm_ptr->div_clk, scm_ptr->ts_data[0]->max_freq); if (clk_rate < scm_ptr->ts_data[0]->min_freq || clk_rate == 0xffffffff) { ret = -ENODEV; goto clk_err; } ret = clk_set_rate(scm_ptr->div_clk, clk_rate); if (ret) { pr_err("Cannot set clock rate\n"); goto clk_err; } scm_ptr->clk_rate = clk_rate; } else if (scm_ptr->rev == 2) { /* add clock rate code for omap5430 */ #ifdef CONFIG_MACH_OMAP_5430ZEBU scm_ptr->clk_rate = 1200; #else clk_rate = clk_round_rate(scm_ptr->fclock, scm_ptr->ts_data[0]->max_freq); if (clk_rate < scm_ptr->ts_data[0]->min_freq || clk_rate == 0xffffffff) { ret = -ENODEV; goto clk_err; } ret = clk_set_rate(scm_ptr->fclock, clk_rate); if (ret) { pr_err("Cannot set clock rate\n"); goto clk_err; } scm_ptr->clk_rate = clk_rate; #endif } clk_enable(scm_ptr->fclock); /* 1 clk cycle */ for (i = 0; i < scm_ptr->cnt; i++) configure_temp_sensor_counter(scm_ptr, i, 1); for (i = 0; i < scm_ptr->cnt; i++) { temp_sensor_init_talert_thresholds(scm_ptr, i, scm_ptr->ts_data[i]->t_hot, scm_ptr->ts_data[i]->t_cold); temp_sensor_configure_tshut_hot(scm_ptr, i, scm_ptr->ts_data[i]->tshut_hot); temp_sensor_configure_tshut_cold(scm_ptr, i, scm_ptr->ts_data[i]-> tshut_cold); } enable_continuous_mode(scm_ptr); /* Set .250 seconds time as default counter */ for (i = 0; i < scm_ptr->cnt; i++) { configure_temp_sensor_counter(scm_ptr, i, scm_ptr->clk_rate / 4); } return 0; clk_err: kfree(scm_ptr->ts_data); fail_alloc: kfree(scm_ptr->registers); return ret; }