thermal: exynos: Add TMU support for Exynos7 SoC
Add registers, bit fields and compatible strings for Exynos7 TMU (Thermal Management Unit). Following are a few of the differences in the Exynos7 TMU from earlier SoCs: - 8 trigger levels - Different bit offsets and more registers for the rising and falling thresholds. - New power down detection bit in the TMU_CONTROL register which does not update the CURRENT_TEMP0 when tmu power down is detected. - Change in bit offset for the NEXT_DATA field of EMUL_CON register. EMUL_CON register address has also changed. - INTSTAT and INTCLEAR registers present in earlier SoCs have been combined into one INTPEND register. The register address for INTCLEAR and INTPEND is also different. - Since there are 8 rising/falling interrupts as against at most 4 in earlier SoCs the INTEN bit offsets are different. - Multiple probe support which is handled by a TMU_CONTROL1 register (No support for this in the current patch). This patch adds special clock support required only for Exynos7. It also updates the "code_to_temp" prototype as Exynos7 has 9 bit code-temp mapping. Acked-by: Lukasz Majewski <l.majewski@samsung.com> Tested-by: Lukasz Majewski <l.majewski@samsung.com> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
This commit is contained in:
parent
14ccc17a37
commit
6c247393cf
2 changed files with 198 additions and 8 deletions
|
@ -119,6 +119,26 @@
|
||||||
#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
|
#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
|
||||||
#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
|
#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
|
||||||
|
|
||||||
|
/* Exynos7 specific registers */
|
||||||
|
#define EXYNOS7_THD_TEMP_RISE7_6 0x50
|
||||||
|
#define EXYNOS7_THD_TEMP_FALL7_6 0x60
|
||||||
|
#define EXYNOS7_TMU_REG_INTEN 0x110
|
||||||
|
#define EXYNOS7_TMU_REG_INTPEND 0x118
|
||||||
|
#define EXYNOS7_TMU_REG_EMUL_CON 0x160
|
||||||
|
|
||||||
|
#define EXYNOS7_TMU_TEMP_MASK 0x1ff
|
||||||
|
#define EXYNOS7_PD_DET_EN_SHIFT 23
|
||||||
|
#define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0
|
||||||
|
#define EXYNOS7_TMU_INTEN_RISE1_SHIFT 1
|
||||||
|
#define EXYNOS7_TMU_INTEN_RISE2_SHIFT 2
|
||||||
|
#define EXYNOS7_TMU_INTEN_RISE3_SHIFT 3
|
||||||
|
#define EXYNOS7_TMU_INTEN_RISE4_SHIFT 4
|
||||||
|
#define EXYNOS7_TMU_INTEN_RISE5_SHIFT 5
|
||||||
|
#define EXYNOS7_TMU_INTEN_RISE6_SHIFT 6
|
||||||
|
#define EXYNOS7_TMU_INTEN_RISE7_SHIFT 7
|
||||||
|
#define EXYNOS7_EMUL_DATA_SHIFT 7
|
||||||
|
#define EXYNOS7_EMUL_DATA_MASK 0x1ff
|
||||||
|
|
||||||
#define MCELSIUS 1000
|
#define MCELSIUS 1000
|
||||||
/**
|
/**
|
||||||
* struct exynos_tmu_data : A structure to hold the private data of the TMU
|
* struct exynos_tmu_data : A structure to hold the private data of the TMU
|
||||||
|
@ -133,6 +153,7 @@
|
||||||
* @lock: lock to implement synchronization.
|
* @lock: lock to implement synchronization.
|
||||||
* @clk: pointer to the clock structure.
|
* @clk: pointer to the clock structure.
|
||||||
* @clk_sec: pointer to the clock structure for accessing the base_second.
|
* @clk_sec: pointer to the clock structure for accessing the base_second.
|
||||||
|
* @sclk: pointer to the clock structure for accessing the tmu special clk.
|
||||||
* @temp_error1: fused value of the first point trim.
|
* @temp_error1: fused value of the first point trim.
|
||||||
* @temp_error2: fused value of the second point trim.
|
* @temp_error2: fused value of the second point trim.
|
||||||
* @regulator: pointer to the TMU regulator structure.
|
* @regulator: pointer to the TMU regulator structure.
|
||||||
|
@ -152,8 +173,8 @@ struct exynos_tmu_data {
|
||||||
enum soc_type soc;
|
enum soc_type soc;
|
||||||
struct work_struct irq_work;
|
struct work_struct irq_work;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct clk *clk, *clk_sec;
|
struct clk *clk, *clk_sec, *sclk;
|
||||||
u8 temp_error1, temp_error2;
|
u16 temp_error1, temp_error2;
|
||||||
struct regulator *regulator;
|
struct regulator *regulator;
|
||||||
struct thermal_zone_device *tzd;
|
struct thermal_zone_device *tzd;
|
||||||
|
|
||||||
|
@ -223,7 +244,7 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
|
||||||
* Calculate a temperature value from a temperature code.
|
* Calculate a temperature value from a temperature code.
|
||||||
* The unit of the temperature is degree Celsius.
|
* The unit of the temperature is degree Celsius.
|
||||||
*/
|
*/
|
||||||
static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
|
static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code)
|
||||||
{
|
{
|
||||||
struct exynos_tmu_platform_data *pdata = data->pdata;
|
struct exynos_tmu_platform_data *pdata = data->pdata;
|
||||||
int temp;
|
int temp;
|
||||||
|
@ -513,6 +534,84 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int exynos7_tmu_initialize(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
|
||||||
|
struct thermal_zone_device *tz = data->tzd;
|
||||||
|
struct exynos_tmu_platform_data *pdata = data->pdata;
|
||||||
|
unsigned int status, trim_info;
|
||||||
|
unsigned int rising_threshold = 0, falling_threshold = 0;
|
||||||
|
int ret = 0, threshold_code, i;
|
||||||
|
unsigned long temp, temp_hist;
|
||||||
|
unsigned int reg_off, bit_off;
|
||||||
|
|
||||||
|
status = readb(data->base + EXYNOS_TMU_REG_STATUS);
|
||||||
|
if (!status) {
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
|
||||||
|
|
||||||
|
data->temp_error1 = trim_info & EXYNOS7_TMU_TEMP_MASK;
|
||||||
|
if (!data->temp_error1 ||
|
||||||
|
(pdata->min_efuse_value > data->temp_error1) ||
|
||||||
|
(data->temp_error1 > pdata->max_efuse_value))
|
||||||
|
data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
|
||||||
|
|
||||||
|
/* Write temperature code for rising and falling threshold */
|
||||||
|
for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) {
|
||||||
|
/*
|
||||||
|
* On exynos7 there are 4 rising and 4 falling threshold
|
||||||
|
* registers (0x50-0x5c and 0x60-0x6c respectively). Each
|
||||||
|
* register holds the value of two threshold levels (at bit
|
||||||
|
* offsets 0 and 16). Based on the fact that there are atmost
|
||||||
|
* eight possible trigger levels, calculate the register and
|
||||||
|
* bit offsets where the threshold levels are to be written.
|
||||||
|
*
|
||||||
|
* e.g. EXYNOS7_THD_TEMP_RISE7_6 (0x50)
|
||||||
|
* [24:16] - Threshold level 7
|
||||||
|
* [8:0] - Threshold level 6
|
||||||
|
* e.g. EXYNOS7_THD_TEMP_RISE5_4 (0x54)
|
||||||
|
* [24:16] - Threshold level 5
|
||||||
|
* [8:0] - Threshold level 4
|
||||||
|
*
|
||||||
|
* and similarly for falling thresholds.
|
||||||
|
*
|
||||||
|
* Based on the above, calculate the register and bit offsets
|
||||||
|
* for rising/falling threshold levels and populate them.
|
||||||
|
*/
|
||||||
|
reg_off = ((7 - i) / 2) * 4;
|
||||||
|
bit_off = ((8 - i) % 2);
|
||||||
|
|
||||||
|
tz->ops->get_trip_temp(tz, i, &temp);
|
||||||
|
temp /= MCELSIUS;
|
||||||
|
|
||||||
|
tz->ops->get_trip_hyst(tz, i, &temp_hist);
|
||||||
|
temp_hist = temp - (temp_hist / MCELSIUS);
|
||||||
|
|
||||||
|
/* Set 9-bit temperature code for rising threshold levels */
|
||||||
|
threshold_code = temp_to_code(data, temp);
|
||||||
|
rising_threshold = readl(data->base +
|
||||||
|
EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
|
||||||
|
rising_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
|
||||||
|
rising_threshold |= threshold_code << (16 * bit_off);
|
||||||
|
writel(rising_threshold,
|
||||||
|
data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
|
||||||
|
|
||||||
|
/* Set 9-bit temperature code for falling threshold levels */
|
||||||
|
threshold_code = temp_to_code(data, temp_hist);
|
||||||
|
falling_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
|
||||||
|
falling_threshold |= threshold_code << (16 * bit_off);
|
||||||
|
writel(falling_threshold,
|
||||||
|
data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->tmu_clear_irqs(data);
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
|
static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
|
||||||
{
|
{
|
||||||
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
|
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
|
||||||
|
@ -573,6 +672,46 @@ static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
|
||||||
writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
|
writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void exynos7_tmu_control(struct platform_device *pdev, bool on)
|
||||||
|
{
|
||||||
|
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
|
||||||
|
struct thermal_zone_device *tz = data->tzd;
|
||||||
|
unsigned int con, interrupt_en;
|
||||||
|
|
||||||
|
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
|
||||||
|
|
||||||
|
if (on) {
|
||||||
|
con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
|
||||||
|
interrupt_en =
|
||||||
|
(of_thermal_is_trip_valid(tz, 7)
|
||||||
|
<< EXYNOS7_TMU_INTEN_RISE7_SHIFT) |
|
||||||
|
(of_thermal_is_trip_valid(tz, 6)
|
||||||
|
<< EXYNOS7_TMU_INTEN_RISE6_SHIFT) |
|
||||||
|
(of_thermal_is_trip_valid(tz, 5)
|
||||||
|
<< EXYNOS7_TMU_INTEN_RISE5_SHIFT) |
|
||||||
|
(of_thermal_is_trip_valid(tz, 4)
|
||||||
|
<< EXYNOS7_TMU_INTEN_RISE4_SHIFT) |
|
||||||
|
(of_thermal_is_trip_valid(tz, 3)
|
||||||
|
<< EXYNOS7_TMU_INTEN_RISE3_SHIFT) |
|
||||||
|
(of_thermal_is_trip_valid(tz, 2)
|
||||||
|
<< EXYNOS7_TMU_INTEN_RISE2_SHIFT) |
|
||||||
|
(of_thermal_is_trip_valid(tz, 1)
|
||||||
|
<< EXYNOS7_TMU_INTEN_RISE1_SHIFT) |
|
||||||
|
(of_thermal_is_trip_valid(tz, 0)
|
||||||
|
<< EXYNOS7_TMU_INTEN_RISE0_SHIFT);
|
||||||
|
|
||||||
|
interrupt_en |=
|
||||||
|
interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
|
||||||
|
} else {
|
||||||
|
con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
|
||||||
|
interrupt_en = 0; /* Disable all interrupts */
|
||||||
|
}
|
||||||
|
con |= 1 << EXYNOS7_PD_DET_EN_SHIFT;
|
||||||
|
|
||||||
|
writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN);
|
||||||
|
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
|
||||||
|
}
|
||||||
|
|
||||||
static int exynos_get_temp(void *p, long *temp)
|
static int exynos_get_temp(void *p, long *temp)
|
||||||
{
|
{
|
||||||
struct exynos_tmu_data *data = p;
|
struct exynos_tmu_data *data = p;
|
||||||
|
@ -602,9 +741,19 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
|
||||||
val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
|
val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
|
||||||
val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
|
val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
|
||||||
}
|
}
|
||||||
val &= ~(EXYNOS_EMUL_DATA_MASK << EXYNOS_EMUL_DATA_SHIFT);
|
if (data->soc == SOC_ARCH_EXYNOS7) {
|
||||||
val |= (temp_to_code(data, temp) << EXYNOS_EMUL_DATA_SHIFT) |
|
val &= ~(EXYNOS7_EMUL_DATA_MASK <<
|
||||||
EXYNOS_EMUL_ENABLE;
|
EXYNOS7_EMUL_DATA_SHIFT);
|
||||||
|
val |= (temp_to_code(data, temp) <<
|
||||||
|
EXYNOS7_EMUL_DATA_SHIFT) |
|
||||||
|
EXYNOS_EMUL_ENABLE;
|
||||||
|
} else {
|
||||||
|
val &= ~(EXYNOS_EMUL_DATA_MASK <<
|
||||||
|
EXYNOS_EMUL_DATA_SHIFT);
|
||||||
|
val |= (temp_to_code(data, temp) <<
|
||||||
|
EXYNOS_EMUL_DATA_SHIFT) |
|
||||||
|
EXYNOS_EMUL_ENABLE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
val &= ~EXYNOS_EMUL_ENABLE;
|
val &= ~EXYNOS_EMUL_ENABLE;
|
||||||
}
|
}
|
||||||
|
@ -620,6 +769,8 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
|
||||||
|
|
||||||
if (data->soc == SOC_ARCH_EXYNOS5260)
|
if (data->soc == SOC_ARCH_EXYNOS5260)
|
||||||
emul_con = EXYNOS5260_EMUL_CON;
|
emul_con = EXYNOS5260_EMUL_CON;
|
||||||
|
else if (data->soc == SOC_ARCH_EXYNOS7)
|
||||||
|
emul_con = EXYNOS7_TMU_REG_EMUL_CON;
|
||||||
else
|
else
|
||||||
emul_con = EXYNOS_EMUL_CON;
|
emul_con = EXYNOS_EMUL_CON;
|
||||||
|
|
||||||
|
@ -683,6 +834,12 @@ static int exynos5440_tmu_read(struct exynos_tmu_data *data)
|
||||||
return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
|
return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int exynos7_tmu_read(struct exynos_tmu_data *data)
|
||||||
|
{
|
||||||
|
return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) &
|
||||||
|
EXYNOS7_TMU_TEMP_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
static void exynos_tmu_work(struct work_struct *work)
|
static void exynos_tmu_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct exynos_tmu_data *data = container_of(work,
|
struct exynos_tmu_data *data = container_of(work,
|
||||||
|
@ -721,6 +878,9 @@ static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
|
||||||
if (data->soc == SOC_ARCH_EXYNOS5260) {
|
if (data->soc == SOC_ARCH_EXYNOS5260) {
|
||||||
tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
|
tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
|
||||||
tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
|
tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
|
||||||
|
} else if (data->soc == SOC_ARCH_EXYNOS7) {
|
||||||
|
tmu_intstat = EXYNOS7_TMU_REG_INTPEND;
|
||||||
|
tmu_intclear = EXYNOS7_TMU_REG_INTPEND;
|
||||||
} else {
|
} else {
|
||||||
tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
|
tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
|
||||||
tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
|
tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
|
||||||
|
@ -782,6 +942,9 @@ static const struct of_device_id exynos_tmu_match[] = {
|
||||||
{
|
{
|
||||||
.compatible = "samsung,exynos5440-tmu",
|
.compatible = "samsung,exynos5440-tmu",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.compatible = "samsung,exynos7-tmu",
|
||||||
|
},
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, exynos_tmu_match);
|
MODULE_DEVICE_TABLE(of, exynos_tmu_match);
|
||||||
|
@ -805,6 +968,8 @@ static int exynos_of_get_soc_type(struct device_node *np)
|
||||||
return SOC_ARCH_EXYNOS5420_TRIMINFO;
|
return SOC_ARCH_EXYNOS5420_TRIMINFO;
|
||||||
else if (of_device_is_compatible(np, "samsung,exynos5440-tmu"))
|
else if (of_device_is_compatible(np, "samsung,exynos5440-tmu"))
|
||||||
return SOC_ARCH_EXYNOS5440;
|
return SOC_ARCH_EXYNOS5440;
|
||||||
|
else if (of_device_is_compatible(np, "samsung,exynos7-tmu"))
|
||||||
|
return SOC_ARCH_EXYNOS7;
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -928,6 +1093,13 @@ static int exynos_map_dt_data(struct platform_device *pdev)
|
||||||
data->tmu_set_emulation = exynos5440_tmu_set_emulation;
|
data->tmu_set_emulation = exynos5440_tmu_set_emulation;
|
||||||
data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
|
data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
|
||||||
break;
|
break;
|
||||||
|
case SOC_ARCH_EXYNOS7:
|
||||||
|
data->tmu_initialize = exynos7_tmu_initialize;
|
||||||
|
data->tmu_control = exynos7_tmu_control;
|
||||||
|
data->tmu_read = exynos7_tmu_read;
|
||||||
|
data->tmu_set_emulation = exynos4412_tmu_set_emulation;
|
||||||
|
data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(&pdev->dev, "Platform not supported\n");
|
dev_err(&pdev->dev, "Platform not supported\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1017,21 +1189,37 @@ static int exynos_tmu_probe(struct platform_device *pdev)
|
||||||
goto err_clk_sec;
|
goto err_clk_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->soc == SOC_ARCH_EXYNOS7) {
|
||||||
|
data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk");
|
||||||
|
if (IS_ERR(data->sclk)) {
|
||||||
|
dev_err(&pdev->dev, "Failed to get sclk\n");
|
||||||
|
goto err_clk;
|
||||||
|
} else {
|
||||||
|
ret = clk_prepare_enable(data->sclk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Failed to enable sclk\n");
|
||||||
|
goto err_clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = exynos_tmu_initialize(pdev);
|
ret = exynos_tmu_initialize(pdev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to initialize TMU\n");
|
dev_err(&pdev->dev, "Failed to initialize TMU\n");
|
||||||
goto err_clk;
|
goto err_sclk;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
|
ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
|
||||||
IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
|
IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
|
dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
|
||||||
goto err_clk;
|
goto err_sclk;
|
||||||
}
|
}
|
||||||
|
|
||||||
exynos_tmu_control(pdev, true);
|
exynos_tmu_control(pdev, true);
|
||||||
return 0;
|
return 0;
|
||||||
|
err_sclk:
|
||||||
|
clk_disable_unprepare(data->sclk);
|
||||||
err_clk:
|
err_clk:
|
||||||
clk_unprepare(data->clk);
|
clk_unprepare(data->clk);
|
||||||
err_clk_sec:
|
err_clk_sec:
|
||||||
|
@ -1051,6 +1239,7 @@ static int exynos_tmu_remove(struct platform_device *pdev)
|
||||||
thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
|
thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
|
||||||
exynos_tmu_control(pdev, false);
|
exynos_tmu_control(pdev, false);
|
||||||
|
|
||||||
|
clk_disable_unprepare(data->sclk);
|
||||||
clk_unprepare(data->clk);
|
clk_unprepare(data->clk);
|
||||||
if (!IS_ERR(data->clk_sec))
|
if (!IS_ERR(data->clk_sec))
|
||||||
clk_unprepare(data->clk_sec);
|
clk_unprepare(data->clk_sec);
|
||||||
|
|
|
@ -34,6 +34,7 @@ enum soc_type {
|
||||||
SOC_ARCH_EXYNOS5420,
|
SOC_ARCH_EXYNOS5420,
|
||||||
SOC_ARCH_EXYNOS5420_TRIMINFO,
|
SOC_ARCH_EXYNOS5420_TRIMINFO,
|
||||||
SOC_ARCH_EXYNOS5440,
|
SOC_ARCH_EXYNOS5440,
|
||||||
|
SOC_ARCH_EXYNOS7,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue