exynos_tmu.c (285d994a51e45ca59a9cde34a3a0ea316e263617) | exynos_tmu.c (a7331f72d3eb2bf6a15405459f7c514607402ca6) |
---|---|
1/* 2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit) 3 * 4 * Copyright (C) 2011 Samsung Electronics 5 * Donggeun Kim <dg77.kim@samsung.com> 6 * Amit Daniel Kachhap <amit.kachhap@linaro.org> 7 * 8 * This program is free software; you can redistribute it and/or modify --- 42 unchanged lines hidden (view full) --- 51 * @temp_error1: fused value of the first point trim. 52 * @temp_error2: fused value of the second point trim. 53 * @regulator: pointer to the TMU regulator structure. 54 * @reg_conf: pointer to structure to register with core thermal. 55 * @tmu_initialize: SoC specific TMU initialization method 56 * @tmu_control: SoC specific TMU control method 57 * @tmu_read: SoC specific TMU temperature read method 58 * @tmu_set_emulation: SoC specific TMU emulation setting method | 1/* 2 * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit) 3 * 4 * Copyright (C) 2011 Samsung Electronics 5 * Donggeun Kim <dg77.kim@samsung.com> 6 * Amit Daniel Kachhap <amit.kachhap@linaro.org> 7 * 8 * This program is free software; you can redistribute it and/or modify --- 42 unchanged lines hidden (view full) --- 51 * @temp_error1: fused value of the first point trim. 52 * @temp_error2: fused value of the second point trim. 53 * @regulator: pointer to the TMU regulator structure. 54 * @reg_conf: pointer to structure to register with core thermal. 55 * @tmu_initialize: SoC specific TMU initialization method 56 * @tmu_control: SoC specific TMU control method 57 * @tmu_read: SoC specific TMU temperature read method 58 * @tmu_set_emulation: SoC specific TMU emulation setting method |
59 * @tmu_clear_irqs: SoC specific TMU interrupts clearing method |
|
59 */ 60struct exynos_tmu_data { 61 int id; 62 struct exynos_tmu_platform_data *pdata; 63 void __iomem *base; 64 void __iomem *base_second; 65 int irq; 66 enum soc_type soc; 67 struct work_struct irq_work; 68 struct mutex lock; 69 struct clk *clk, *clk_sec; 70 u8 temp_error1, temp_error2; 71 struct regulator *regulator; 72 struct thermal_sensor_conf *reg_conf; 73 int (*tmu_initialize)(struct platform_device *pdev); 74 void (*tmu_control)(struct platform_device *pdev, bool on); 75 int (*tmu_read)(struct exynos_tmu_data *data); 76 void (*tmu_set_emulation)(struct exynos_tmu_data *data, 77 unsigned long temp); | 60 */ 61struct exynos_tmu_data { 62 int id; 63 struct exynos_tmu_platform_data *pdata; 64 void __iomem *base; 65 void __iomem *base_second; 66 int irq; 67 enum soc_type soc; 68 struct work_struct irq_work; 69 struct mutex lock; 70 struct clk *clk, *clk_sec; 71 u8 temp_error1, temp_error2; 72 struct regulator *regulator; 73 struct thermal_sensor_conf *reg_conf; 74 int (*tmu_initialize)(struct platform_device *pdev); 75 void (*tmu_control)(struct platform_device *pdev, bool on); 76 int (*tmu_read)(struct exynos_tmu_data *data); 77 void (*tmu_set_emulation)(struct exynos_tmu_data *data, 78 unsigned long temp); |
79 void (*tmu_clear_irqs)(struct exynos_tmu_data *data); |
|
78}; 79 80/* 81 * TMU treats temperature as a mapped temperature code. 82 * The temperature is converted differently depending on the calibration type. 83 */ 84static int temp_to_code(struct exynos_tmu_data *data, u8 temp) 85{ --- 40 unchanged lines hidden (view full) --- 126 default: 127 temp = temp_code - pdata->default_temp_offset; 128 break; 129 } 130 131 return temp; 132} 133 | 80}; 81 82/* 83 * TMU treats temperature as a mapped temperature code. 84 * The temperature is converted differently depending on the calibration type. 85 */ 86static int temp_to_code(struct exynos_tmu_data *data, u8 temp) 87{ --- 40 unchanged lines hidden (view full) --- 128 default: 129 temp = temp_code - pdata->default_temp_offset; 130 break; 131 } 132 133 return temp; 134} 135 |
134static void exynos_tmu_clear_irqs(struct exynos_tmu_data *data) 135{ 136 const struct exynos_tmu_registers *reg = data->pdata->registers; 137 unsigned int val_irq; 138 139 val_irq = readl(data->base + reg->tmu_intstat); 140 /* 141 * Clear the interrupts. Please note that the documentation for 142 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly 143 * states that INTCLEAR register has a different placing of bits 144 * responsible for FALL IRQs than INTSTAT register. Exynos5420 145 * and Exynos5440 documentation is correct (Exynos4210 doesn't 146 * support FALL IRQs at all). 147 */ 148 writel(val_irq, data->base + reg->tmu_intclear); 149} 150 | |
151static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) 152{ 153 struct exynos_tmu_platform_data *pdata = data->pdata; 154 155 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK; 156 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) & 157 EXYNOS_TMU_TEMP_MASK); 158 --- 95 unchanged lines hidden (view full) --- 254 /* Write temperature code for threshold */ 255 threshold_code = temp_to_code(data, pdata->threshold); 256 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); 257 258 for (i = 0; i < pdata->non_hw_trigger_levels; i++) 259 writeb(pdata->trigger_levels[i], data->base + 260 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4); 261 | 136static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) 137{ 138 struct exynos_tmu_platform_data *pdata = data->pdata; 139 140 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK; 141 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) & 142 EXYNOS_TMU_TEMP_MASK); 143 --- 95 unchanged lines hidden (view full) --- 239 /* Write temperature code for threshold */ 240 threshold_code = temp_to_code(data, pdata->threshold); 241 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); 242 243 for (i = 0; i < pdata->non_hw_trigger_levels; i++) 244 writeb(pdata->trigger_levels[i], data->base + 245 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4); 246 |
262 exynos_tmu_clear_irqs(data); | 247 data->tmu_clear_irqs(data); |
263out: 264 return ret; 265} 266 267static int exynos4412_tmu_initialize(struct platform_device *pdev) 268{ 269 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 270 struct exynos_tmu_platform_data *pdata = data->pdata; --- 28 unchanged lines hidden (view full) --- 299 sanitize_temp_error(data, trim_info); 300 301 /* Write temperature code for rising and falling threshold */ 302 rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE); 303 rising_threshold = get_th_reg(data, rising_threshold, false); 304 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); 305 writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL); 306 | 248out: 249 return ret; 250} 251 252static int exynos4412_tmu_initialize(struct platform_device *pdev) 253{ 254 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 255 struct exynos_tmu_platform_data *pdata = data->pdata; --- 28 unchanged lines hidden (view full) --- 284 sanitize_temp_error(data, trim_info); 285 286 /* Write temperature code for rising and falling threshold */ 287 rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE); 288 rising_threshold = get_th_reg(data, rising_threshold, false); 289 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); 290 writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL); 291 |
307 exynos_tmu_clear_irqs(data); | 292 data->tmu_clear_irqs(data); |
308 309 /* if last threshold limit is also present */ 310 i = pdata->max_trigger_level - 1; 311 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) { 312 threshold_code = temp_to_code(data, pdata->trigger_levels[i]); 313 /* 1-4 level to be assigned in th0 reg */ 314 rising_threshold &= ~(0xff << 8 * i); 315 rising_threshold |= threshold_code << 8 * i; --- 32 unchanged lines hidden (view full) --- 348 sanitize_temp_error(data, trim_info); 349 350 /* Write temperature code for rising and falling threshold */ 351 rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0); 352 rising_threshold = get_th_reg(data, rising_threshold, false); 353 writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0); 354 writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1); 355 | 293 294 /* if last threshold limit is also present */ 295 i = pdata->max_trigger_level - 1; 296 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) { 297 threshold_code = temp_to_code(data, pdata->trigger_levels[i]); 298 /* 1-4 level to be assigned in th0 reg */ 299 rising_threshold &= ~(0xff << 8 * i); 300 rising_threshold |= threshold_code << 8 * i; --- 32 unchanged lines hidden (view full) --- 333 sanitize_temp_error(data, trim_info); 334 335 /* Write temperature code for rising and falling threshold */ 336 rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0); 337 rising_threshold = get_th_reg(data, rising_threshold, false); 338 writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0); 339 writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1); 340 |
356 exynos_tmu_clear_irqs(data); | 341 data->tmu_clear_irqs(data); |
357 358 /* if last threshold limit is also present */ 359 i = pdata->max_trigger_level - 1; 360 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) { 361 threshold_code = temp_to_code(data, pdata->trigger_levels[i]); 362 /* 5th level to be assigned in th2 reg */ 363 rising_threshold = 364 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT; --- 187 unchanged lines hidden (view full) --- 552 if (!IS_ERR(data->clk_sec)) 553 clk_disable(data->clk_sec); 554 555 exynos_report_trigger(data->reg_conf); 556 mutex_lock(&data->lock); 557 clk_enable(data->clk); 558 559 /* TODO: take action based on particular interrupt */ | 342 343 /* if last threshold limit is also present */ 344 i = pdata->max_trigger_level - 1; 345 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) { 346 threshold_code = temp_to_code(data, pdata->trigger_levels[i]); 347 /* 5th level to be assigned in th2 reg */ 348 rising_threshold = 349 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT; --- 187 unchanged lines hidden (view full) --- 537 if (!IS_ERR(data->clk_sec)) 538 clk_disable(data->clk_sec); 539 540 exynos_report_trigger(data->reg_conf); 541 mutex_lock(&data->lock); 542 clk_enable(data->clk); 543 544 /* TODO: take action based on particular interrupt */ |
560 exynos_tmu_clear_irqs(data); | 545 data->tmu_clear_irqs(data); |
561 562 clk_disable(data->clk); 563 mutex_unlock(&data->lock); 564out: 565 enable_irq(data->irq); 566} 567 | 546 547 clk_disable(data->clk); 548 mutex_unlock(&data->lock); 549out: 550 enable_irq(data->irq); 551} 552 |
553static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data) 554{ 555 unsigned int val_irq; 556 u32 tmu_intstat, tmu_intclear; 557 558 if (data->soc == SOC_ARCH_EXYNOS5260) { 559 tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT; 560 tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR; 561 } else { 562 tmu_intstat = EXYNOS_TMU_REG_INTSTAT; 563 tmu_intclear = EXYNOS_TMU_REG_INTCLEAR; 564 } 565 566 val_irq = readl(data->base + tmu_intstat); 567 /* 568 * Clear the interrupts. Please note that the documentation for 569 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly 570 * states that INTCLEAR register has a different placing of bits 571 * responsible for FALL IRQs than INTSTAT register. Exynos5420 572 * and Exynos5440 documentation is correct (Exynos4210 doesn't 573 * support FALL IRQs at all). 574 */ 575 writel(val_irq, data->base + tmu_intclear); 576} 577 578static void exynos5440_tmu_clear_irqs(struct exynos_tmu_data *data) 579{ 580 unsigned int val_irq; 581 582 val_irq = readl(data->base + EXYNOS5440_TMU_S0_7_IRQ); 583 /* clear the interrupts */ 584 writel(val_irq, data->base + EXYNOS5440_TMU_S0_7_IRQ); 585} 586 |
|
568static irqreturn_t exynos_tmu_irq(int irq, void *id) 569{ 570 struct exynos_tmu_data *data = id; 571 572 disable_irq_nosync(irq); 573 schedule_work(&data->irq_work); 574 575 return IRQ_HANDLED; --- 179 unchanged lines hidden (view full) --- 755 756 data->soc = pdata->type; 757 758 switch (data->soc) { 759 case SOC_ARCH_EXYNOS4210: 760 data->tmu_initialize = exynos4210_tmu_initialize; 761 data->tmu_control = exynos4210_tmu_control; 762 data->tmu_read = exynos4210_tmu_read; | 587static irqreturn_t exynos_tmu_irq(int irq, void *id) 588{ 589 struct exynos_tmu_data *data = id; 590 591 disable_irq_nosync(irq); 592 schedule_work(&data->irq_work); 593 594 return IRQ_HANDLED; --- 179 unchanged lines hidden (view full) --- 774 775 data->soc = pdata->type; 776 777 switch (data->soc) { 778 case SOC_ARCH_EXYNOS4210: 779 data->tmu_initialize = exynos4210_tmu_initialize; 780 data->tmu_control = exynos4210_tmu_control; 781 data->tmu_read = exynos4210_tmu_read; |
782 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; |
|
763 break; 764 case SOC_ARCH_EXYNOS3250: 765 case SOC_ARCH_EXYNOS4412: 766 case SOC_ARCH_EXYNOS5250: 767 case SOC_ARCH_EXYNOS5260: 768 case SOC_ARCH_EXYNOS5420: 769 case SOC_ARCH_EXYNOS5420_TRIMINFO: 770 data->tmu_initialize = exynos4412_tmu_initialize; 771 data->tmu_control = exynos4210_tmu_control; 772 data->tmu_read = exynos4412_tmu_read; 773 data->tmu_set_emulation = exynos4412_tmu_set_emulation; | 783 break; 784 case SOC_ARCH_EXYNOS3250: 785 case SOC_ARCH_EXYNOS4412: 786 case SOC_ARCH_EXYNOS5250: 787 case SOC_ARCH_EXYNOS5260: 788 case SOC_ARCH_EXYNOS5420: 789 case SOC_ARCH_EXYNOS5420_TRIMINFO: 790 data->tmu_initialize = exynos4412_tmu_initialize; 791 data->tmu_control = exynos4210_tmu_control; 792 data->tmu_read = exynos4412_tmu_read; 793 data->tmu_set_emulation = exynos4412_tmu_set_emulation; |
794 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; |
|
774 break; 775 case SOC_ARCH_EXYNOS5440: 776 data->tmu_initialize = exynos5440_tmu_initialize; 777 data->tmu_control = exynos5440_tmu_control; 778 data->tmu_read = exynos5440_tmu_read; 779 data->tmu_set_emulation = exynos5440_tmu_set_emulation; | 795 break; 796 case SOC_ARCH_EXYNOS5440: 797 data->tmu_initialize = exynos5440_tmu_initialize; 798 data->tmu_control = exynos5440_tmu_control; 799 data->tmu_read = exynos5440_tmu_read; 800 data->tmu_set_emulation = exynos5440_tmu_set_emulation; |
801 data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; |
|
780 break; 781 default: 782 ret = -EINVAL; 783 dev_err(&pdev->dev, "Platform not supported\n"); 784 goto err_clk; 785 } 786 787 ret = exynos_tmu_initialize(pdev); --- 124 unchanged lines hidden --- | 802 break; 803 default: 804 ret = -EINVAL; 805 dev_err(&pdev->dev, "Platform not supported\n"); 806 goto err_clk; 807 } 808 809 ret = exynos_tmu_initialize(pdev); --- 124 unchanged lines hidden --- |