Skip to content

Commit

Permalink
thermal: exynos: add exynos*_tmu_set_[trip,hyst]() helpers
Browse files Browse the repository at this point in the history
Add exynos*_tmu_set_[trip,hyst]() helpers and convert
all ->tmu_initialize implementations accordingly.

Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Eduardo Valentin <[email protected]>
  • Loading branch information
bzolnier authored and Eduardo Valentin committed May 6, 2018
1 parent fac36ba commit a503a10
Showing 1 changed file with 140 additions and 142 deletions.
282 changes: 140 additions & 142 deletions drivers/thermal/samsung/exynos_tmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,30 +305,6 @@ static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
EXYNOS_TMU_TEMP_MASK;
}

static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling)
{
struct thermal_zone_device *tz = data->tzd;
const struct thermal_trip * const trips =
of_thermal_get_trip_points(tz);
unsigned long temp;
int i, ntrips = min_t(int, of_thermal_get_ntrips(tz), data->ntrip);

for (i = 0; i < ntrips; i++) {
if (trips[i].type == THERMAL_TRIP_CRITICAL)
continue;

temp = trips[i].temperature / MCELSIUS;
if (falling)
temp -= (trips[i].hysteresis / MCELSIUS);
else
threshold &= ~(0xff << 8 * i);

threshold |= temp_to_code(data, temp) << 8 * i;
}

return threshold;
}

static int exynos_tmu_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
Expand Down Expand Up @@ -411,37 +387,79 @@ 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, u8 temp)
{
const struct thermal_trip * const trips =
of_thermal_get_trip_points(data->tzd);
u8 ref, th_code;

ref = trips[0].temperature / MCELSIUS;

if (trip == 0) {
th_code = temp_to_code(data, ref);
writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
}

temp -= ref;
writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip * 4);
}

static void exynos4210_tmu_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd;
const struct thermal_trip * const trips =
of_thermal_get_trip_points(tz);
int threshold_code, i;
unsigned long reference, temp;
unsigned long temp;
int i;

sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));

/* Write temperature code for threshold */
reference = trips[0].temperature / MCELSIUS;
threshold_code = temp_to_code(data, reference);
writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);

for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
temp = trips[i].temperature / MCELSIUS;
writeb(temp - reference, data->base +
EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
exynos4210_tmu_set_trip_temp(data, i, temp);
}
}

static void exynos4412_tmu_set_trip_temp(struct exynos_tmu_data *data,
int trip, 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 |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
}
}

static void exynos4412_tmu_set_trip_hyst(struct exynos_tmu_data *data,
int trip, u8 temp, u8 hyst)
{
u32 th;

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_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd;
const struct thermal_trip * const trips =
of_thermal_get_trip_points(data->tzd);
unsigned int trim_info, con, ctrl, rising_threshold;
int threshold_code, i;
unsigned long crit_temp = 0;
of_thermal_get_trip_points(tz);
unsigned long temp, hyst;
unsigned int trim_info, ctrl;
int i, ntrips = min_t(int, of_thermal_get_ntrips(tz), data->ntrip);

if (data->soc == SOC_ARCH_EXYNOS3250 ||
data->soc == SOC_ARCH_EXYNOS4412 ||
Expand All @@ -465,37 +483,61 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev)
sanitize_temp_error(data, trim_info);

/* Write temperature code for rising and falling threshold */
rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
rising_threshold = get_th_reg(data, rising_threshold, false);
writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);

/* if last threshold limit is also present */
for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++) {
if (trips[i].type == THERMAL_TRIP_CRITICAL) {
crit_temp = trips[i].temperature;
break;
}
for (i = 0; i < ntrips; i++) {
temp = trips[i].temperature / MCELSIUS;
exynos4412_tmu_set_trip_temp(data, i, temp);

hyst = trips[i].hysteresis / MCELSIUS;
exynos4412_tmu_set_trip_hyst(data, i, temp, hyst);
}
}

