mirror of
				https://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 11:35:51 +00:00 
			
		
		
		
	Introduce initial support for Airoha AN7583 SoC and add all the required patch for basic functionality of the SoC. Airoha AN7583 is based on Airoha EN7581 SoC with some major changes on the PHY handling and Serdes. It can be see as a lower spec of EN7581 with modern and simplified implementations. All the patch are sent upstream and are pending revision. Support for PCIe and USB will come later as soon as DT structure is accepted upstream. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
		
			
				
	
	
		
			278 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 5891a9e5fbdf9a305b5f81e2625455efb2a886f0 Mon Sep 17 00:00:00 2001
 | |
| From: Christian Marangi <ansuelsmth@gmail.com>
 | |
| Date: Fri, 23 May 2025 19:59:20 +0200
 | |
| Subject: [PATCH 5/5] thermal/drivers: airoha: Add support for AN7583
 | |
| 
 | |
| Add support for Airoha AN7583 Thermal driver. This apply similar logic
 | |
| on how to read the temperature but totally drop support for the
 | |
| PTP_THERMAL subsystem. PTP_THERMAL subsystem was a way to trigger trip
 | |
| point from hardware by configuring how to read the temperature
 | |
| internally.
 | |
| 
 | |
| This subsystem has been totally removed from Airoha AN7583 permitting
 | |
| only to read the temperature.
 | |
| 
 | |
| The SoC support up to 3 sensor but the original driver always read the
 | |
| BGA sensor hence it's currently implemented reading only this specific
 | |
| sensor. Reference and values for the other 2 sensor are defined for
 | |
| further implementation if confirmed working.
 | |
| 
 | |
| set_thermal_mux() is extended to also address muxing the sensor as
 | |
| AN7583 use a different way to read the temperature from 3 different
 | |
| diode. The EN7581 code is updated to account for these changes.
 | |
| 
 | |
| Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 | |
| ---
 | |
|  drivers/thermal/airoha_thermal.c | 158 ++++++++++++++++++++++++++++++-
 | |
|  1 file changed, 154 insertions(+), 4 deletions(-)
 | |
| 
 | |
| --- a/drivers/thermal/airoha_thermal.c
 | |
| +++ b/drivers/thermal/airoha_thermal.c
 | |
| @@ -18,6 +18,12 @@
 | |
|  #define EN7581_DOUT_TADC			0x2f8
 | |
|  #define   EN7581_DOUT_TADC_MASK			GENMASK(15, 0)
 | |
|  
 | |
| +#define AN7583_MUX_SENSOR			0x2a0
 | |
| +#define   AN7583_LOAD_ADJ			GENMASK(3, 2)
 | |
| +#define AN7583_MUX_TADC				0x2e4
 | |
| +#define   AN7583_MUX_TADC_MASK			GENMASK(3, 1)
 | |
| +#define AN7583_DOUT_TADC			0x2f0
 | |
| +
 | |
|  /* PTP_THERMAL regs */
 | |
|  #define EN7581_TEMPMONCTL0			0x800
 | |
|  #define   EN7581_SENSE3_EN			BIT(3)
 | |
| @@ -181,6 +187,11 @@
 | |
|  #define EN7581_SCU_THERMAL_PROTECT_KEY		0x12
 | |
|  #define EN7581_SCU_THERMAL_MUX_DIODE1		0x7
 | |
|  
 | |
| +#define AN7583_SCU_THERMAL_PROTECT_KEY		0x80
 | |
| +#define AN7583_NUM_SENSOR			3
 | |
| +
 | |
| +#define AIROHA_THERMAL_NO_MUX_SENSOR		-1
 | |
| +
 | |
|  /* Convert temp to raw value as read from ADC	((((temp / 100) - init) * slope) / 1000) + offset */
 | |
|  #define TEMP_TO_RAW(priv, temp)			((((((temp) / 100) - (priv)->init_temp) * \
 | |
