linux/drivers/thermal/mediatek/lvts_thermal.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2023 MediaTek Inc.
 * Author: Balsam CHIHI <[email protected]>
 */

#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/nvmem-consumer.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/thermal.h>
#include <dt-bindings/thermal/mediatek,lvts-thermal.h>

#include "../thermal_hwmon.h"

#define LVTS_MONCTL0(__base)
#define LVTS_MONCTL1(__base)
#define LVTS_MONCTL2(__base)
#define LVTS_MONINT(__base)
#define LVTS_MONINTSTS(__base)
#define LVTS_MONIDET0(__base)
#define LVTS_MONIDET1(__base)
#define LVTS_MONIDET2(__base)
#define LVTS_MONIDET3(__base)
#define LVTS_H2NTHRE(__base)
#define LVTS_HTHRE(__base)
#define LVTS_OFFSETH(__base)
#define LVTS_OFFSETL(__base)
#define LVTS_MSRCTL0(__base)
#define LVTS_MSRCTL1(__base)
#define LVTS_TSSEL(__base)
#define LVTS_CALSCALE(__base)
#define LVTS_ID(__base)
#define LVTS_CONFIG(__base)
#define LVTS_EDATA00(__base)
#define LVTS_EDATA01(__base)
#define LVTS_EDATA02(__base)
#define LVTS_EDATA03(__base)
#define LVTS_MSR0(__base)
#define LVTS_MSR1(__base)
#define LVTS_MSR2(__base)
#define LVTS_MSR3(__base)
#define LVTS_IMMD0(__base)
#define LVTS_IMMD1(__base)
#define LVTS_IMMD2(__base)
#define LVTS_IMMD3(__base)
#define LVTS_PROTCTL(__base)
#define LVTS_PROTTA(__base)
#define LVTS_PROTTB(__base)
#define LVTS_PROTTC(__base)
#define LVTS_CLKEN(__base)

#define LVTS_PERIOD_UNIT
#define LVTS_GROUP_INTERVAL
#define LVTS_FILTER_INTERVAL
#define LVTS_SENSOR_INTERVAL
#define LVTS_HW_FILTER
#define LVTS_TSSEL_CONF
#define LVTS_CALSCALE_CONF
#define LVTS_MONINT_CONF

#define LVTS_MONINT_OFFSET_SENSOR0
#define LVTS_MONINT_OFFSET_SENSOR1
#define LVTS_MONINT_OFFSET_SENSOR2
#define LVTS_MONINT_OFFSET_SENSOR3

#define LVTS_INT_SENSOR0
#define LVTS_INT_SENSOR1
#define LVTS_INT_SENSOR2
#define LVTS_INT_SENSOR3

#define LVTS_SENSOR_MAX
#define LVTS_GOLDEN_TEMP_MAX
#define LVTS_GOLDEN_TEMP_DEFAULT
#define LVTS_COEFF_A_MT8195
#define LVTS_COEFF_B_MT8195
#define LVTS_COEFF_A_MT7988
#define LVTS_COEFF_B_MT7988

#define LVTS_MSR_IMMEDIATE_MODE
#define LVTS_MSR_FILTERED_MODE

#define LVTS_MSR_READ_TIMEOUT_US
#define LVTS_MSR_READ_WAIT_US

#define LVTS_HW_TSHUT_TEMP

#define LVTS_MINIMUM_THRESHOLD

static int golden_temp =;
static int golden_temp_offset;

struct lvts_sensor_data {};

struct lvts_ctrl_data {};

#define VALID_SENSOR_MAP(s0, s1, s2, s3)

#define lvts_for_each_valid_sensor(i, lvts_ctrl)

struct lvts_data {};

struct lvts_sensor {};

struct lvts_ctrl {};

struct lvts_domain {};

#ifdef CONFIG_MTK_LVTS_THERMAL_DEBUGFS

#define LVTS_DEBUG_FS_REGS(__reg)

static const struct debugfs_reg32 lvts_regs[] =;

static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td)
{}

static void lvts_debugfs_exit(struct lvts_domain *lvts_td)
{}

#else

static inline int lvts_debugfs_init(struct device *dev,
				    struct lvts_domain *lvts_td)
{
	return 0;
}

static void lvts_debugfs_exit(struct lvts_domain *lvts_td) { }

#endif

static int lvts_raw_to_temp(u32 raw_temp, int temp_factor)
{}

static u32 lvts_temp_to_raw(int temperature, int temp_factor)
{}

static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
{}

static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl)
{}

static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high)
{}

static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
{}

static irqreturn_t lvts_ctrl_irq_handler(struct lvts_ctrl *lvts_ctrl)
{}

/*
 * Temperature interrupt handler. Even if the driver supports more
 * interrupt modes, we use the interrupt when the temperature crosses
 * the hot threshold the way up and the way down (modulo the
 * hysteresis).
 *
 * Each thermal domain has a couple of interrupts, one for hardware
 * reset and another one for all the thermal events happening on the
 * different sensors.
 *
 * The interrupt is configured for thermal events when crossing the
 * hot temperature limit. At each interrupt, we check in every
 * controller if there is an interrupt pending.
 */
static irqreturn_t lvts_irq_handler(int irq, void *data)
{}

static struct thermal_zone_device_ops lvts_ops =;

static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
					const struct lvts_ctrl_data *lvts_ctrl_data)
{}

