exynos_tmu.c (9025d563cd9bd141a7b7f2095b6a760cd9d83a4e) exynos_tmu.c (14a11dc7e0dbf4acdd9c7b703ebd088f14def739)
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

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

42 * @pdata: pointer to the tmu platform/configuration data
43 * @base: base address of the single instance of the TMU controller.
44 * @base_second: base address of the common registers of the TMU controller.
45 * @irq: irq number of the TMU controller.
46 * @soc: id of the SOC type.
47 * @irq_work: pointer to the irq work structure.
48 * @lock: lock to implement synchronization.
49 * @clk: pointer to the clock structure.
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

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

42 * @pdata: pointer to the tmu platform/configuration data
43 * @base: base address of the single instance of the TMU controller.
44 * @base_second: base address of the common registers of the TMU controller.
45 * @irq: irq number of the TMU controller.
46 * @soc: id of the SOC type.
47 * @irq_work: pointer to the irq work structure.
48 * @lock: lock to implement synchronization.
49 * @clk: pointer to the clock structure.
50 * @clk_sec: pointer to the clock structure for accessing the base_second.
50 * @temp_error1: fused value of the first point trim.
51 * @temp_error2: fused value of the second point trim.
52 * @regulator: pointer to the TMU regulator structure.
53 * @reg_conf: pointer to structure to register with core thermal.
54 */
55struct exynos_tmu_data {
56 int id;
57 struct exynos_tmu_platform_data *pdata;
58 void __iomem *base;
59 void __iomem *base_second;
60 int irq;
61 enum soc_type soc;
62 struct work_struct irq_work;
63 struct mutex lock;
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 */
56struct exynos_tmu_data {
57 int id;
58 struct exynos_tmu_platform_data *pdata;
59 void __iomem *base;
60 void __iomem *base_second;
61 int irq;
62 enum soc_type soc;
63 struct work_struct irq_work;
64 struct mutex lock;
64 struct clk *clk;
65 struct clk *clk, *clk_sec;
65 u8 temp_error1, temp_error2;
66 struct regulator *regulator;
67 struct thermal_sensor_conf *reg_conf;
68};
69
70/*
71 * TMU treats temperature as a mapped temperature code.
72 * The temperature is converted differently depending on the calibration type.

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

147 struct exynos_tmu_platform_data *pdata = data->pdata;
148 const struct exynos_tmu_registers *reg = pdata->registers;
149 unsigned int status, trim_info = 0, con;
150 unsigned int rising_threshold = 0, falling_threshold = 0;
151 int ret = 0, threshold_code, i, trigger_levs = 0;
152
153 mutex_lock(&data->lock);
154 clk_enable(data->clk);
66 u8 temp_error1, temp_error2;
67 struct regulator *regulator;
68 struct thermal_sensor_conf *reg_conf;
69};
70
71/*
72 * TMU treats temperature as a mapped temperature code.
73 * The temperature is converted differently depending on the calibration type.

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

148 struct exynos_tmu_platform_data *pdata = data->pdata;
149 const struct exynos_tmu_registers *reg = pdata->registers;
150 unsigned int status, trim_info = 0, con;
151 unsigned int rising_threshold = 0, falling_threshold = 0;
152 int ret = 0, threshold_code, i, trigger_levs = 0;
153
154 mutex_lock(&data->lock);
155 clk_enable(data->clk);
156 if (!IS_ERR(data->clk_sec))
157 clk_enable(data->clk_sec);
155
156 if (TMU_SUPPORTS(pdata, READY_STATUS)) {
157 status = readb(data->base + reg->tmu_status);
158 if (!status) {
159 ret = -EBUSY;
160 goto out;
161 }
162 }

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

181 case 1:
182 trim_info = readl(data->base + reg->triminfo_data);
183 break;
184 case 2:
185 trim_info = readl(data->base -
186 EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
187 }
188 } else {
158
159 if (TMU_SUPPORTS(pdata, READY_STATUS)) {
160 status = readb(data->base + reg->tmu_status);
161 if (!status) {
162 ret = -EBUSY;
163 goto out;
164 }
165 }

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

184 case 1:
185 trim_info = readl(data->base + reg->triminfo_data);
186 break;
187 case 2:
188 trim_info = readl(data->base -
189 EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
190 }
191 } else {
189 trim_info = readl(data->base + reg->triminfo_data);
192 /* On exynos5420 the triminfo register is in the shared space */
193 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
194 trim_info = readl(data->base_second +
195 reg->triminfo_data);
196 else
197 trim_info = readl(data->base + reg->triminfo_data);
190 }
191 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
192 data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
193 EXYNOS_TMU_TEMP_MASK);
194
195 if (!data->temp_error1 ||
196 (pdata->min_efuse_value > data->temp_error1) ||
197 (data->temp_error1 > pdata->max_efuse_value))

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