threshold_code = temp_to_code(data, crit_temp / MCELSIUS);
/* 1-4 level to be assigned in th0 reg */
rising_threshold &= ~(0xff << 8 * i);
rising_threshold |= threshold_code << 8 * i;
writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
static void exynos5433_tmu_set_trip_temp(struct exynos_tmu_data *data,
int trip, 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);
}

static void exynos5433_tmu_set_trip_hyst(struct exynos_tmu_data *data,
int trip, u8 temp, u8 hyst)
{
unsigned int reg_off, j;
u32 th;

if (trip > 3) {
reg_off = EXYNOS5433_THD_TEMP_FALL7_4;
j = trip - 4;
} else {
reg_off = EXYNOS5433_THD_TEMP_FALL3_0;
j = trip;
}

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_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd;
unsigned int trim_info;
unsigned int rising_threshold = 0, falling_threshold = 0;
int temp, temp_hist;
int threshold_code, i, sensor_id, cal_type;
int sensor_id, cal_type, i, temp, hyst;

trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
sanitize_temp_error(data, trim_info);
Expand Down Expand Up @@ -525,111 +567,67 @@ static void exynos5433_tmu_initialize(struct platform_device *pdev)

/* Write temperature code for rising and falling threshold */
for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
int rising_reg_offset, falling_reg_offset;
int j = 0;

switch (i) {
case 0:
case 1:
case 2:
case 3:
rising_reg_offset = EXYNOS5433_THD_TEMP_RISE3_0;
falling_reg_offset = EXYNOS5433_THD_TEMP_FALL3_0;
j = i;
break;
case 4:
case 5:
case 6:
case 7:
rising_reg_offset = EXYNOS5433_THD_TEMP_RISE7_4;
falling_reg_offset = EXYNOS5433_THD_TEMP_FALL7_4;
j = i - 4;
break;
default:
continue;
}

/* Write temperature code for rising threshold */
tz->ops->get_trip_temp(tz, i, &temp);
temp /= MCELSIUS;
threshold_code = temp_to_code(data, temp);

rising_threshold = readl(data->base + rising_reg_offset);
rising_threshold &= ~(0xff << j * 8);
rising_threshold |= (threshold_code << j * 8);
writel(rising_threshold, data->base + rising_reg_offset);
exynos5433_tmu_set_trip_temp(data, i, temp);

/* Write temperature code for falling threshold */
tz->ops->get_trip_hyst(tz, i, &temp_hist);
temp_hist = temp - (temp_hist / MCELSIUS);
threshold_code = temp_to_code(data, temp_hist);

falling_threshold = readl(data->base + falling_reg_offset);
falling_threshold &= ~(0xff << j * 8);
falling_threshold |= (threshold_code << j * 8);
writel(falling_threshold, data->base + falling_reg_offset);
tz->ops->get_trip_hyst(tz, i, &hyst);
hyst /= MCELSIUS;
exynos5433_tmu_set_trip_hyst(data, i, temp, hyst);
}
}

static void exynos7_tmu_set_trip_temp(struct exynos_tmu_data *data,
int trip, 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);
}

static void exynos7_tmu_set_trip_hyst(struct exynos_tmu_data *data,
int trip, u8 temp, u8 hyst)
{
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_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_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd;
unsigned int trim_info;
unsigned int rising_threshold = 0, falling_threshold = 0;
int threshold_code, i;
int temp, temp_hist;
unsigned int reg_off, bit_off;
int i, temp, hyst;

trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
sanitize_temp_error(data, trim_info);

/* 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;
exynos7_tmu_set_trip_temp(data, i, temp);

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);
tz->ops->get_trip_hyst(tz, i, &hyst);
hyst /= MCELSIUS;
exynos7_tmu_set_trip_hyst(data, i, temp, hyst);
}
}

Expand Down

0 comments on commit a503a10

Please sign in to comment.