exynos_tmu.c (fccfe0993b5dc550e5f9fbb716fb0b588c5fdbc1) exynos_tmu.c (199b3e3c860cdf3f092e7cbb2bf08b8a96ed4beb)
1/*
2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
3 *
4 * Copyright (C) 2014 Samsung Electronics
5 * Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
6 * Lukasz Majewski <l.majewski@samsung.com>
7 *
8 * Copyright (C) 2011 Samsung Electronics

--- 163 unchanged lines hidden (view full) ---

172
173#define EXYNOS_NOISE_CANCEL_MODE 4
174
175#define MCELSIUS 1000
176/**
177 * struct exynos_tmu_data : A structure to hold the private data of the TMU
178 driver
179 * @id: identifier of the one instance of the TMU controller.
1/*
2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
3 *
4 * Copyright (C) 2014 Samsung Electronics
5 * Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
6 * Lukasz Majewski <l.majewski@samsung.com>
7 *
8 * Copyright (C) 2011 Samsung Electronics

--- 163 unchanged lines hidden (view full) ---

172
173#define EXYNOS_NOISE_CANCEL_MODE 4
174
175#define MCELSIUS 1000
176/**
177 * struct exynos_tmu_data : A structure to hold the private data of the TMU
178 driver
179 * @id: identifier of the one instance of the TMU controller.
180 * @pdata: pointer to the tmu platform/configuration data
181 * @base: base address of the single instance of the TMU controller.
182 * @base_second: base address of the common registers of the TMU controller.
183 * @irq: irq number of the TMU controller.
184 * @soc: id of the SOC type.
185 * @irq_work: pointer to the irq work structure.
186 * @lock: lock to implement synchronization.
187 * @clk: pointer to the clock structure.
188 * @clk_sec: pointer to the clock structure for accessing the base_second.
189 * @sclk: pointer to the clock structure for accessing the tmu special clk.
180 * @base: base address of the single instance of the TMU controller.
181 * @base_second: base address of the common registers of the TMU controller.
182 * @irq: irq number of the TMU controller.
183 * @soc: id of the SOC type.
184 * @irq_work: pointer to the irq work structure.
185 * @lock: lock to implement synchronization.
186 * @clk: pointer to the clock structure.
187 * @clk_sec: pointer to the clock structure for accessing the base_second.
188 * @sclk: pointer to the clock structure for accessing the tmu special clk.
189 * @cal_type: calibration type for temperature
190 * @efuse_value: SoC defined fuse value
191 * @min_efuse_value: minimum valid trimming data
192 * @max_efuse_value: maximum valid trimming data
193 * @temp_error1: fused value of the first point trim.
194 * @temp_error2: fused value of the second point trim.
195 * @gain: gain of amplifier in the positive-TC generator block
196 * 0 < gain <= 15
197 * @reference_voltage: reference voltage of amplifier

--- 6 unchanged lines hidden (view full) ---

204 * @tmu_initialize: SoC specific TMU initialization method
205 * @tmu_control: SoC specific TMU control method
206 * @tmu_read: SoC specific TMU temperature read method
207 * @tmu_set_emulation: SoC specific TMU emulation setting method
208 * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
209 */
210struct exynos_tmu_data {
211 int id;
190 * @efuse_value: SoC defined fuse value
191 * @min_efuse_value: minimum valid trimming data
192 * @max_efuse_value: maximum valid trimming data
193 * @temp_error1: fused value of the first point trim.
194 * @temp_error2: fused value of the second point trim.
195 * @gain: gain of amplifier in the positive-TC generator block
196 * 0 < gain <= 15
197 * @reference_voltage: reference voltage of amplifier

--- 6 unchanged lines hidden (view full) ---

204 * @tmu_initialize: SoC specific TMU initialization method
205 * @tmu_control: SoC specific TMU control method
206 * @tmu_read: SoC specific TMU temperature read method
207 * @tmu_set_emulation: SoC specific TMU emulation setting method
208 * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
209 */
210struct exynos_tmu_data {
211 int id;
212 struct exynos_tmu_platform_data *pdata;
213 void __iomem *base;
214 void __iomem *base_second;
215 int irq;
216 enum soc_type soc;
217 struct work_struct irq_work;
218 struct mutex lock;
219 struct clk *clk, *clk_sec, *sclk;
212 void __iomem *base;
213 void __iomem *base_second;
214 int irq;
215 enum soc_type soc;
216 struct work_struct irq_work;
217 struct mutex lock;
218 struct clk *clk, *clk_sec, *sclk;
219 u32 cal_type;
220 u32 efuse_value;
221 u32 min_efuse_value;
222 u32 max_efuse_value;
223 u16 temp_error1, temp_error2;
224 u8 gain;
225 u8 reference_voltage;
226 struct regulator *regulator;
227 struct thermal_zone_device *tzd;

--- 35 unchanged lines hidden (view full) ---

263}
264
265/*
266 * TMU treats temperature as a mapped temperature code.
267 * The temperature is converted differently depending on the calibration type.
268 */
269static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
270{
220 u32 efuse_value;
221 u32 min_efuse_value;
222 u32 max_efuse_value;
223 u16 temp_error1, temp_error2;
224 u8 gain;
225 u8 reference_voltage;
226 struct regulator *regulator;
227 struct thermal_zone_device *tzd;

--- 35 unchanged lines hidden (view full) ---

263}
264
265/*
266 * TMU treats temperature as a mapped temperature code.
267 * The temperature is converted differently depending on the calibration type.
268 */
269static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
270{
271 struct exynos_tmu_platform_data *pdata = data->pdata;
272
273 if (pdata->cal_type == TYPE_ONE_POINT_TRIMMING)
271 if (data->cal_type == TYPE_ONE_POINT_TRIMMING)
274 return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM;
275
276 return (temp - EXYNOS_FIRST_POINT_TRIM) *
277 (data->temp_error2 - data->temp_error1) /
278 (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) +
279 data->temp_error1;
280}
281
282/*
283 * Calculate a temperature value from a temperature code.
284 * The unit of the temperature is degree Celsius.
285 */
286static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code)
287{
272 return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM;
273
274 return (temp - EXYNOS_FIRST_POINT_TRIM) *
275 (data->temp_error2 - data->temp_error1) /
276 (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) +
277 data->temp_error1;
278}
279
280/*
281 * Calculate a temperature value from a temperature code.
282 * The unit of the temperature is degree Celsius.
283 */
284static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code)
285{
288 struct exynos_tmu_platform_data *pdata = data->pdata;
289
290 if (pdata->cal_type == TYPE_ONE_POINT_TRIMMING)
286 if (data->cal_type == TYPE_ONE_POINT_TRIMMING)
291 return temp_code - data->temp_error1 + EXYNOS_FIRST_POINT_TRIM;
292
293 return (temp_code - data->temp_error1) *
294 (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) /
295 (data->temp_error2 - data->temp_error1) +
296 EXYNOS_FIRST_POINT_TRIM;
297}
298

