thermal/drivers/exynos: Use set_trips ops
Currently, each trip point defined in the device tree corresponds to a single hardware interrupt. This commit instead switches to using two hardware interrupts, whose values are set dynamically using the set_trips callback. Additionally, the critical temperature threshold is handled specifically. Setting interrupts in this way also fixes a long-standing lockdep warning, which was caused by calling thermal_zone_get_trips with our lock being held. Do note that this requires TMU initialization to be split into two parts, as done by the parent commit: parts of the initialization call into the thermal_zone_device structure and so must be done after its registration, but the initialization is also responsible for setting up calibration, which must be done before thermal_zone_device registration, which will call set_trips for the first time; if the calibration is not done in time, the interrupt values will be silently wrong! Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> Signed-off-by: Mateusz Majewski <m.majewski2@samsung.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20231201095625.301884-10-m.majewski2@samsung.com
This commit is contained in:
parent
af00d48833
commit
5314b15437
@ -158,10 +158,12 @@ enum soc_type {
|
||||
* in the positive-TC generator block
|
||||
* 0 < reference_voltage <= 31
|
||||
* @tzd: pointer to thermal_zone_device structure
|
||||
* @ntrip: number of supported trip points.
|
||||
* @enabled: current status of TMU device
|
||||
* @tmu_set_trip_temp: SoC specific method to set trip (rising threshold)
|
||||
* @tmu_set_trip_hyst: SoC specific to set hysteresis (falling threshold)
|
||||
* @tmu_set_low_temp: SoC specific method to set trip (falling threshold)
|
||||
* @tmu_set_high_temp: SoC specific method to set trip (rising threshold)
|
||||
* @tmu_set_crit_temp: SoC specific method to set critical temperature
|
||||
* @tmu_disable_low: SoC specific method to disable an interrupt (falling threshold)
|
||||
* @tmu_disable_high: SoC specific method to disable an interrupt (rising threshold)
|
||||
* @tmu_initialize: SoC specific TMU initialization method
|
||||
* @tmu_control: SoC specific TMU control method
|
||||
* @tmu_read: SoC specific TMU temperature read method
|
||||
@ -183,13 +185,13 @@ struct exynos_tmu_data {
|
||||
u8 gain;
|
||||
u8 reference_voltage;
|
||||
struct thermal_zone_device *tzd;
|
||||
unsigned int ntrip;
|
||||
bool enabled;
|
||||
|
||||
void (*tmu_set_trip_temp)(struct exynos_tmu_data *data, int trip,
|
||||
u8 temp);
|
||||
void (*tmu_set_trip_hyst)(struct exynos_tmu_data *data, int trip,
|
||||
u8 temp, u8 hyst);
|
||||
void (*tmu_set_low_temp)(struct exynos_tmu_data *data, u8 temp);
|
||||
void (*tmu_set_high_temp)(struct exynos_tmu_data *data, u8 temp);
|
||||
void (*tmu_set_crit_temp)(struct exynos_tmu_data *data, u8 temp);
|
||||
void (*tmu_disable_low)(struct exynos_tmu_data *data);
|
||||
void (*tmu_disable_high)(struct exynos_tmu_data *data);
|
||||
void (*tmu_initialize)(struct platform_device *pdev);
|
||||
void (*tmu_control)(struct platform_device *pdev, bool on);
|
||||
int (*tmu_read)(struct exynos_tmu_data *data);
|
||||
@ -279,49 +281,28 @@ static int exynos_thermal_zone_configure(struct platform_device *pdev)
|
||||
{
|
||||
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
|
||||
struct thermal_zone_device *tzd = data->tzd;
|
||||
int i, num_trips = thermal_zone_get_num_trips(tzd);
|
||||
int ret = 0, temp;
|
||||
int ret, temp;
|
||||
|
||||
ret = thermal_zone_get_crit_temp(tzd, &temp);
|
||||
if (ret) {
|
||||
/* FIXME: Remove this special case */
|
||||
if (data->soc == SOC_ARCH_EXYNOS5433)
|
||||
return 0;
|
||||
|
||||
if (ret && data->soc != SOC_ARCH_EXYNOS5433) { /* FIXME */
|
||||
dev_err(&pdev->dev,
|
||||
"No CRITICAL trip point defined in device tree!\n");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
||||
if (num_trips > data->ntrip) {
|
||||
dev_info(&pdev->dev,
|
||||
"More trip points than supported by this TMU.\n");
|
||||
dev_info(&pdev->dev,
|
||||
"%d trip points should be configured in polling mode.\n",
|
||||
num_trips - data->ntrip);
|
||||
}
|
||||
|
||||
clk_enable(data->clk);
|
||||
|
||||
num_trips = min_t(int, num_trips, data->ntrip);
|
||||
data->tmu_set_crit_temp(data, temp / MCELSIUS);
|
||||
|
||||
/* Write temperature code for rising and falling threshold */
|
||||
for (i = 0; i < num_trips; i++) {
|
||||
struct thermal_trip trip;
|
||||
|
||||
ret = thermal_zone_get_trip(tzd, i, &trip);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
data->tmu_set_trip_temp(data, i, trip.temperature / MCELSIUS);
|
||||
data->tmu_set_trip_hyst(data, i, trip.temperature / MCELSIUS,
|
||||
trip.hysteresis / MCELSIUS);
|
||||
}
|
||||
|
||||
err:
|
||||
clk_disable(data->clk);
|
||||
mutex_unlock(&data->lock);
|
||||
out:
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
|
||||
@ -354,17 +335,74 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
|
||||
mutex_unlock(&data->lock);
|
||||
}
|
||||
|
||||
static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data,
|
||||
int trip_id, u8 temp)
|
||||
static void exynos_tmu_update_bit(struct exynos_tmu_data *data, int reg_off,
|
||||
int bit_off, bool enable)
|
||||
{
|
||||
temp = temp_to_code(data, temp);
|
||||
writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip_id * 4);
|
||||
u32 interrupt_en;
|
||||
|
||||
interrupt_en = readl(data->base + reg_off);
|
||||
if (enable)
|
||||
interrupt_en |= BIT(bit_off);
|
||||
else
|
||||
interrupt_en &= ~BIT(bit_off);
|
||||
writel(interrupt_en, data->base + reg_off);
|
||||
}
|
||||
|
||||
/* failing thresholds are not supported on Exynos4210 */
|
||||
static void exynos4210_tmu_set_trip_hyst(struct exynos_tmu_data *data,
|
||||
int trip, u8 temp, u8 hyst)
|
||||
static void exynos_tmu_update_temp(struct exynos_tmu_data *data, int reg_off,
|
||||
int bit_off, u8 temp)
|
||||
{
|
||||
u16 tmu_temp_mask;
|
||||
u32 th;
|
||||
|
||||
tmu_temp_mask =
|
||||
(data->soc == SOC_ARCH_EXYNOS7) ? EXYNOS7_TMU_TEMP_MASK
|
||||
: EXYNOS_TMU_TEMP_MASK;
|
||||
|
||||
th = readl(data->base + reg_off);
|
||||
th &= ~(tmu_temp_mask << bit_off);
|
||||
th |= temp_to_code(data, temp) << bit_off;
|
||||
writel(th, data->base + reg_off);
|
||||
}
|
||||
|
||||
static void exynos4210_tmu_set_low_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
/*
|
||||
* Failing thresholds are not supported on Exynos 4210.
|
||||
* We use polling instead.
|
||||
*/
|
||||
}
|
||||
|
||||
static void exynos4210_tmu_set_high_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
temp = temp_to_code(data, temp);
|
||||
writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + 4);
|
||||
exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_RISE0_SHIFT + 4, true);
|
||||
}
|
||||
|
||||
static void exynos4210_tmu_disable_low(struct exynos_tmu_data *data)
|
||||
{
|
||||
/* Again, this is handled by polling. */
|
||||
}
|
||||
|
||||
static void exynos4210_tmu_disable_high(struct exynos_tmu_data *data)
|
||||
{
|
||||
exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_RISE0_SHIFT + 4, false);
|
||||
}
|
||||
|
||||
static void exynos4210_tmu_set_crit_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
/*
|
||||
* Hardware critical temperature handling is not supported on Exynos 4210.
|
||||
* We still set the critical temperature threshold, but this is only to
|
||||
* make sure it is handled as soon as possible. It is just a normal interrupt.
|
||||
*/
|
||||
|
||||
temp = temp_to_code(data, temp);
|
||||
writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + 12);
|
||||
exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_RISE0_SHIFT + 12, true);
|
||||
}
|
||||
|
||||
static void exynos4210_tmu_initialize(struct platform_device *pdev)
|
||||
@ -376,33 +414,31 @@ static void exynos4210_tmu_initialize(struct platform_device *pdev)
|
||||
writeb(0, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
|
||||
}
|
||||
|
||||
static void exynos4412_tmu_set_trip_temp(struct exynos_tmu_data *data,
|
||||
int trip, u8 temp)
|
||||
static void exynos4412_tmu_set_low_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
u32 th, con;
|
||||
|
||||
th = readl(data->base + EXYNOS_THD_TEMP_RISE);
|
||||
th &= ~(0xff << 8 * trip);
|
||||
th |= temp_to_code(data, temp) << 8 * trip;
|
||||
writel(th, data->base + EXYNOS_THD_TEMP_RISE);
|
||||
|
||||
if (trip == 3) {
|
||||
con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
|
||||
con |= BIT(EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
|
||||
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
|
||||
}
|
||||
exynos_tmu_update_temp(data, EXYNOS_THD_TEMP_FALL, 0, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_FALL0_SHIFT, true);
|
||||
}
|
||||
|
||||
static void exynos4412_tmu_set_trip_hyst(struct exynos_tmu_data *data,
|
||||
int trip, u8 temp, u8 hyst)
|
||||
static void exynos4412_tmu_set_high_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
u32 th;
|
||||
exynos_tmu_update_temp(data, EXYNOS_THD_TEMP_RISE, 8, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_RISE0_SHIFT + 4, true);
|
||||
}
|
||||
|
||||
th = readl(data->base + EXYNOS_THD_TEMP_FALL);
|
||||
th &= ~(0xff << 8 * trip);
|
||||
if (hyst)
|
||||
th |= temp_to_code(data, temp - hyst) << 8 * trip;
|
||||
writel(th, data->base + EXYNOS_THD_TEMP_FALL);
|
||||
static void exynos4412_tmu_disable_low(struct exynos_tmu_data *data)
|
||||
{
|
||||
exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_FALL0_SHIFT, false);
|
||||
}
|
||||
|
||||
static void exynos4412_tmu_set_crit_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
exynos_tmu_update_temp(data, EXYNOS_THD_TEMP_RISE, 24, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS_TMU_REG_CONTROL,
|
||||
EXYNOS_TMU_THERM_TRIP_EN_SHIFT, true);
|
||||
}
|
||||
|
||||
static void exynos4412_tmu_initialize(struct platform_device *pdev)
|
||||
@ -432,44 +468,39 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev)
|
||||
sanitize_temp_error(data, trim_info);
|
||||
}
|
||||
|
||||
static void exynos5433_tmu_set_trip_temp(struct exynos_tmu_data *data,
|
||||
int trip, u8 temp)
|
||||
static void exynos5433_tmu_set_low_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
unsigned int reg_off, j;
|
||||
u32 th;
|
||||
|
||||
if (trip > 3) {
|
||||
reg_off = EXYNOS5433_THD_TEMP_RISE7_4;
|
||||
j = trip - 4;
|
||||
} else {
|
||||
reg_off = EXYNOS5433_THD_TEMP_RISE3_0;
|
||||
j = trip;
|
||||
}
|
||||
|
||||
th = readl(data->base + reg_off);
|
||||
th &= ~(0xff << j * 8);
|
||||
th |= (temp_to_code(data, temp) << j * 8);
|
||||
writel(th, data->base + reg_off);
|
||||
exynos_tmu_update_temp(data, EXYNOS5433_THD_TEMP_FALL3_0, 0, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_FALL0_SHIFT, true);
|
||||
}
|
||||
|
||||
static void exynos5433_tmu_set_trip_hyst(struct exynos_tmu_data *data,
|
||||
int trip, u8 temp, u8 hyst)
|
||||
static void exynos5433_tmu_set_high_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
unsigned int reg_off, j;
|
||||
u32 th;
|
||||
exynos_tmu_update_temp(data, EXYNOS5433_THD_TEMP_RISE3_0, 8, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
|
||||
EXYNOS7_TMU_INTEN_RISE0_SHIFT + 1, true);
|
||||
}
|
||||
|
||||
if (trip > 3) {
|
||||
reg_off = EXYNOS5433_THD_TEMP_FALL7_4;
|
||||
j = trip - 4;
|
||||
} else {
|
||||
reg_off = EXYNOS5433_THD_TEMP_FALL3_0;
|
||||
j = trip;
|
||||
}
|
||||
static void exynos5433_tmu_disable_low(struct exynos_tmu_data *data)
|
||||
{
|
||||
exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_FALL0_SHIFT, false);
|
||||
}
|
||||
|
||||
th = readl(data->base + reg_off);
|
||||
th &= ~(0xff << j * 8);
|
||||
th |= (temp_to_code(data, temp - hyst) << j * 8);
|
||||
writel(th, data->base + reg_off);
|
||||
static void exynos5433_tmu_disable_high(struct exynos_tmu_data *data)
|
||||
{
|
||||
exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
|
||||
EXYNOS7_TMU_INTEN_RISE0_SHIFT + 1, false);
|
||||
}
|
||||
|
||||
static void exynos5433_tmu_set_crit_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
exynos_tmu_update_temp(data, EXYNOS5433_THD_TEMP_RISE7_4, 24, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS_TMU_REG_CONTROL,
|
||||
EXYNOS_TMU_THERM_TRIP_EN_SHIFT, true);
|
||||
exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
|
||||
EXYNOS7_TMU_INTEN_RISE0_SHIFT + 7, true);
|
||||
}
|
||||
|
||||
static void exynos5433_tmu_initialize(struct platform_device *pdev)
|
||||
@ -505,34 +536,41 @@ static void exynos5433_tmu_initialize(struct platform_device *pdev)
|
||||
cal_type ? 2 : 1);
|
||||
}
|
||||
|
||||
static void exynos7_tmu_set_trip_temp(struct exynos_tmu_data *data,
|
||||
int trip, u8 temp)
|
||||
static void exynos7_tmu_set_low_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
unsigned int reg_off, bit_off;
|
||||
u32 th;
|
||||
|
||||
reg_off = ((7 - trip) / 2) * 4;
|
||||
bit_off = ((8 - trip) % 2);
|
||||
|
||||
th = readl(data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
|
||||
th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
|
||||
th |= temp_to_code(data, temp) << (16 * bit_off);
|
||||
writel(th, data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
|
||||
exynos_tmu_update_temp(data, EXYNOS7_THD_TEMP_FALL7_6 + 12, 0, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_FALL0_SHIFT + 0, true);
|
||||
}
|
||||
|
||||
static void exynos7_tmu_set_trip_hyst(struct exynos_tmu_data *data,
|
||||
int trip, u8 temp, u8 hyst)
|
||||
static void exynos7_tmu_set_high_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
unsigned int reg_off, bit_off;
|
||||
u32 th;
|
||||
exynos_tmu_update_temp(data, EXYNOS7_THD_TEMP_RISE7_6 + 12, 16, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
|
||||
EXYNOS7_TMU_INTEN_RISE0_SHIFT + 1, true);
|
||||
}
|
||||
|
||||
reg_off = ((7 - trip) / 2) * 4;
|
||||
bit_off = ((8 - trip) % 2);
|
||||
static void exynos7_tmu_disable_low(struct exynos_tmu_data *data)
|
||||
{
|
||||
exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
|
||||
EXYNOS_TMU_INTEN_FALL0_SHIFT + 0, false);
|
||||
}
|
||||
|
||||
th = readl(data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
|
||||
th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
|
||||
th |= temp_to_code(data, temp - hyst) << (16 * bit_off);
|
||||
writel(th, data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
|
||||
static void exynos7_tmu_disable_high(struct exynos_tmu_data *data)
|
||||
{
|
||||
exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
|
||||
EXYNOS7_TMU_INTEN_RISE0_SHIFT + 1, false);
|
||||
}
|
||||
|
||||
static void exynos7_tmu_set_crit_temp(struct exynos_tmu_data *data, u8 temp)
|
||||
{
|
||||
/*
|
||||
* Like Exynos 4210, Exynos 7 does not seem to support critical temperature
|
||||
* handling in hardware. Again, we still set a separate interrupt for it.
|
||||
*/
|
||||
exynos_tmu_update_temp(data, EXYNOS7_THD_TEMP_RISE7_6 + 0, 16, temp);
|
||||
exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
|
||||
EXYNOS7_TMU_INTEN_RISE0_SHIFT + 7, true);
|
||||
}
|
||||
|
||||
static void exynos7_tmu_initialize(struct platform_device *pdev)
|
||||
@ -547,87 +585,44 @@ static void exynos7_tmu_initialize(struct platform_device *pdev)
|
||||
static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
|
||||
{
|
||||
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
|
||||
struct thermal_zone_device *tz = data->tzd;
|
||||
struct thermal_trip trip;
|
||||
unsigned int con, interrupt_en = 0, i;
|
||||
unsigned int con;
|
||||
|
||||
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
|
||||
|
||||
if (on) {
|
||||
for (i = 0; i < data->ntrip; i++) {
|
||||
if (thermal_zone_get_trip(tz, i, &trip))
|
||||
continue;
|
||||
|
||||
interrupt_en |=
|
||||
BIT(EXYNOS_TMU_INTEN_RISE0_SHIFT + i * 4);
|
||||
}
|
||||
|
||||
if (data->soc != SOC_ARCH_EXYNOS4210)
|
||||
interrupt_en |=
|
||||
interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
|
||||
|
||||
if (on)
|
||||
con |= BIT(EXYNOS_TMU_CORE_EN_SHIFT);
|
||||
} else {
|
||||
else
|
||||
con &= ~BIT(EXYNOS_TMU_CORE_EN_SHIFT);
|
||||
}
|
||||
|
||||
writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
|
||||
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
|
||||
}
|
||||
|
||||
static void exynos5433_tmu_control(struct platform_device *pdev, bool on)
|
||||
{
|
||||
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
|
||||
struct thermal_zone_device *tz = data->tzd;
|
||||
struct thermal_trip trip;
|
||||
unsigned int con, interrupt_en = 0, pd_det_en, i;
|
||||
unsigned int con, pd_det_en;
|
||||
|
||||
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
|
||||
|
||||
if (on) {
|
||||
for (i = 0; i < data->ntrip; i++) {
|
||||
if (thermal_zone_get_trip(tz, i, &trip))
|
||||
continue;
|
||||
|
||||
interrupt_en |=
|
||||
BIT(EXYNOS7_TMU_INTEN_RISE0_SHIFT + i);
|
||||
}
|
||||
|
||||
interrupt_en |=
|
||||
interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
|
||||
|
||||
if (on)
|
||||
con |= BIT(EXYNOS_TMU_CORE_EN_SHIFT);
|
||||
} else
|
||||
else
|
||||
con &= ~BIT(EXYNOS_TMU_CORE_EN_SHIFT);
|
||||
|
||||
pd_det_en = on ? EXYNOS5433_PD_DET_EN : 0;
|
||||
|
||||
writel(pd_det_en, data->base + EXYNOS5433_TMU_PD_DET_EN);
|
||||
writel(interrupt_en, data->base + EXYNOS5433_TMU_REG_INTEN);
|
||||
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
|
||||
}
|
||||
|
||||
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;
|
||||
struct thermal_trip trip;
|
||||
unsigned int con, interrupt_en = 0, i;
|
||||
unsigned int con;
|
||||
|
||||
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
|
||||
|
||||
if (on) {
|
||||
for (i = 0; i < data->ntrip; i++) {
|
||||
if (thermal_zone_get_trip(tz, i, &trip))
|
||||
continue;
|
||||
|
||||
interrupt_en |=
|
||||
BIT(EXYNOS7_TMU_INTEN_RISE0_SHIFT + i);
|
||||
}
|
||||
|
||||
interrupt_en |=
|
||||
interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
|
||||
|
||||
con |= BIT(EXYNOS_TMU_CORE_EN_SHIFT);
|
||||
con |= BIT(EXYNOS7_PD_DET_EN_SHIFT);
|
||||
} else {
|
||||
@ -635,7 +630,6 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
|
||||
con &= ~BIT(EXYNOS7_PD_DET_EN_SHIFT);
|
||||
}
|
||||
|
||||
writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN);
|
||||
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
|
||||
}
|
||||
|
||||
@ -873,13 +867,15 @@ static int exynos_map_dt_data(struct platform_device *pdev)
|
||||
|
||||
switch (data->soc) {
|
||||
case SOC_ARCH_EXYNOS4210:
|
||||
data->tmu_set_trip_temp = exynos4210_tmu_set_trip_temp;
|
||||
data->tmu_set_trip_hyst = exynos4210_tmu_set_trip_hyst;
|
||||
data->tmu_set_low_temp = exynos4210_tmu_set_low_temp;
|
||||
data->tmu_set_high_temp = exynos4210_tmu_set_high_temp;
|
||||
data->tmu_disable_low = exynos4210_tmu_disable_low;
|
||||
data->tmu_disable_high = exynos4210_tmu_disable_high;
|
||||
data->tmu_set_crit_temp = exynos4210_tmu_set_crit_temp;
|
||||
data->tmu_initialize = exynos4210_tmu_initialize;
|
||||
data->tmu_control = exynos4210_tmu_control;
|
||||
data->tmu_read = exynos4210_tmu_read;
|
||||
data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
|
||||
data->ntrip = 4;
|
||||
data->gain = 15;
|
||||
data->reference_voltage = 7;
|
||||
data->efuse_value = 55;
|
||||
@ -892,14 +888,16 @@ static int exynos_map_dt_data(struct platform_device *pdev)
|
||||
case SOC_ARCH_EXYNOS5260:
|
||||
case SOC_ARCH_EXYNOS5420:
|
||||
case SOC_ARCH_EXYNOS5420_TRIMINFO:
|
||||
data->tmu_set_trip_temp = exynos4412_tmu_set_trip_temp;
|
||||
data->tmu_set_trip_hyst = exynos4412_tmu_set_trip_hyst;
|
||||
data->tmu_set_low_temp = exynos4412_tmu_set_low_temp;
|
||||
data->tmu_set_high_temp = exynos4412_tmu_set_high_temp;
|
||||
data->tmu_disable_low = exynos4412_tmu_disable_low;
|
||||
data->tmu_disable_high = exynos4210_tmu_disable_high;
|
||||
data->tmu_set_crit_temp = exynos4412_tmu_set_crit_temp;
|
||||
data->tmu_initialize = exynos4412_tmu_initialize;
|
||||
data->tmu_control = exynos4210_tmu_control;
|
||||
data->tmu_read = exynos4412_tmu_read;
|
||||
data->tmu_set_emulation = exynos4412_tmu_set_emulation;
|
||||
data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
|
||||
data->ntrip = 4;
|
||||
data->gain = 8;
|
||||
data->reference_voltage = 16;
|
||||
data->efuse_value = 55;
|
||||
@ -911,14 +909,16 @@ static int exynos_map_dt_data(struct platform_device *pdev)
|
||||
data->max_efuse_value = 100;
|
||||
break;
|
||||
case SOC_ARCH_EXYNOS5433:
|
||||
data->tmu_set_trip_temp = exynos5433_tmu_set_trip_temp;
|
||||
data->tmu_set_trip_hyst = exynos5433_tmu_set_trip_hyst;
|
||||
data->tmu_set_low_temp = exynos5433_tmu_set_low_temp;
|
||||
data->tmu_set_high_temp = exynos5433_tmu_set_high_temp;
|
||||
data->tmu_disable_low = exynos5433_tmu_disable_low;
|
||||
data->tmu_disable_high = exynos5433_tmu_disable_high;
|
||||
data->tmu_set_crit_temp = exynos5433_tmu_set_crit_temp;
|
||||
data->tmu_initialize = exynos5433_tmu_initialize;
|
||||
data->tmu_control = exynos5433_tmu_control;
|
||||
data->tmu_read = exynos4412_tmu_read;
|
||||
data->tmu_set_emulation = exynos4412_tmu_set_emulation;
|
||||
data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
|
||||
data->ntrip = 8;
|
||||
data->gain = 8;
|
||||
if (res.start == EXYNOS5433_G3D_BASE)
|
||||
data->reference_voltage = 23;
|
||||
@ -929,14 +929,16 @@ static int exynos_map_dt_data(struct platform_device *pdev)
|
||||
data->max_efuse_value = 150;
|
||||
break;
|
||||
case SOC_ARCH_EXYNOS7:
|
||||
data->tmu_set_trip_temp = exynos7_tmu_set_trip_temp;
|
||||
data->tmu_set_trip_hyst = exynos7_tmu_set_trip_hyst;
|
||||
data->tmu_set_low_temp = exynos7_tmu_set_low_temp;
|
||||
data->tmu_set_high_temp = exynos7_tmu_set_high_temp;
|
||||
data->tmu_disable_low = exynos7_tmu_disable_low;
|
||||
data->tmu_disable_high = exynos7_tmu_disable_high;
|
||||
data->tmu_set_crit_temp = exynos7_tmu_set_crit_temp;
|
||||
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;
|
||||
data->ntrip = 8;
|
||||
data->gain = 9;
|
||||
data->reference_voltage = 17;
|
||||
data->efuse_value = 75;
|
||||
@ -972,9 +974,32 @@ static int exynos_map_dt_data(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
|
||||
{
|
||||
struct exynos_tmu_data *data = thermal_zone_device_priv(tz);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
clk_enable(data->clk);
|
||||
|
||||
if (low > INT_MIN)
|
||||
data->tmu_set_low_temp(data, low / MCELSIUS);
|
||||
else
|
||||
data->tmu_disable_low(data);
|
||||
if (high < INT_MAX)
|
||||
data->tmu_set_high_temp(data, high / MCELSIUS);
|
||||
else
|
||||
data->tmu_disable_high(data);
|
||||
|
||||
clk_disable(data->clk);
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct thermal_zone_device_ops exynos_sensor_ops = {
|
||||
.get_temp = exynos_get_temp,
|
||||
.set_emul_temp = exynos_tmu_set_emulation,
|
||||
.set_trips = exynos_set_trips,
|
||||
};
|
||||
|
||||
static int exynos_tmu_probe(struct platform_device *pdev)
|
||||
|
Loading…
x
Reference in New Issue
Block a user