297 }
298 }
299 /*Clear the PMIN in the common TMU register*/
300 if (reg->tmu_pmin && !data->id)
301 writel(0, data->base_second + reg->tmu_pmin);
302out:
303 clk_disable(data->clk);
304 mutex_unlock(&data->lock);
198 }
199 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
200 data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
201 EXYNOS_TMU_TEMP_MASK);
202
203 if (!data->temp_error1 ||
204 (pdata->min_efuse_value > data->temp_error1) ||
205 (data->temp_error1 > pdata->max_efuse_value))

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

305 }
306 }
307 /*Clear the PMIN in the common TMU register*/
308 if (reg->tmu_pmin && !data->id)
309 writel(0, data->base_second + reg->tmu_pmin);
310out:
311 clk_disable(data->clk);
312 mutex_unlock(&data->lock);
313 if (!IS_ERR(data->clk_sec))
314 clk_disable(data->clk_sec);
305
306 return ret;
307}
308
309static void exynos_tmu_control(struct platform_device *pdev, bool on)
310{
311 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
312 struct exynos_tmu_platform_data *pdata = data->pdata;

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

448static void exynos_tmu_work(struct work_struct *work)
449{
450 struct exynos_tmu_data *data = container_of(work,
451 struct exynos_tmu_data, irq_work);
452 struct exynos_tmu_platform_data *pdata = data->pdata;
453 const struct exynos_tmu_registers *reg = pdata->registers;
454 unsigned int val_irq, val_type;
455
315
316 return ret;
317}
318
319static void exynos_tmu_control(struct platform_device *pdev, bool on)
320{
321 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
322 struct exynos_tmu_platform_data *pdata = data->pdata;

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

458static void exynos_tmu_work(struct work_struct *work)
459{
460 struct exynos_tmu_data *data = container_of(work,
461 struct exynos_tmu_data, irq_work);
462 struct exynos_tmu_platform_data *pdata = data->pdata;
463 const struct exynos_tmu_registers *reg = pdata->registers;
464 unsigned int val_irq, val_type;
465
466 if (!IS_ERR(data->clk_sec))
467 clk_enable(data->clk_sec);
456 /* Find which sensor generated this interrupt */
457 if (reg->tmu_irqstatus) {
458 val_type = readl(data->base_second + reg->tmu_irqstatus);
459 if (!((val_type >> data->id) & 0x1))
460 goto out;
461 }
468 /* Find which sensor generated this interrupt */
469 if (reg->tmu_irqstatus) {
470 val_type = readl(data->base_second + reg->tmu_irqstatus);
471 if (!((val_type >> data->id) & 0x1))
472 goto out;
473 }
474 if (!IS_ERR(data->clk_sec))
475 clk_disable(data->clk_sec);
462
463 exynos_report_trigger(data->reg_conf);
464 mutex_lock(&data->lock);
465 clk_enable(data->clk);
466
467 /* TODO: take action based on particular interrupt */
468 val_irq = readl(data->base + reg->tmu_intstat);
469 /* clear the interrupts */

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

494 .compatible = "samsung,exynos4412-tmu",
495 .data = (void *)EXYNOS4412_TMU_DRV_DATA,
496 },
497 {
498 .compatible = "samsung,exynos5250-tmu",
499 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
500 },
501 {
476
477 exynos_report_trigger(data->reg_conf);
478 mutex_lock(&data->lock);
479 clk_enable(data->clk);
480
481 /* TODO: take action based on particular interrupt */
482 val_irq = readl(data->base + reg->tmu_intstat);
483 /* clear the interrupts */

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

508 .compatible = "samsung,exynos4412-tmu",
509 .data = (void *)EXYNOS4412_TMU_DRV_DATA,
510 },
511 {
512 .compatible = "samsung,exynos5250-tmu",
513 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
514 },
515 {
516 .compatible = "samsung,exynos5420-tmu",
517 .data = (void *)EXYNOS5420_TMU_DRV_DATA,
518 },
519 {
520 .compatible = "samsung,exynos5420-tmu-ext-triminfo",
521 .data = (void *)EXYNOS5420_TMU_DRV_DATA,
522 },
523 {
502 .compatible = "samsung,exynos5440-tmu",
503 .data = (void *)EXYNOS5440_TMU_DRV_DATA,
504 },
505 {},
506};
507MODULE_DEVICE_TABLE(of, exynos_tmu_match);
508
509static inline struct exynos_tmu_platform_data *exynos_get_driver_data(

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

624 INIT_WORK(&data->irq_work, exynos_tmu_work);
625
626 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
627 if (IS_ERR(data->clk)) {
628 dev_err(&pdev->dev, "Failed to get clock\n");
629 return PTR_ERR(data->clk);
630 }
631
524 .compatible = "samsung,exynos5440-tmu",
525 .data = (void *)EXYNOS5440_TMU_DRV_DATA,
526 },
527 {},
528};
529MODULE_DEVICE_TABLE(of, exynos_tmu_match);
530
531static inline struct exynos_tmu_platform_data *exynos_get_driver_data(

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

646 INIT_WORK(&data->irq_work, exynos_tmu_work);
647
648 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
649 if (IS_ERR(data->clk)) {
650 dev_err(&pdev->dev, "Failed to get clock\n");
651 return PTR_ERR(data->clk);
652 }
653
654 data->clk_sec = devm_clk_get(&pdev->dev, "tmu_triminfo_apbif");
655 if (IS_ERR(data->clk_sec)) {
656 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO) {
657 dev_err(&pdev->dev, "Failed to get triminfo clock\n");
658 return PTR_ERR(data->clk_sec);
659 }
660 } else {
661 ret = clk_prepare(data->clk_sec);
662 if (ret) {
663 dev_err(&pdev->dev, "Failed to get clock\n");
664 return ret;
665 }
666 }
667
632 ret = clk_prepare(data->clk);
668 ret = clk_prepare(data->clk);
633 if (ret)
634 return ret;
669 if (ret) {
670 dev_err(&pdev->dev, "Failed to get clock\n");
671 goto err_clk_sec;
672 }
635
636 if (pdata->type == SOC_ARCH_EXYNOS4210 ||
637 pdata->type == SOC_ARCH_EXYNOS4412 ||
638 pdata->type == SOC_ARCH_EXYNOS5250 ||
673
674 if (pdata->type == SOC_ARCH_EXYNOS4210 ||
675 pdata->type == SOC_ARCH_EXYNOS4412 ||
676 pdata->type == SOC_ARCH_EXYNOS5250 ||
677 pdata->type == SOC_ARCH_EXYNOS5420_TRIMINFO ||
639 pdata->type == SOC_ARCH_EXYNOS5440)
640 data->soc = pdata->type;
641 else {
642 ret = -EINVAL;
643 dev_err(&pdev->dev, "Platform not supported\n");
644 goto err_clk;
645 }
646

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

699 if (ret) {
700 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
701 goto err_clk;
702 }
703
704 return 0;
705err_clk:
706 clk_unprepare(data->clk);
678 pdata->type == SOC_ARCH_EXYNOS5440)
679 data->soc = pdata->type;
680 else {
681 ret = -EINVAL;
682 dev_err(&pdev->dev, "Platform not supported\n");
683 goto err_clk;
684 }
685

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