|  						  (priv)->default_slope) / 1000) + \
 | |
| @@ -193,8 +204,39 @@
 | |
|  
 | |
|  #define AIROHA_MAX_SAMPLES			6
 | |
|  
 | |
| +/*
 | |
| + * AN7583 supports all these ADC mux but the original driver
 | |
| + * always checked temp with the AN7583_BGP_TEMP_SENSOR.
 | |
| + * Assume using the other sensor temperature is invalid and
 | |
| + * always read from AN7583_BGP_TEMP_SENSOR.
 | |
| + *
 | |
| + * On top of this it's defined that AN7583 supports 3
 | |
| + * sensor: AN7583_BGP_TEMP_SENSOR, AN7583_GBE_TEMP_SENSOR,
 | |
| + * AN7583_CPU_TEMP_SENSOR.
 | |
| + *
 | |
| + * Provide the ADC mux for reference.
 | |
| + */
 | |
| +enum an7583_thermal_adc_mux {
 | |
| +	AN7583_BGP_TEMP_SENSOR,
 | |
| +	AN7583_PAD_AVS,
 | |
| +	AN7583_CORE_POWER,
 | |
| +	AN7583_AVSDAC_OUT,
 | |
| +	AN7583_VCM,
 | |
| +	AN7583_GBE_TEMP_SENSOR,
 | |
| +	AN7583_CPU_TEMP_SENSOR,
 | |
| +
 | |
| +	AN7583_ADC_MUX_MAX,
 | |
| +};
 | |
| +
 | |
| +enum an7583_thermal_diode_mux {
 | |
| +	AN7583_D0_TADC,
 | |
| +	AN7583_ZERO_TADC,
 | |
| +	AN7583_D1_TADC,
 | |
| +};
 | |
| +
 | |
|  enum airoha_thermal_chip_scu_field {
 | |
|  	AIROHA_THERMAL_DOUT_TADC,
 | |
| +	AIROHA_THERMAL_MUX_SENSOR,
 | |
|  	AIROHA_THERMAL_MUX_TADC,
 | |
|  
 | |
|  	/* keep last */
 | |
| @@ -208,6 +250,7 @@ struct airoha_thermal_priv {
 | |
|  	struct resource scu_adc_res;
 | |
|  
 | |
|  	u32 pllrg_protect;
 | |
| +	int current_adc;
 | |
|  
 | |
|  	struct thermal_zone_device *tz;
 | |
|  	int init_temp;
 | |
| @@ -224,6 +267,24 @@ struct airoha_thermal_soc_data {
 | |
|  	int (*post_probe)(struct platform_device *pdev);
 | |
|  };
 | |
|  
 | |
| +static const unsigned int an7583_thermal_coeff[AN7583_ADC_MUX_MAX] = {
 | |
| +	[AN7583_BGP_TEMP_SENSOR] = 973,
 | |
| +	[AN7583_GBE_TEMP_SENSOR] = 995,
 | |
| +	[AN7583_CPU_TEMP_SENSOR] = 1035,
 | |
| +};
 | |
| +
 | |
| +static const unsigned int an7583_thermal_slope[AN7583_ADC_MUX_MAX] = {
 | |
| +	[AN7583_BGP_TEMP_SENSOR] = 7440,
 | |
| +	[AN7583_GBE_TEMP_SENSOR] = 7620,
 | |
| +	[AN7583_CPU_TEMP_SENSOR] = 8390,
 | |
| +};
 | |
| +
 | |
| +static const unsigned int an7583_thermal_offset[AN7583_ADC_MUX_MAX] = {
 | |
| +	[AN7583_BGP_TEMP_SENSOR] = 294,
 | |
| +	[AN7583_GBE_TEMP_SENSOR] = 298,
 | |
| +	[AN7583_CPU_TEMP_SENSOR] = 344,
 | |
| +};
 | |
| +
 | |
|  static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv)
 | |
|  {
 | |
|  	u32 val;
 | |
| @@ -234,7 +295,7 @@ static int airoha_get_thermal_ADC(struct
 | |
|  }
 | |
|  
 | |
|  static void airoha_set_thermal_mux(struct airoha_thermal_priv *priv,
 | |
| -				   int tdac_idx)
 | |
| +				   int tdac_idx, int sensor_idx)
 | |
|  {
 | |
|  	u32 pllrg;
 | |
|  
 | |
| @@ -245,9 +306,20 @@ static void airoha_set_thermal_mux(struc
 | |
|  	regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT,
 | |
|  		     priv->pllrg_protect);
 | |
|  
 | |
| +	/*
 | |
| +	 * Configure Thermal Sensor mux to sensor_idx.
 | |
| +	 * (if not supported, sensor_idx is AIROHA_THERMAL_NO_MUX_SENSOR)
 | |
| +	 */
 | |
| +	if (sensor_idx != AIROHA_THERMAL_NO_MUX_SENSOR)
 | |
| +		regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_SENSOR],
 | |
| +				   sensor_idx);
 | |