/*
 * The efuse blob values follows the sensor enumeration per thermal
 * controller. The decoding of the stream is as follow:
 *
 * MT8192 :
 * Stream index map for MCU Domain mt8192 :
 *
 * <-----mcu-tc#0-----> <-----sensor#0----->        <-----sensor#1----->
 *  0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0A | 0x0B
 *
 * <-----sensor#2----->        <-----sensor#3----->
 *  0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 | 0x13
 *
 * <-----sensor#4----->        <-----sensor#5----->        <-----sensor#6----->        <-----sensor#7----->
 *  0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 | 0x22 | 0x23
 *
 * Stream index map for AP Domain mt8192 :
 *
 * <-----sensor#0----->        <-----sensor#1----->
 *  0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A | 0x2B
 *
 * <-----sensor#2----->        <-----sensor#3----->
 *  0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33
 *
 * <-----sensor#4----->        <-----sensor#5----->
 *  0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B
 *
 * <-----sensor#6----->        <-----sensor#7----->        <-----sensor#8----->
 *  0x3C | 0x3D | 0x3E | 0x3F | 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47
 *
 * MT8195 :
 * Stream index map for MCU Domain mt8195 :
 *
 * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1----->
 *  0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09
 *
 * <-----mcu-tc#1-----> <-----sensor#2-----> <-----sensor#3----->
 *  0x0A | 0x0B | 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12
 *
 * <-----mcu-tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7----->
 *  0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21
 *
 * Stream index map for AP Domain mt8195 :
 *
 * <-----ap--tc#0-----> <-----sensor#0-----> <-----sensor#1----->
 *  0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A
 *
 * <-----ap--tc#1-----> <-----sensor#2-----> <-----sensor#3----->
 *  0x2B | 0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33
 *
 * <-----ap--tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6----->
 *  0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B | 0x3C | 0x3D | 0x3E | 0x3F
 *
 * <-----ap--tc#3-----> <-----sensor#7-----> <-----sensor#8----->
 *  0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48
 *
 * Note: In some cases, values don't strictly follow a little endian ordering.
 * The data description gives byte offsets constituting each calibration value
 * for each sensor.
 */
static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
					const struct lvts_ctrl_data *lvts_ctrl_data,
					u8 *efuse_calibration,
					size_t calib_len)
{}

/*
 * The efuse bytes stream can be split into different chunk of
 * nvmems. This function reads and concatenate those into a single
 * buffer so it can be read sequentially when initializing the
 * calibration data.
 */
static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td,
					const struct lvts_data *lvts_data)
{}

static int lvts_golden_temp_init(struct device *dev, u8 *calib,
				 const struct lvts_data *lvts_data)
{}

static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td,
					const struct lvts_data *lvts_data)
{}

/*
 * At this point the configuration register is the only place in the
 * driver where we write multiple values. Per hardware constraint,
 * each write in the configuration register must be separated by a
 * delay of 2 us.
 */
static void lvts_write_config(struct lvts_ctrl *lvts_ctrl, u32 *cmds, int nr_cmds)
{}

static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl)
{}

static int lvts_domain_reset(struct device *dev, struct reset_control *reset)
{}

/*
 * Enable or disable the clocks of a specified thermal controller
 */
static int lvts_ctrl_set_enable(struct lvts_ctrl *lvts_ctrl, int enable)
{}

static int lvts_ctrl_connect(struct device *dev, struct lvts_ctrl *lvts_ctrl)
{}

static int lvts_ctrl_initialize(struct device *dev, struct lvts_ctrl *lvts_ctrl)
{}

static int lvts_ctrl_calibrate(struct device *dev, struct lvts_ctrl *lvts_ctrl)
{}

static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl)
{}

static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
{}

static int lvts_domain_init(struct device *dev, struct lvts_domain *lvts_td,
					const struct lvts_data *lvts_data)
{}

static int lvts_probe(struct platform_device *pdev)
{}

static void lvts_remove(struct platform_device *pdev)
{}

static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] =;

static int lvts_suspend(struct device *dev)
{}

static int lvts_resume(struct device *dev)
{}

/*
 * The MT8186 calibration data is stored as packed 3-byte little-endian
 * values using a weird layout that makes sense only when viewed as a 32-bit
 * hexadecimal word dump. Let's suppose SxBy where x = sensor number and
 * y = byte number where the LSB is y=0. We then have:
 *
 *   [S0B2-S0B1-S0B0-S1B2] [S1B1-S1B0-S2B2-S2B1] [S2B0-S3B2-S3B1-S3B0]
 *
 * However, when considering a byte stream, those appear as follows:
 *
 *   [S1B2] [S0B0[ [S0B1] [S0B2] [S2B1] [S2B2] [S1B0] [S1B1] [S3B0] [S3B1] [S3B2] [S2B0]
 *
 * Hence the rather confusing offsets provided below.
 */
static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] =;

static const struct lvts_ctrl_data mt8188_lvts_mcu_data_ctrl[] =;

static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] =;

static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] =;

static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] =;

static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] =;

static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] =;

static const struct lvts_data mt7988_lvts_ap_data =;

static const struct lvts_data mt8186_lvts_data =;

static const struct lvts_data mt8188_lvts_mcu_data =;

static const struct lvts_data mt8188_lvts_ap_data =;

static const struct lvts_data mt8192_lvts_mcu_data =;

static const struct lvts_data mt8192_lvts_ap_data =;

static const struct lvts_data mt8195_lvts_mcu_data =;

static const struct lvts_data mt8195_lvts_ap_data =;

static const struct of_device_id lvts_of_match[] =;
MODULE_DEVICE_TABLE(of, lvts_of_match);

static const struct dev_pm_ops lvts_pm_ops =;

static struct platform_driver lvts_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();