1*3da2d29cSRaymond Sun /* 2*3da2d29cSRaymond Sun * Copyright (c) 2025, MediaTek Inc. All rights reserved. 3*3da2d29cSRaymond Sun * 4*3da2d29cSRaymond Sun * SPDX-License-Identifier: BSD-3-Clause 5*3da2d29cSRaymond Sun */ 6*3da2d29cSRaymond Sun 7*3da2d29cSRaymond Sun #include <errno.h> 8*3da2d29cSRaymond Sun #include <stdint.h> 9*3da2d29cSRaymond Sun #include <stdio.h> 10*3da2d29cSRaymond Sun #include <common/debug.h> 11*3da2d29cSRaymond Sun #include <drivers/delay_timer.h> 12*3da2d29cSRaymond Sun #include <lib/mmio.h> 13*3da2d29cSRaymond Sun #include <lib/mmio_poll.h> 14*3da2d29cSRaymond Sun #include <lib/utils_def.h> 15*3da2d29cSRaymond Sun 16*3da2d29cSRaymond Sun #include <lib/mtk_init/mtk_init.h> 17*3da2d29cSRaymond Sun #include <lpm/mt_lp_api.h> 18*3da2d29cSRaymond Sun #include <mtk_mmap_pool.h> 19*3da2d29cSRaymond Sun #include <soc_temp_lvts_interface.h> 20*3da2d29cSRaymond Sun #include <thermal_lvts.h> 21*3da2d29cSRaymond Sun 22*3da2d29cSRaymond Sun static void lvts_write_device_nodelay(struct lvts_data *lvts_data, 23*3da2d29cSRaymond Sun uint32_t data, unsigned int tc_id) 24*3da2d29cSRaymond Sun { 25*3da2d29cSRaymond Sun uintptr_t base; 26*3da2d29cSRaymond Sun 27*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, tc_id); 28*3da2d29cSRaymond Sun 29*3da2d29cSRaymond Sun mmio_write_32(LVTS_CONFIG_0 + base, data); 30*3da2d29cSRaymond Sun } 31*3da2d29cSRaymond Sun 32*3da2d29cSRaymond Sun static void lvts_write_data_check(struct lvts_data *lvts_data, uint32_t data, 33*3da2d29cSRaymond Sun unsigned int tc_id) 34*3da2d29cSRaymond Sun { 35*3da2d29cSRaymond Sun uintptr_t base; 36*3da2d29cSRaymond Sun int ret; 37*3da2d29cSRaymond Sun uint32_t temp; 38*3da2d29cSRaymond Sun 39*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, tc_id); 40*3da2d29cSRaymond Sun 41*3da2d29cSRaymond Sun ret = mmio_read_32_poll_timeout( 42*3da2d29cSRaymond Sun LVTS_CONFIG_0 + base, 43*3da2d29cSRaymond Sun temp, 44*3da2d29cSRaymond Sun ((temp & (0x1 << DEVICE_ACCESS_START_BIT)) == 0), 45*3da2d29cSRaymond Sun 20); 46*3da2d29cSRaymond Sun 47*3da2d29cSRaymond Sun if (ret) 48*3da2d29cSRaymond Sun INFO("write device err: LVTS %d didn't ready, data 0x%x\n", 49*3da2d29cSRaymond Sun tc_id, data); 50*3da2d29cSRaymond Sun } 51*3da2d29cSRaymond Sun 52*3da2d29cSRaymond Sun void lvts_write_all_device(struct lvts_data *lvts_data, uint32_t data) 53*3da2d29cSRaymond Sun { 54*3da2d29cSRaymond Sun unsigned int tc_id; 55*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 56*3da2d29cSRaymond Sun 57*3da2d29cSRaymond Sun for (tc_id = 0; tc_id < lvts_data->num_tc; tc_id++) { 58*3da2d29cSRaymond Sun if (tc[tc_id].ctrl_on_off == CTRL_OFF) 59*3da2d29cSRaymond Sun continue; 60*3da2d29cSRaymond Sun 61*3da2d29cSRaymond Sun lvts_write_device_nodelay(lvts_data, data, tc_id); 62*3da2d29cSRaymond Sun } 63*3da2d29cSRaymond Sun dmbsy(); 64*3da2d29cSRaymond Sun for (tc_id = 0; tc_id < lvts_data->num_tc; tc_id++) { 65*3da2d29cSRaymond Sun if (tc[tc_id].ctrl_on_off == CTRL_OFF) 66*3da2d29cSRaymond Sun continue; 67*3da2d29cSRaymond Sun 68*3da2d29cSRaymond Sun lvts_write_data_check(lvts_data, data, tc_id); 69*3da2d29cSRaymond Sun } 70*3da2d29cSRaymond Sun } 71*3da2d29cSRaymond Sun 72*3da2d29cSRaymond Sun void lvts_write_device(struct lvts_data *lvts_data, uint32_t data, 73*3da2d29cSRaymond Sun unsigned int tc_id) 74*3da2d29cSRaymond Sun { 75*3da2d29cSRaymond Sun uintptr_t base; 76*3da2d29cSRaymond Sun int ret; 77*3da2d29cSRaymond Sun uint32_t temp; 78*3da2d29cSRaymond Sun 79*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, tc_id); 80*3da2d29cSRaymond Sun 81*3da2d29cSRaymond Sun mmio_write_32(LVTS_CONFIG_0 + base, data); 82*3da2d29cSRaymond Sun dmbsy(); 83*3da2d29cSRaymond Sun 84*3da2d29cSRaymond Sun udelay(5); 85*3da2d29cSRaymond Sun 86*3da2d29cSRaymond Sun ret = mmio_read_32_poll_timeout( 87*3da2d29cSRaymond Sun LVTS_CONFIG_0 + base, 88*3da2d29cSRaymond Sun temp, 89*3da2d29cSRaymond Sun ((temp & (0x1 << DEVICE_ACCESS_START_BIT)) == 0), 90*3da2d29cSRaymond Sun 20); 91*3da2d29cSRaymond Sun 92*3da2d29cSRaymond Sun if (ret) 93*3da2d29cSRaymond Sun INFO("write device err: LVTS %d didn't ready, data 0x%x\n", 94*3da2d29cSRaymond Sun tc_id, data); 95*3da2d29cSRaymond Sun 96*3da2d29cSRaymond Sun } 97*3da2d29cSRaymond Sun 98*3da2d29cSRaymond Sun uint32_t lvts_read_device(struct lvts_data *lvts_data, uint32_t reg_idx, 99*3da2d29cSRaymond Sun unsigned int tc_id) 100*3da2d29cSRaymond Sun { 101*3da2d29cSRaymond Sun uintptr_t base; 102*3da2d29cSRaymond Sun uint32_t temp, data; 103*3da2d29cSRaymond Sun uint32_t write_val = READ_DEVICE_REG(reg_idx); 104*3da2d29cSRaymond Sun int ret; 105*3da2d29cSRaymond Sun 106*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, tc_id); 107*3da2d29cSRaymond Sun mmio_write_32(LVTS_CONFIG_0 + base, write_val); 108*3da2d29cSRaymond Sun dmbsy(); 109*3da2d29cSRaymond Sun 110*3da2d29cSRaymond Sun ret = mmio_read_32_poll_timeout( 111*3da2d29cSRaymond Sun LVTS_CONFIG_0 + base, 112*3da2d29cSRaymond Sun temp, 113*3da2d29cSRaymond Sun ((temp & (0x1 << DEVICE_ACCESS_START_BIT)) == 0), 114*3da2d29cSRaymond Sun 20); 115*3da2d29cSRaymond Sun if (ret) 116*3da2d29cSRaymond Sun INFO("read device err: LVTS %d didn't ready, reg_idx 0x%x\n", 117*3da2d29cSRaymond Sun tc_id, reg_idx); 118*3da2d29cSRaymond Sun 119*3da2d29cSRaymond Sun data = mmio_read_32(LVTSRDATA0_0 + base); 120*3da2d29cSRaymond Sun 121*3da2d29cSRaymond Sun return data; 122*3da2d29cSRaymond Sun } 123*3da2d29cSRaymond Sun 124*3da2d29cSRaymond Sun #define THERMAL_SENSOR_IDLE_MASK (BIT(10) | BIT(7) | BIT(0)) 125*3da2d29cSRaymond Sun #define HALF_WORD (16) 126*3da2d29cSRaymond Sun #define IDLE_CHECK_BIT1_MASK (BIT(10)) 127*3da2d29cSRaymond Sun #define IDLE_CHECK_BIT2_MASK (BIT(7)) 128*3da2d29cSRaymond Sun #define IDLE_CHECK_BIT3_MASK (BIT(0)) 129*3da2d29cSRaymond Sun #define SHIFT_8 (8) 130*3da2d29cSRaymond Sun #define SHIFT_6 (6) 131*3da2d29cSRaymond Sun 132*3da2d29cSRaymond Sun static uint32_t lvts_thermal_check_all_sensing_point_idle( 133*3da2d29cSRaymond Sun struct lvts_data *lvts_data) 134*3da2d29cSRaymond Sun { 135*3da2d29cSRaymond Sun unsigned int i; 136*3da2d29cSRaymond Sun uintptr_t base; 137*3da2d29cSRaymond Sun uint32_t temp, mask, error_code; 138*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 139*3da2d29cSRaymond Sun 140*3da2d29cSRaymond Sun mask = THERMAL_SENSOR_IDLE_MASK; 141*3da2d29cSRaymond Sun 142*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 143*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 144*3da2d29cSRaymond Sun continue; 145*3da2d29cSRaymond Sun 146*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 147*3da2d29cSRaymond Sun temp = mmio_read_32(base + LVTSMSRCTL1_0); 148*3da2d29cSRaymond Sun /* Check if bit10=bit7=bit0=0 */ 149*3da2d29cSRaymond Sun if ((temp & mask) != 0) { 150*3da2d29cSRaymond Sun error_code = (i << HALF_WORD) 151*3da2d29cSRaymond Sun + ((temp & IDLE_CHECK_BIT1_MASK) >> SHIFT_8) 152*3da2d29cSRaymond Sun + ((temp & IDLE_CHECK_BIT2_MASK) >> SHIFT_6) 153*3da2d29cSRaymond Sun + (temp & IDLE_CHECK_BIT3_MASK); 154*3da2d29cSRaymond Sun 155*3da2d29cSRaymond Sun return error_code; 156*3da2d29cSRaymond Sun } 157*3da2d29cSRaymond Sun } 158*3da2d29cSRaymond Sun 159*3da2d29cSRaymond Sun return 0; 160*3da2d29cSRaymond Sun } 161*3da2d29cSRaymond Sun 162*3da2d29cSRaymond Sun #define ITERATION_TIME (80) 163*3da2d29cSRaymond Sun #define DELAY_US (2) 164*3da2d29cSRaymond Sun 165*3da2d29cSRaymond Sun static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data) 166*3da2d29cSRaymond Sun { 167*3da2d29cSRaymond Sun unsigned int i; 168*3da2d29cSRaymond Sun uintptr_t base; 169*3da2d29cSRaymond Sun uint32_t temp, mask, error_code; 170*3da2d29cSRaymond Sun int cnt = 0; 171*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 172*3da2d29cSRaymond Sun static unsigned int no_idle_count; 173*3da2d29cSRaymond Sun 174*3da2d29cSRaymond Sun mask = THERMAL_SENSOR_IDLE_MASK; 175*3da2d29cSRaymond Sun 176*3da2d29cSRaymond Sun while (cnt < ITERATION_TIME) { 177*3da2d29cSRaymond Sun temp = lvts_thermal_check_all_sensing_point_idle(lvts_data); 178*3da2d29cSRaymond Sun if (temp == 0) 179*3da2d29cSRaymond Sun goto TAIL; 180*3da2d29cSRaymond Sun 181*3da2d29cSRaymond Sun udelay(DELAY_US); 182*3da2d29cSRaymond Sun cnt++; 183*3da2d29cSRaymond Sun 184*3da2d29cSRaymond Sun } 185*3da2d29cSRaymond Sun no_idle_count++; 186*3da2d29cSRaymond Sun mmio_write_32(THERMAL_CSRAM_BASE + NO_IDLE_COUNT_ADDR_OFFSET, 187*3da2d29cSRaymond Sun no_idle_count); 188*3da2d29cSRaymond Sun 189*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 190*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 191*3da2d29cSRaymond Sun continue; 192*3da2d29cSRaymond Sun 193*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 194*3da2d29cSRaymond Sun temp = mmio_read_32(LVTSMSRCTL1_0 + base); 195*3da2d29cSRaymond Sun /* 196*3da2d29cSRaymond Sun * Error code 197*3da2d29cSRaymond Sun * 000: IDLE 198*3da2d29cSRaymond Sun * 001: Write transaction 199*3da2d29cSRaymond Sun * 010: Waiting for read after Write 200*3da2d29cSRaymond Sun * 011: Disable Continue fetching on Device 201*3da2d29cSRaymond Sun * 100: Read transaction 202*3da2d29cSRaymond Sun * 101: Set Device special Register for Voltage threshold 203*3da2d29cSRaymond Sun * 111: Set TSMCU number for Fetch 204*3da2d29cSRaymond Sun */ 205*3da2d29cSRaymond Sun if ((temp & mask) != 0) { 206*3da2d29cSRaymond Sun error_code = ((temp & IDLE_CHECK_BIT1_MASK) >> SHIFT_8) 207*3da2d29cSRaymond Sun + ((temp & IDLE_CHECK_BIT2_MASK) >> SHIFT_6) 208*3da2d29cSRaymond Sun + (temp & IDLE_CHECK_BIT3_MASK); 209*3da2d29cSRaymond Sun 210*3da2d29cSRaymond Sun INFO("LVTS %d sensing points not idle, error_code %d\n", 211*3da2d29cSRaymond Sun i, error_code); 212*3da2d29cSRaymond Sun } 213*3da2d29cSRaymond Sun } 214*3da2d29cSRaymond Sun TAIL: 215*3da2d29cSRaymond Sun return; 216*3da2d29cSRaymond Sun } 217*3da2d29cSRaymond Sun 218*3da2d29cSRaymond Sun static void disable_all_sensing_points(struct lvts_data *lvts_data) 219*3da2d29cSRaymond Sun { 220*3da2d29cSRaymond Sun unsigned int i; 221*3da2d29cSRaymond Sun uintptr_t base; 222*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 223*3da2d29cSRaymond Sun 224*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 225*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 226*3da2d29cSRaymond Sun continue; 227*3da2d29cSRaymond Sun 228*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 229*3da2d29cSRaymond Sun mmio_write_32(LVTSMONCTL0_0 + base, DISABLE_SENSING_POINT); 230*3da2d29cSRaymond Sun } 231*3da2d29cSRaymond Sun dmbsy(); 232*3da2d29cSRaymond Sun } 233*3da2d29cSRaymond Sun 234*3da2d29cSRaymond Sun static void enable_all_sensing_points(struct lvts_data *lvts_data) 235*3da2d29cSRaymond Sun { 236*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 237*3da2d29cSRaymond Sun unsigned int i, j, num; 238*3da2d29cSRaymond Sun uintptr_t base; 239*3da2d29cSRaymond Sun uint32_t flag; 240*3da2d29cSRaymond Sun 241*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 242*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 243*3da2d29cSRaymond Sun continue; 244*3da2d29cSRaymond Sun 245*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 246*3da2d29cSRaymond Sun num = tc[i].num_sensor; 247*3da2d29cSRaymond Sun 248*3da2d29cSRaymond Sun if (num > ALL_SENSING_POINTS) { 249*3da2d29cSRaymond Sun INFO("%s, LVTS%d, illegal number of sensors: %d\n", 250*3da2d29cSRaymond Sun __func__, i, tc[i].num_sensor); 251*3da2d29cSRaymond Sun continue; 252*3da2d29cSRaymond Sun } 253*3da2d29cSRaymond Sun 254*3da2d29cSRaymond Sun flag = LVTS_SINGLE_SENSE; 255*3da2d29cSRaymond Sun for (j = 0; j < tc[i].num_sensor; j++) { 256*3da2d29cSRaymond Sun if (tc[i].sensor_on_off[j] != SEN_ON) 257*3da2d29cSRaymond Sun continue; 258*3da2d29cSRaymond Sun 259*3da2d29cSRaymond Sun flag = flag | (0x1 << j); 260*3da2d29cSRaymond Sun } 261*3da2d29cSRaymond Sun mmio_write_32(LVTSMONCTL0_0 + base, flag); 262*3da2d29cSRaymond Sun } 263*3da2d29cSRaymond Sun dmbsy(); 264*3da2d29cSRaymond Sun } 265*3da2d29cSRaymond Sun 266*3da2d29cSRaymond Sun void set_polling_speed(struct lvts_data *lvts_data, unsigned int tc_id) 267*3da2d29cSRaymond Sun { 268*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 269*3da2d29cSRaymond Sun uint32_t lvts_mon_ctrl1, lvts_mon_ctrl2; 270*3da2d29cSRaymond Sun uintptr_t base; 271*3da2d29cSRaymond Sun 272*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, tc_id); 273*3da2d29cSRaymond Sun 274*3da2d29cSRaymond Sun lvts_mon_ctrl1 = (((tc[tc_id].tc_speed.group_interval_delay 275*3da2d29cSRaymond Sun << 20) & GENMASK(29, 20)) | 276*3da2d29cSRaymond Sun (tc[tc_id].tc_speed.period_unit & 277*3da2d29cSRaymond Sun GENMASK(9, 0))); 278*3da2d29cSRaymond Sun lvts_mon_ctrl2 = (((tc[tc_id].tc_speed.filter_interval_delay 279*3da2d29cSRaymond Sun << 16) & GENMASK(25, 16)) | 280*3da2d29cSRaymond Sun (tc[tc_id].tc_speed.sensor_interval_delay 281*3da2d29cSRaymond Sun & GENMASK(9, 0))); 282*3da2d29cSRaymond Sun /* 283*3da2d29cSRaymond Sun * Clock source of LVTS thermal controller is 26MHz. 284*3da2d29cSRaymond Sun * Period unit is a base for all interval delays 285*3da2d29cSRaymond Sun * All interval delays must multiply it to convert a setting to time. 286*3da2d29cSRaymond Sun * Filter interval delay is a delay between two samples of the same 287*3da2d29cSRaymond Sun * sensor 288*3da2d29cSRaymond Sun * Sensor interval delay is a delay between two samples of differnet 289*3da2d29cSRaymond Sun * sensors 290*3da2d29cSRaymond Sun * Group interval delay is a delay between different rounds. 291*3da2d29cSRaymond Sun * For example: 292*3da2d29cSRaymond Sun * If Period unit = C, filter delay = 1, sensor delay = 2, group 293*3da2d29cSRaymond Sun * delay = 1, 294*3da2d29cSRaymond Sun * and two sensors, TS1 and TS2, are in a LVTS thermal controller 295*3da2d29cSRaymond Sun * and then 296*3da2d29cSRaymond Sun * Period unit = C * 1/26M * 256 = 12 * 38.46ns * 256 = 118.149us 297*3da2d29cSRaymond Sun * Filter interval delay = 1 * Period unit = 118.149us 298*3da2d29cSRaymond Sun * Sensor interval delay = 2 * Period unit = 236.298us 299*3da2d29cSRaymond Sun * Group interval delay = 1 * Period unit = 118.149us 300*3da2d29cSRaymond Sun * 301*3da2d29cSRaymond Sun * TS1 TS1 ... TS1 TS2 TS2 ... TS2 TS1... 302*3da2d29cSRaymond Sun * <--> Filter interval delay 303*3da2d29cSRaymond Sun * <--> Sensor interval delay 304*3da2d29cSRaymond Sun * <--> Group interval delay 305*3da2d29cSRaymond Sun */ 306*3da2d29cSRaymond Sun mmio_write_32(LVTSMONCTL1_0 + base, lvts_mon_ctrl1); 307*3da2d29cSRaymond Sun mmio_write_32(LVTSMONCTL2_0 + base, lvts_mon_ctrl2); 308*3da2d29cSRaymond Sun dmbsy(); 309*3da2d29cSRaymond Sun } 310*3da2d29cSRaymond Sun 311*3da2d29cSRaymond Sun void set_hw_filter(struct lvts_data *lvts_data, unsigned int tc_id) 312*3da2d29cSRaymond Sun { 313*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 314*3da2d29cSRaymond Sun uint32_t option; 315*3da2d29cSRaymond Sun uintptr_t base; 316*3da2d29cSRaymond Sun 317*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, tc_id); 318*3da2d29cSRaymond Sun option = tc[tc_id].hw_filter & 0x7; 319*3da2d29cSRaymond Sun /* hw filter 320*3da2d29cSRaymond Sun * 000: Get one sample 321*3da2d29cSRaymond Sun * 001: Get 2 samples and average them 322*3da2d29cSRaymond Sun * 010: Get 4 samples, drop max&min and average the rest of 2 samples 323*3da2d29cSRaymond Sun * 011: Get 6 samples, drop max&min and average the rest of 4 samples 324*3da2d29cSRaymond Sun * 100: Get 10 samples, drop max&min and average the rest of 8 samples 325*3da2d29cSRaymond Sun * 101: Get 18 samples, drop max&min and average the rest of 16 samples 326*3da2d29cSRaymond Sun */ 327*3da2d29cSRaymond Sun option = (option << 9) | (option << 6) | (option << 3) | option; 328*3da2d29cSRaymond Sun 329*3da2d29cSRaymond Sun mmio_write_32(LVTSMSRCTL0_0 + base, option); 330*3da2d29cSRaymond Sun dmbsy(); 331*3da2d29cSRaymond Sun } 332*3da2d29cSRaymond Sun 333*3da2d29cSRaymond Sun unsigned int get_dominator_index(struct lvts_data *lvts_data, 334*3da2d29cSRaymond Sun unsigned int tc_id) 335*3da2d29cSRaymond Sun { 336*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 337*3da2d29cSRaymond Sun unsigned int d_index; 338*3da2d29cSRaymond Sun 339*3da2d29cSRaymond Sun if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) { 340*3da2d29cSRaymond Sun d_index = ALL_SENSING_POINTS; 341*3da2d29cSRaymond Sun } else if (tc[tc_id].dominator_sensing_point < 342*3da2d29cSRaymond Sun tc[tc_id].num_sensor){ 343*3da2d29cSRaymond Sun d_index = tc[tc_id].dominator_sensing_point; 344*3da2d29cSRaymond Sun } else { 345*3da2d29cSRaymond Sun INFO("Error: LVTS%d, dominator_sensing_point= %d over %d\n", 346*3da2d29cSRaymond Sun tc_id, tc[tc_id].dominator_sensing_point, 347*3da2d29cSRaymond Sun tc[tc_id].num_sensor); 348*3da2d29cSRaymond Sun 349*3da2d29cSRaymond Sun INFO("Use the sensing point 0 as the dominated sensor\n"); 350*3da2d29cSRaymond Sun d_index = SENSING_POINT0; 351*3da2d29cSRaymond Sun } 352*3da2d29cSRaymond Sun 353*3da2d29cSRaymond Sun return d_index; 354*3da2d29cSRaymond Sun } 355*3da2d29cSRaymond Sun 356*3da2d29cSRaymond Sun static void set_all_tc_hw_reboot(struct lvts_data *lvts_data) 357*3da2d29cSRaymond Sun { 358*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 359*3da2d29cSRaymond Sun int trip_point; 360*3da2d29cSRaymond Sun unsigned int i; 361*3da2d29cSRaymond Sun 362*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 363*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 364*3da2d29cSRaymond Sun continue; 365*3da2d29cSRaymond Sun 366*3da2d29cSRaymond Sun trip_point = tc[i].hw_reboot_trip_point; 367*3da2d29cSRaymond Sun 368*3da2d29cSRaymond Sun if (tc[i].num_sensor == 0) 369*3da2d29cSRaymond Sun continue; 370*3da2d29cSRaymond Sun 371*3da2d29cSRaymond Sun if (trip_point == DISABLE_THERMAL_HW_REBOOT) { 372*3da2d29cSRaymond Sun disable_hw_reboot_interrupt(lvts_data, i); 373*3da2d29cSRaymond Sun continue; 374*3da2d29cSRaymond Sun } 375*3da2d29cSRaymond Sun 376*3da2d29cSRaymond Sun set_tc_hw_reboot_threshold(lvts_data, trip_point, i); 377*3da2d29cSRaymond Sun } 378*3da2d29cSRaymond Sun } 379*3da2d29cSRaymond Sun 380*3da2d29cSRaymond Sun static bool lvts_lk_init_check(struct lvts_data *lvts_data) 381*3da2d29cSRaymond Sun { 382*3da2d29cSRaymond Sun unsigned int i; 383*3da2d29cSRaymond Sun uint32_t data; 384*3da2d29cSRaymond Sun uintptr_t base; 385*3da2d29cSRaymond Sun bool ret = false; 386*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 387*3da2d29cSRaymond Sun 388*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 389*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 390*3da2d29cSRaymond Sun continue; 391*3da2d29cSRaymond Sun 392*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 393*3da2d29cSRaymond Sun 394*3da2d29cSRaymond Sun /* Check LVTS device ID */ 395*3da2d29cSRaymond Sun data = mmio_read_32(LVTSSPARE0_0 + base) & GENMASK(11, 0); 396*3da2d29cSRaymond Sun 397*3da2d29cSRaymond Sun if (data == LK_LVTS_MAGIC) { 398*3da2d29cSRaymond Sun mmio_write_32(LVTSSPARE0_0 + base, 0x0); 399*3da2d29cSRaymond Sun ret = true; 400*3da2d29cSRaymond Sun } else { 401*3da2d29cSRaymond Sun ret = false; 402*3da2d29cSRaymond Sun break; 403*3da2d29cSRaymond Sun } 404*3da2d29cSRaymond Sun } 405*3da2d29cSRaymond Sun dmbsy(); 406*3da2d29cSRaymond Sun return ret; 407*3da2d29cSRaymond Sun } 408*3da2d29cSRaymond Sun 409*3da2d29cSRaymond Sun static void lvts_set_init_flag_tfa(struct lvts_data *lvts_data) 410*3da2d29cSRaymond Sun { 411*3da2d29cSRaymond Sun uintptr_t base; 412*3da2d29cSRaymond Sun unsigned int i; 413*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 414*3da2d29cSRaymond Sun 415*3da2d29cSRaymond Sun /* write TFA init done flag to inform kernel */ 416*3da2d29cSRaymond Sun 417*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 418*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 419*3da2d29cSRaymond Sun continue; 420*3da2d29cSRaymond Sun 421*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 422*3da2d29cSRaymond Sun 423*3da2d29cSRaymond Sun /* enable sensing point 0 */ 424*3da2d29cSRaymond Sun mmio_write_32(base + LVTSSPARE0_0, TFA_LVTS_MAGIC); 425*3da2d29cSRaymond Sun } 426*3da2d29cSRaymond Sun dmbsy(); 427*3da2d29cSRaymond Sun } 428*3da2d29cSRaymond Sun 429*3da2d29cSRaymond Sun static void lvts_clear_init_flag_tfa(struct lvts_data *lvts_data) 430*3da2d29cSRaymond Sun { 431*3da2d29cSRaymond Sun uintptr_t base; 432*3da2d29cSRaymond Sun unsigned int i; 433*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 434*3da2d29cSRaymond Sun 435*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 436*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 437*3da2d29cSRaymond Sun continue; 438*3da2d29cSRaymond Sun 439*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 440*3da2d29cSRaymond Sun mmio_write_32(LVTSSPARE0_0 + base, 0); 441*3da2d29cSRaymond Sun } 442*3da2d29cSRaymond Sun dmbsy(); 443*3da2d29cSRaymond Sun } 444*3da2d29cSRaymond Sun 445*3da2d29cSRaymond Sun static int read_calibration_data(struct lvts_data *lvts_data) 446*3da2d29cSRaymond Sun { 447*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 448*3da2d29cSRaymond Sun unsigned int i, j, s_index; 449*3da2d29cSRaymond Sun uintptr_t base; 450*3da2d29cSRaymond Sun struct sensor_cal_data *cal_data = &lvts_data->cal_data; 451*3da2d29cSRaymond Sun 452*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 453*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 454*3da2d29cSRaymond Sun continue; 455*3da2d29cSRaymond Sun 456*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 457*3da2d29cSRaymond Sun 458*3da2d29cSRaymond Sun for (j = 0; j < tc[i].num_sensor; j++) { 459*3da2d29cSRaymond Sun if (tc[i].sensor_on_off[j] != SEN_ON) 460*3da2d29cSRaymond Sun continue; 461*3da2d29cSRaymond Sun 462*3da2d29cSRaymond Sun s_index = tc[i].sensor_map[j]; 463*3da2d29cSRaymond Sun 464*3da2d29cSRaymond Sun cal_data->efuse_data[s_index] = 465*3da2d29cSRaymond Sun mmio_read_32(LVTSEDATA00_0 + base + 0x4 * j); 466*3da2d29cSRaymond Sun 467*3da2d29cSRaymond Sun } 468*3da2d29cSRaymond Sun } 469*3da2d29cSRaymond Sun 470*3da2d29cSRaymond Sun return 0; 471*3da2d29cSRaymond Sun } 472*3da2d29cSRaymond Sun 473*3da2d29cSRaymond Sun static int lvts_init(struct lvts_data *lvts_data) 474*3da2d29cSRaymond Sun { 475*3da2d29cSRaymond Sun struct platform_ops *ops = &lvts_data->ops; 476*3da2d29cSRaymond Sun int ret; 477*3da2d29cSRaymond Sun bool lk_init = false; 478*3da2d29cSRaymond Sun 479*3da2d29cSRaymond Sun mmio_write_32(THERMAL_CSRAM_BASE + CLOSE_FOOTPRINT_ADDR_OFFSET, 0x0); 480*3da2d29cSRaymond Sun 481*3da2d29cSRaymond Sun thermal_clock_open(); 482*3da2d29cSRaymond Sun 483*3da2d29cSRaymond Sun lk_init = lvts_lk_init_check(lvts_data); 484*3da2d29cSRaymond Sun if (lk_init == true) { 485*3da2d29cSRaymond Sun ret = read_calibration_data(lvts_data); 486*3da2d29cSRaymond Sun 487*3da2d29cSRaymond Sun lvts_set_init_flag_tfa(lvts_data); 488*3da2d29cSRaymond Sun lvts_data->init_done = true; 489*3da2d29cSRaymond Sun INFO("%s, LK init LVTS\n", __func__); 490*3da2d29cSRaymond Sun 491*3da2d29cSRaymond Sun return ret; 492*3da2d29cSRaymond Sun } 493*3da2d29cSRaymond Sun 494*3da2d29cSRaymond Sun ops->lvts_reset(lvts_data); 495*3da2d29cSRaymond Sun 496*3da2d29cSRaymond Sun if (ops->device_identification) 497*3da2d29cSRaymond Sun ops->device_identification(lvts_data); 498*3da2d29cSRaymond Sun 499*3da2d29cSRaymond Sun if (ops->device_enable_and_init) 500*3da2d29cSRaymond Sun ops->device_enable_and_init(lvts_data); 501*3da2d29cSRaymond Sun 502*3da2d29cSRaymond Sun if (IS_ENABLE(lvts_data, (int)FEATURE_DEVICE_AUTO_RCK)) { 503*3da2d29cSRaymond Sun if (ops->device_enable_auto_rck) 504*3da2d29cSRaymond Sun ops->device_enable_auto_rck(lvts_data); 505*3da2d29cSRaymond Sun } else { 506*3da2d29cSRaymond Sun if (ops->device_read_count_rc_n) 507*3da2d29cSRaymond Sun ops->device_read_count_rc_n(lvts_data); 508*3da2d29cSRaymond Sun } 509*3da2d29cSRaymond Sun 510*3da2d29cSRaymond Sun if (ops->set_cal_data) 511*3da2d29cSRaymond Sun ops->set_cal_data(lvts_data); 512*3da2d29cSRaymond Sun 513*3da2d29cSRaymond Sun disable_all_sensing_points(lvts_data); 514*3da2d29cSRaymond Sun wait_all_tc_sensing_point_idle(lvts_data); 515*3da2d29cSRaymond Sun if (ops->init_controller) 516*3da2d29cSRaymond Sun ops->init_controller(lvts_data); 517*3da2d29cSRaymond Sun 518*3da2d29cSRaymond Sun set_all_tc_hw_reboot(lvts_data); 519*3da2d29cSRaymond Sun enable_all_sensing_points(lvts_data); 520*3da2d29cSRaymond Sun lvts_set_init_flag_tfa(lvts_data); 521*3da2d29cSRaymond Sun lvts_data->init_done = true; 522*3da2d29cSRaymond Sun 523*3da2d29cSRaymond Sun return 0; 524*3da2d29cSRaymond Sun } 525*3da2d29cSRaymond Sun 526*3da2d29cSRaymond Sun static int update_lvts_data_from_efuse(struct lvts_data *lvts_data) 527*3da2d29cSRaymond Sun { 528*3da2d29cSRaymond Sun struct platform_ops *ops = &lvts_data->ops; 529*3da2d29cSRaymond Sun 530*3da2d29cSRaymond Sun if (ops->get_calibration_data) 531*3da2d29cSRaymond Sun ops->get_calibration_data(lvts_data); 532*3da2d29cSRaymond Sun 533*3da2d29cSRaymond Sun if (ops->efuse_to_cal_data) 534*3da2d29cSRaymond Sun ops->efuse_to_cal_data(lvts_data); 535*3da2d29cSRaymond Sun 536*3da2d29cSRaymond Sun if (ops->check_cal_data) 537*3da2d29cSRaymond Sun ops->check_cal_data(lvts_data); 538*3da2d29cSRaymond Sun 539*3da2d29cSRaymond Sun if (ops->update_coef_data) 540*3da2d29cSRaymond Sun ops->update_coef_data(lvts_data); 541*3da2d29cSRaymond Sun 542*3da2d29cSRaymond Sun return 0; 543*3da2d29cSRaymond Sun } 544*3da2d29cSRaymond Sun 545*3da2d29cSRaymond Sun static void lvts_close(struct lvts_data *lvts_data) 546*3da2d29cSRaymond Sun { 547*3da2d29cSRaymond Sun mmio_write_32(THERMAL_CSRAM_BASE + INIT_FOOTPRINT_ADDR_OFFSET, 0x0); 548*3da2d29cSRaymond Sun 549*3da2d29cSRaymond Sun lvts_data->ops.lvts_reset(lvts_data); 550*3da2d29cSRaymond Sun 551*3da2d29cSRaymond Sun lvts_clear_init_flag_tfa(lvts_data); 552*3da2d29cSRaymond Sun 553*3da2d29cSRaymond Sun thermal_clock_close(); 554*3da2d29cSRaymond Sun } 555*3da2d29cSRaymond Sun 556*3da2d29cSRaymond Sun void set_calibration_data_v1(struct lvts_data *lvts_data) 557*3da2d29cSRaymond Sun { 558*3da2d29cSRaymond Sun struct tc_settings *tc = lvts_data->tc; 559*3da2d29cSRaymond Sun struct sensor_cal_data *cal_data = &lvts_data->cal_data; 560*3da2d29cSRaymond Sun unsigned int i, j, s_index; 561*3da2d29cSRaymond Sun uint32_t e_data; 562*3da2d29cSRaymond Sun uintptr_t base; 563*3da2d29cSRaymond Sun 564*3da2d29cSRaymond Sun for (i = 0; i < lvts_data->num_tc; i++) { 565*3da2d29cSRaymond Sun if (tc[i].ctrl_on_off == CTRL_OFF) 566*3da2d29cSRaymond Sun continue; 567*3da2d29cSRaymond Sun 568*3da2d29cSRaymond Sun base = GET_BASE_ADDR(lvts_data, i); 569*3da2d29cSRaymond Sun 570*3da2d29cSRaymond Sun for (j = 0; j < tc[i].num_sensor; j++) { 571*3da2d29cSRaymond Sun if (tc[i].sensor_on_off[j] != SEN_ON) 572*3da2d29cSRaymond Sun continue; 573*3da2d29cSRaymond Sun 574*3da2d29cSRaymond Sun s_index = tc[i].sensor_map[j]; 575*3da2d29cSRaymond Sun if (IS_ENABLE(lvts_data, (int)FEATURE_DEVICE_AUTO_RCK)) 576*3da2d29cSRaymond Sun e_data = cal_data->count_r[s_index]; 577*3da2d29cSRaymond Sun else 578*3da2d29cSRaymond Sun e_data = cal_data->efuse_data[s_index]; 579*3da2d29cSRaymond Sun 580*3da2d29cSRaymond Sun mmio_write_32(LVTSEDATA00_0 + base + 0x4 * j, e_data); 581*3da2d29cSRaymond Sun } 582*3da2d29cSRaymond Sun } 583*3da2d29cSRaymond Sun dmbsy(); 584*3da2d29cSRaymond Sun } 585*3da2d29cSRaymond Sun 586*3da2d29cSRaymond Sun static int lvts_thermal_init(void) 587*3da2d29cSRaymond Sun { 588*3da2d29cSRaymond Sun struct lvts_data *lvts_data; 589*3da2d29cSRaymond Sun int ret; 590*3da2d29cSRaymond Sun 591*3da2d29cSRaymond Sun lvts_data = &lvts_data_instance; 592*3da2d29cSRaymond Sun 593*3da2d29cSRaymond Sun ret = update_lvts_data_from_efuse(lvts_data); 594*3da2d29cSRaymond Sun if (ret) 595*3da2d29cSRaymond Sun return ret; 596*3da2d29cSRaymond Sun 597*3da2d29cSRaymond Sun ret = lvts_init(lvts_data); 598*3da2d29cSRaymond Sun if (ret) 599*3da2d29cSRaymond Sun return ret; 600*3da2d29cSRaymond Sun 601*3da2d29cSRaymond Sun return 0; 602*3da2d29cSRaymond Sun } 603*3da2d29cSRaymond Sun 604*3da2d29cSRaymond Sun /* suspend/resume */ 605*3da2d29cSRaymond Sun static int lvts_suspend_callback(struct lvts_data *lvts_data) 606*3da2d29cSRaymond Sun { 607*3da2d29cSRaymond Sun lvts_close(lvts_data); 608*3da2d29cSRaymond Sun 609*3da2d29cSRaymond Sun return 0; 610*3da2d29cSRaymond Sun } 611*3da2d29cSRaymond Sun 612*3da2d29cSRaymond Sun static int lvts_resume_callback(struct lvts_data *lvts_data) 613*3da2d29cSRaymond Sun { 614*3da2d29cSRaymond Sun return lvts_init(lvts_data); 615*3da2d29cSRaymond Sun } 616*3da2d29cSRaymond Sun 617*3da2d29cSRaymond Sun static void *lvts_pm_suspend_event_handler(const void *arg) 618*3da2d29cSRaymond Sun { 619*3da2d29cSRaymond Sun struct mt_lp_publish_event const *event = 620*3da2d29cSRaymond Sun (struct mt_lp_publish_event const *) arg; 621*3da2d29cSRaymond Sun struct lvts_data *lvts_data = &lvts_data_instance; 622*3da2d29cSRaymond Sun int ret; 623*3da2d29cSRaymond Sun 624*3da2d29cSRaymond Sun if (!event) { 625*3da2d29cSRaymond Sun return NULL; 626*3da2d29cSRaymond Sun } 627*3da2d29cSRaymond Sun 628*3da2d29cSRaymond Sun if (event->id == MT_LPM_PUBEVENTS_SYS_POWER_OFF) { 629*3da2d29cSRaymond Sun ret = lvts_suspend_callback(lvts_data); 630*3da2d29cSRaymond Sun if (ret) { 631*3da2d29cSRaymond Sun INFO("%s, %d, ret = %d\n", __func__, __LINE__, ret); 632*3da2d29cSRaymond Sun } 633*3da2d29cSRaymond Sun return (void *)arg; 634*3da2d29cSRaymond Sun 635*3da2d29cSRaymond Sun } else if (event->id == MT_LPM_PUBEVENTS_SYS_POWER_ON) { 636*3da2d29cSRaymond Sun ret = lvts_resume_callback(lvts_data); 637*3da2d29cSRaymond Sun if (ret) { 638*3da2d29cSRaymond Sun INFO("%s, %d, ret = %d\n", __func__, __LINE__, ret); 639*3da2d29cSRaymond Sun } 640*3da2d29cSRaymond Sun return (void *)arg; 641*3da2d29cSRaymond Sun } 642*3da2d29cSRaymond Sun 643*3da2d29cSRaymond Sun return NULL; 644*3da2d29cSRaymond Sun } 645*3da2d29cSRaymond Sun MT_LP_SUBSCRIBE_SUSPEND(lvts_pm_suspend_event_handler); 646*3da2d29cSRaymond Sun 647*3da2d29cSRaymond Sun MTK_PLAT_RUNTIME_INIT(lvts_thermal_init); 648