| +
 | |
|  	/* Configure Thermal ADC mux to tdac_idx */
 | |
| -	regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC],
 | |
| -			   tdac_idx);
 | |
| +	if (priv->current_adc != tdac_idx) {
 | |
| +		regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC],
 | |
| +				   tdac_idx);
 | |
| +		priv->current_adc = tdac_idx;
 | |
| +	}
 | |
|  
 | |
|  	/* Sleep 10 ms for Thermal ADC to enable */
 | |
|  	usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
 | |
| @@ -360,7 +432,8 @@ static void en7581_thermal_setup_adc_val
 | |
|  	u32 efuse_calib_info, cpu_sensor;
 | |
|  
 | |
|  	/* Setup Thermal Sensor to ADC mode and setup the mux to DIODE1 */
 | |
| -	airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1);
 | |
| +	airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1,
 | |
| +			       AIROHA_THERMAL_NO_MUX_SENSOR);
 | |
|  
 | |
|  	regmap_read(priv->map, EN7581_EFUSE_TEMP_OFFSET_REG, &efuse_calib_info);
 | |
|  	if (efuse_calib_info) {
 | |
| @@ -476,6 +549,10 @@ static int en7581_thermal_probe(struct p
 | |
|  	for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) {
 | |
|  		struct regmap_field *field;
 | |
|  
 | |
| +		/* Skip registering MUX_SENSOR field as not supported */
 | |
| +		if (i == AIROHA_THERMAL_MUX_SENSOR)
 | |
| +			continue;
 | |
| +
 | |
|  		field = devm_regmap_field_alloc(dev, priv->chip_scu,
 | |
|  						en7581_chip_scu_fields[i]);
 | |
|  		if (IS_ERR(field))
 | |
| @@ -516,6 +593,71 @@ static int en7581_thermal_post_probe(str
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| +static int an7583_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 | |
| +{
 | |
| +	struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
 | |
| +	int sensor_idx;
 | |
| +	int delta_diode, delta_gain;
 | |
| +	int coeff, slope, offset;
 | |
| +
 | |
| +	int diode_zero, diode_d0, diode_d1;
 | |
| +
 | |
| +	/* Always read sensor AN7583_BGP_TEMP_SENSOR */
 | |
| +	sensor_idx = AN7583_BGP_TEMP_SENSOR;
 | |
| +
 | |
| +	coeff = an7583_thermal_coeff[sensor_idx];
 | |
| +	slope = an7583_thermal_slope[sensor_idx];
 | |
| +	offset = an7583_thermal_offset[sensor_idx];
 | |
| +
 | |
| +	airoha_set_thermal_mux(priv, sensor_idx, AN7583_ZERO_TADC);
 | |
| +	diode_zero = airoha_get_thermal_ADC(priv);
 | |
| +	airoha_set_thermal_mux(priv, sensor_idx, AN7583_D0_TADC);
 | |
| +	diode_d0 = airoha_get_thermal_ADC(priv);
 | |
| +	airoha_set_thermal_mux(priv, sensor_idx, AN7583_D1_TADC);
 | |
| +	diode_d1 = airoha_get_thermal_ADC(priv);
 | |
| +
 | |
| +	delta_diode = diode_d1 - diode_d0;
 | |
| +	delta_gain = (delta_diode * coeff) / 100 + (diode_zero - diode_d1);
 | |
| +	*temp = (slope * delta_diode * 10) / delta_gain - offset * 10;
 | |
| +	*temp *= 100;
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static const struct thermal_zone_device_ops an7583_tz_ops = {
 | |
| +	.get_temp = an7583_thermal_get_temp,
 | |
| +};
 | |
| +
 | |
| +static const struct reg_field an7583_chip_scu_fields[AIROHA_THERMAL_FIELD_MAX] = {
 | |
| +	[AIROHA_THERMAL_DOUT_TADC] = REG_FIELD(AN7583_DOUT_TADC, 0, 31),
 | |
| +	[AIROHA_THERMAL_MUX_TADC] = REG_FIELD(AN7583_MUX_TADC, 1, 3),
 | |
| +	[AIROHA_THERMAL_MUX_SENSOR] = REG_FIELD(AN7583_MUX_SENSOR, 2, 3),
 | |
| +};
 | |
| +
 | |
| +static int an7583_thermal_probe(struct platform_device *pdev,
 | |
| +				struct airoha_thermal_priv *priv)
 | |
| +{
 | |
| +	struct device *dev = &pdev->dev;
 | |
| +	int i;
 | |
| +
 | |
| +	priv->chip_scu = device_node_to_regmap(dev->parent->of_node);
 | |
| +	if (IS_ERR(priv->map))
 | |
| +		return PTR_ERR(priv->map);
 | |
| +
 | |
| +	for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) {
 | |
| +		struct regmap_field *field;
 | |
| +
 | |
| +		field = devm_regmap_field_alloc(dev, priv->chip_scu,
 | |
| +						an7583_chip_scu_fields[i]);
 | |
| +		if (IS_ERR(field))
 | |
| +			return PTR_ERR(field);
 | |
| +
 | |
| +		priv->chip_scu_fields[i] = field;
 | |
| +	}
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
|  static int airoha_thermal_probe(struct platform_device *pdev)
 | |
|  {
 | |
|  	const struct airoha_thermal_soc_data *soc_data;
 | |
| @@ -530,6 +672,7 @@ static int airoha_thermal_probe(struct p
 | |
|  		return -ENOMEM;
 | |
|  
 | |
|  	priv->pllrg_protect = soc_data->pllrg_protect;
 | |
| +	priv->current_adc = -1;
 | |
|  
 | |
|  	if (!soc_data->probe)
 | |
|  		return -EINVAL;
 | |
| @@ -558,8 +701,15 @@ static const struct airoha_thermal_soc_d
 | |
|  	.post_probe = &en7581_thermal_post_probe,
 | |
|  };
 | |
|  
 | |
| +static const struct airoha_thermal_soc_data an7583_data = {
 | |
| +	.pllrg_protect = AN7583_SCU_THERMAL_PROTECT_KEY,
 | |
| +	.thdev_ops = &an7583_tz_ops,
 | |
| +	.probe = &an7583_thermal_probe,
 | |
| +};
 | |
| +
 | |
|  static const struct of_device_id airoha_thermal_match[] = {
 | |
|  	{ .compatible = "airoha,en7581-thermal", .data = &en7581_data },
 | |
| +	{ .compatible = "airoha,an7583-thermal", .data = &an7583_data },
 | |
|  	{},
 | |
|  };
 | |
|  MODULE_DEVICE_TABLE(of, airoha_thermal_match);
 |