738 if (ret) {
739 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
740 goto err_clk;
741 }
742
743 return 0;
744err_clk:
745 clk_unprepare(data->clk);
746err_clk_sec:
747 if (!IS_ERR(data->clk_sec))
748 clk_unprepare(data->clk_sec);
707 return ret;
708}
709
710static int exynos_tmu_remove(struct platform_device *pdev)
711{
712 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
713
714 exynos_tmu_control(pdev, false);
715
716 exynos_unregister_thermal(data->reg_conf);
717
718 clk_unprepare(data->clk);
749 return ret;
750}
751
752static int exynos_tmu_remove(struct platform_device *pdev)
753{
754 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
755
756 exynos_tmu_control(pdev, false);
757
758 exynos_unregister_thermal(data->reg_conf);
759
760 clk_unprepare(data->clk);
761 if (!IS_ERR(data->clk_sec))
762 clk_unprepare(data->clk_sec);
719
720 if (!IS_ERR(data->regulator))
721 regulator_disable(data->regulator);
722
723 return 0;
724}
725
726#ifdef CONFIG_PM_SLEEP

--- 41 unchanged lines hidden ---
763
764 if (!IS_ERR(data->regulator))
765 regulator_disable(data->regulator);
766
767 return 0;
768}
769
770#ifdef CONFIG_PM_SLEEP

--- 41 unchanged lines hidden ---