--- 215 unchanged lines hidden (view full) ---

514
515out:
516 return ret;
517}
518
519static int exynos5433_tmu_initialize(struct platform_device *pdev)
520{
521 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
287 return temp_code - data->temp_error1 + EXYNOS_FIRST_POINT_TRIM;
288
289 return (temp_code - data->temp_error1) *
290 (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) /
291 (data->temp_error2 - data->temp_error1) +
292 EXYNOS_FIRST_POINT_TRIM;
293}
294

--- 215 unchanged lines hidden (view full) ---

510
511out:
512 return ret;
513}
514
515static int exynos5433_tmu_initialize(struct platform_device *pdev)
516{
517 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
522 struct exynos_tmu_platform_data *pdata = data->pdata;
523 struct thermal_zone_device *tz = data->tzd;
524 unsigned int status, trim_info;
525 unsigned int rising_threshold = 0, falling_threshold = 0;
526 int temp, temp_hist;
527 int ret = 0, threshold_code, i, sensor_id, cal_type;
528
529 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
530 if (!status) {

--- 10 unchanged lines hidden (view full) ---

541 dev_info(&pdev->dev, "Temperature sensor ID: 0x%x\n", sensor_id);
542
543 /* Read the calibration mode */
544 writel(trim_info, data->base + EXYNOS_TMU_REG_TRIMINFO);
545 cal_type = (trim_info & EXYNOS5433_TRIMINFO_CALIB_SEL_MASK)
546 >> EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT;
547
548 switch (cal_type) {
518 struct thermal_zone_device *tz = data->tzd;
519 unsigned int status, trim_info;
520 unsigned int rising_threshold = 0, falling_threshold = 0;
521 int temp, temp_hist;
522 int ret = 0, threshold_code, i, sensor_id, cal_type;
523
524 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
525 if (!status) {

--- 10 unchanged lines hidden (view full) ---

536 dev_info(&pdev->dev, "Temperature sensor ID: 0x%x\n", sensor_id);
537
538 /* Read the calibration mode */
539 writel(trim_info, data->base + EXYNOS_TMU_REG_TRIMINFO);
540 cal_type = (trim_info & EXYNOS5433_TRIMINFO_CALIB_SEL_MASK)
541 >> EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT;
542
543 switch (cal_type) {
549 case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING:
550 pdata->cal_type = TYPE_ONE_POINT_TRIMMING;
551 break;
552 case EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING:
544 case EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING:
553 pdata->cal_type = TYPE_TWO_POINT_TRIMMING;
545 data->cal_type = TYPE_TWO_POINT_TRIMMING;
554 break;
546 break;
547 case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING:
555 default:
548 default:
556 pdata->cal_type = TYPE_ONE_POINT_TRIMMING;
549 data->cal_type = TYPE_ONE_POINT_TRIMMING;
557 break;
558 }
559
560 dev_info(&pdev->dev, "Calibration type is %d-point calibration\n",
561 cal_type ? 2 : 1);
562
563 /* Write temperature code for rising and falling threshold */
564 for (i = 0; i < of_thermal_get_ntrips(tz); i++) {

--- 563 unchanged lines hidden (view full) ---

1128 }, {
1129 .compatible = "samsung,exynos7-tmu",
1130 .data = (const void *)SOC_ARCH_EXYNOS7,
1131 },
1132 { },
1133};
1134MODULE_DEVICE_TABLE(of, exynos_tmu_match);
1135
550 break;
551 }
552
553 dev_info(&pdev->dev, "Calibration type is %d-point calibration\n",
554 cal_type ? 2 : 1);
555
556 /* Write temperature code for rising and falling threshold */
557 for (i = 0; i < of_thermal_get_ntrips(tz); i++) {

--- 563 unchanged lines hidden (view full) ---

1121 }, {
1122 .compatible = "samsung,exynos7-tmu",
1123 .data = (const void *)SOC_ARCH_EXYNOS7,
1124 },
1125 { },
1126};
1127MODULE_DEVICE_TABLE(of, exynos_tmu_match);
1128
1136static int exynos_of_sensor_conf(struct device_node *np,
1137 struct exynos_tmu_platform_data *pdata)
1138{
1139 of_node_get(np);
1140
1141 of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type);
1142
1143 of_node_put(np);
1144 return 0;
1145}
1146
1147static int exynos_map_dt_data(struct platform_device *pdev)
1148{
1149 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1129static int exynos_map_dt_data(struct platform_device *pdev)
1130{
1131 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1150 struct exynos_tmu_platform_data *pdata;
1151 struct resource res;
1152
1153 if (!data || !pdev->dev.of_node)
1154 return -ENODEV;
1155
1156 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
1157 if (data->id < 0)
1158 data->id = 0;

--- 10 unchanged lines hidden (view full) ---

1169 }
1170
1171 data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
1172 if (!data->base) {
1173 dev_err(&pdev->dev, "Failed to ioremap memory\n");
1174 return -EADDRNOTAVAIL;
1175 }
1176
1132 struct resource res;
1133
1134 if (!data || !pdev->dev.of_node)
1135 return -ENODEV;
1136
1137 data->id = of_alias_get_id(pdev->dev.of_node, "tmuctrl");
1138 if (data->id < 0)
1139 data->id = 0;

--- 10 unchanged lines hidden (view full) ---

1150 }
1151
1152 data->base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
1153 if (!data->base) {
1154 dev_err(&pdev->dev, "Failed to ioremap memory\n");
1155 return -EADDRNOTAVAIL;
1156 }
1157
1177 pdata = devm_kzalloc(&pdev->dev,
1178 sizeof(struct exynos_tmu_platform_data),
1179 GFP_KERNEL);
1180 if (!pdata)
1181 return -ENOMEM;
1182
1183 exynos_of_sensor_conf(pdev->dev.of_node, pdata);
1184 data->pdata = pdata;
1185 data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev);
1186
1187 switch (data->soc) {
1188 case SOC_ARCH_EXYNOS4210:
1189 data->tmu_initialize = exynos4210_tmu_initialize;
1190 data->tmu_control = exynos4210_tmu_control;
1191 data->tmu_read = exynos4210_tmu_read;
1192 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;

--- 68 unchanged lines hidden (view full) ---

1261 data->min_efuse_value = 15;
1262 data->max_efuse_value = 100;
1263 break;
1264 default:
1265 dev_err(&pdev->dev, "Platform not supported\n");
1266 return -EINVAL;
1267 }
1268
1158 data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev);
1159
1160 switch (data->soc) {
1161 case SOC_ARCH_EXYNOS4210:
1162 data->tmu_initialize = exynos4210_tmu_initialize;
1163 data->tmu_control = exynos4210_tmu_control;
1164 data->tmu_read = exynos4210_tmu_read;
1165 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;

--- 68 unchanged lines hidden (view full) ---

1234 data->min_efuse_value = 15;
1235 data->max_efuse_value = 100;
1236 break;
1237 default:
1238 dev_err(&pdev->dev, "Platform not supported\n");
1239 return -EINVAL;
1240 }
1241
1242 data->cal_type = TYPE_ONE_POINT_TRIMMING;
1243
1269 /*
1270 * Check if the TMU shares some registers and then try to map the
1271 * memory of common registers.
1272 */
1273 if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO &&
1274 data->soc != SOC_ARCH_EXYNOS5440)
1275 return 0;
1276

--- 208 unchanged lines hidden ---
1244 /*
1245 * Check if the TMU shares some registers and then try to map the
1246 * memory of common registers.
1247 */
1248 if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO &&
1249 data->soc != SOC_ARCH_EXYNOS5440)
1250 return 0;
1251

--- 208 unchanged lines hidden ---