Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 1/3] drivers/perf: hisi: Consolidate uncore PMU cpuhp states
From: Robin Murphy @ 2026-07-27 12:41 UTC (permalink / raw)
  To: Yushan Wang, will, mark.rutland, linux-arm-kernel, linux-kernel
  Cc: u.kleine-koenig, linuxarm, liuyonglong, prime.zeng, wangzhou1,
	wuyifan50
In-Reply-To: <20260724025238.3411328-2-wangyushan12@huawei.com>

On 24/07/2026 3:52 am, Yushan Wang wrote:
> Every HiSilicon uncore PMU driver allocates its own static cpuhp state
> even though they all register identical online/offline callbacks. This
> wastes slots in the cpuhp state enum and needlessly fragments the
> hotplug state space.
> 
> Move the cpuhp state setup into the shared hisi_uncore_pmu framework:
> register a single dynamic state (CPUHP_AP_ONLINE_DYN) at framework
> module init and export it for all HiSilicon uncore PMU drivers to use.
> Drop the now-unused static CPUHP_AP_PERF_ARM_HISI_* entries from
> include/linux/cpuhotplug.h.
> 
> The L3C PMU driver keeps a private dynamic state because it has its own
> hotplug callbacks for migrating multiple per-CPU interrupt affinities,
> but switches from its former static slot to CPUHP_AP_ONLINE_DYN for
> consistency.
> 
> No intended functional changes.
> 
> Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
> ---
>   drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c  | 34 +++---------------
>   drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 34 +++---------------
>   drivers/perf/hisilicon/hisi_uncore_hha_pmu.c  | 34 +++---------------
>   drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c  | 21 +++++------
>   drivers/perf/hisilicon/hisi_uncore_mn_pmu.c   | 35 ++----------------
>   drivers/perf/hisilicon/hisi_uncore_noc_pmu.c  | 35 ++----------------
>   drivers/perf/hisilicon/hisi_uncore_pa_pmu.c   | 34 +++---------------
>   drivers/perf/hisilicon/hisi_uncore_pmu.c      | 25 +++++++++++++
>   drivers/perf/hisilicon/hisi_uncore_pmu.h      |  2 ++
>   drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 34 +++---------------
>   drivers/perf/hisilicon/hisi_uncore_uc_pmu.c   | 36 ++-----------------
>   include/linux/cpuhotplug.h                    |  6 ----
>   12 files changed, 67 insertions(+), 263 deletions(-)

Neat! Seems like a pretty nice win already, plus it only makes a 
conversion easier if my generic hotplug idea takes off :)

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

> diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
> index b879b81adfdd..83967725c51c 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
> @@ -295,7 +295,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
>   
>   	/* Power Management should be disabled before using CPA PMU. */
>   	hisi_cpa_pmu_disable_pm(cpa_pmu);
> -	ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
> +	ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
>   				       &cpa_pmu->node);
>   	if (ret) {
>   		dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> @@ -307,7 +307,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
>   	if (ret) {
>   		dev_err(cpa_pmu->dev, "PMU register failed\n");
>   		cpuhp_state_remove_instance_nocalls(
> -			CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, &cpa_pmu->node);
> +			hisi_uncore_pmu_cpuhp_state, &cpa_pmu->node);
>   		hisi_cpa_pmu_enable_pm(cpa_pmu);
>   		return ret;
>   	}
> @@ -321,7 +321,7 @@ static void hisi_cpa_pmu_remove(struct platform_device *pdev)
>   	struct hisi_pmu *cpa_pmu = platform_get_drvdata(pdev);
>   
>   	perf_pmu_unregister(&cpa_pmu->pmu);
> -	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
> +	cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
>   					    &cpa_pmu->node);
>   	hisi_cpa_pmu_enable_pm(cpa_pmu);
>   }
> @@ -336,33 +336,7 @@ static struct platform_driver hisi_cpa_pmu_driver = {
>   	.remove = hisi_cpa_pmu_remove,
>   };
>   
> -static int __init hisi_cpa_pmu_module_init(void)
> -{
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
> -				      "AP_PERF_ARM_HISI_CPA_ONLINE",
> -				      hisi_uncore_pmu_online_cpu,
> -				      hisi_uncore_pmu_offline_cpu);
> -	if (ret) {
> -		pr_err("setup hotplug failed: %d\n", ret);
> -		return ret;
> -	}
> -
> -	ret = platform_driver_register(&hisi_cpa_pmu_driver);
> -	if (ret)
> -		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE);
> -
> -	return ret;
> -}
> -module_init(hisi_cpa_pmu_module_init);
> -
> -static void __exit hisi_cpa_pmu_module_exit(void)
> -{
> -	platform_driver_unregister(&hisi_cpa_pmu_driver);
> -	cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE);
> -}
> -module_exit(hisi_cpa_pmu_module_exit);
> +module_platform_driver(hisi_cpa_pmu_driver);
>   
>   MODULE_IMPORT_NS("HISI_PMU");
>   MODULE_DESCRIPTION("HiSilicon SoC CPA PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> index 21c494881ca0..e905160523ee 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> @@ -401,7 +401,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
>   	if (!name)
>   		return -ENOMEM;
>   
> -	ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
> +	ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
>   				       &ddrc_pmu->node);
>   	if (ret) {
>   		dev_err(&pdev->dev, "Error %d registering hotplug;\n", ret);
> @@ -414,7 +414,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
>   	if (ret) {
>   		dev_err(ddrc_pmu->dev, "DDRC PMU register failed!\n");
>   		cpuhp_state_remove_instance_nocalls(
> -			CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, &ddrc_pmu->node);
> +			hisi_uncore_pmu_cpuhp_state, &ddrc_pmu->node);
>   	}
>   
>   	return ret;
> @@ -425,7 +425,7 @@ static void hisi_ddrc_pmu_remove(struct platform_device *pdev)
>   	struct hisi_pmu *ddrc_pmu = platform_get_drvdata(pdev);
>   
>   	perf_pmu_unregister(&ddrc_pmu->pmu);
> -	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
> +	cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
>   					    &ddrc_pmu->node);
>   }
>   
> @@ -501,33 +501,7 @@ static struct platform_driver hisi_ddrc_pmu_driver = {
>   	.remove = hisi_ddrc_pmu_remove,
>   };
>   
> -static int __init hisi_ddrc_pmu_module_init(void)
> -{
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
> -				      "AP_PERF_ARM_HISI_DDRC_ONLINE",
> -				      hisi_uncore_pmu_online_cpu,
> -				      hisi_uncore_pmu_offline_cpu);
> -	if (ret) {
> -		pr_err("DDRC PMU: setup hotplug, ret = %d\n", ret);
> -		return ret;
> -	}
> -
> -	ret = platform_driver_register(&hisi_ddrc_pmu_driver);
> -	if (ret)
> -		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE);
> -
> -	return ret;
> -}
> -module_init(hisi_ddrc_pmu_module_init);
> -
> -static void __exit hisi_ddrc_pmu_module_exit(void)
> -{
> -	platform_driver_unregister(&hisi_ddrc_pmu_driver);
> -	cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE);
> -}
> -module_exit(hisi_ddrc_pmu_module_exit);
> +module_platform_driver(hisi_ddrc_pmu_driver);
>   
>   MODULE_IMPORT_NS("HISI_PMU");
>   MODULE_DESCRIPTION("HiSilicon SoC DDRC uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> index 97cfaa586a87..93a250b7abb8 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> @@ -490,7 +490,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
>   	if (!name)
>   		return -ENOMEM;
>   
> -	ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
> +	ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
>   				       &hha_pmu->node);
>   	if (ret) {
>   		dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> @@ -503,7 +503,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
>   	if (ret) {
>   		dev_err(hha_pmu->dev, "HHA PMU register failed!\n");
>   		cpuhp_state_remove_instance_nocalls(
> -			CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, &hha_pmu->node);
> +			hisi_uncore_pmu_cpuhp_state, &hha_pmu->node);
>   	}
>   
>   	return ret;
> @@ -514,7 +514,7 @@ static void hisi_hha_pmu_remove(struct platform_device *pdev)
>   	struct hisi_pmu *hha_pmu = platform_get_drvdata(pdev);
>   
>   	perf_pmu_unregister(&hha_pmu->pmu);
> -	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
> +	cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
>   					    &hha_pmu->node);
>   }
>   
> @@ -528,33 +528,7 @@ static struct platform_driver hisi_hha_pmu_driver = {
>   	.remove = hisi_hha_pmu_remove,
>   };
>   
> -static int __init hisi_hha_pmu_module_init(void)
> -{
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
> -				      "AP_PERF_ARM_HISI_HHA_ONLINE",
> -				      hisi_uncore_pmu_online_cpu,
> -				      hisi_uncore_pmu_offline_cpu);
> -	if (ret) {
> -		pr_err("HHA PMU: Error setup hotplug, ret = %d;\n", ret);
> -		return ret;
> -	}
> -
> -	ret = platform_driver_register(&hisi_hha_pmu_driver);
> -	if (ret)
> -		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE);
> -
> -	return ret;
> -}
> -module_init(hisi_hha_pmu_module_init);
> -
> -static void __exit hisi_hha_pmu_module_exit(void)
> -{
> -	platform_driver_unregister(&hisi_hha_pmu_driver);
> -	cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE);
> -}
> -module_exit(hisi_hha_pmu_module_exit);
> +module_platform_driver(hisi_hha_pmu_driver);
>   
>   MODULE_IMPORT_NS("HISI_PMU");
>   MODULE_DESCRIPTION("HiSilicon SoC HHA uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
> index f963e4f9e552..0b78a0e094dd 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
> @@ -93,6 +93,8 @@ struct hisi_l3c_pmu_ext {
>   	bool support_ext;
>   };
>   
> +static enum cpuhp_state hisi_l3c_pmu_cpuhp_state;
> +
>   static bool support_ext(struct hisi_l3c_pmu *pmu)
>   {
>   	struct hisi_l3c_pmu_ext *l3c_pmu_ext = pmu->l3c_pmu.dev_info->private;
> @@ -845,8 +847,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
>   	if (!name)
>   		return -ENOMEM;
>   
> -	ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
> -				       &l3c_pmu->node);
> +	ret = cpuhp_state_add_instance(hisi_l3c_pmu_cpuhp_state, &l3c_pmu->node);
>   	if (ret) {
>   		dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
>   		return ret;
> @@ -858,7 +859,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
>   	if (ret) {
>   		dev_err(l3c_pmu->dev, "L3C PMU register failed!\n");
>   		cpuhp_state_remove_instance_nocalls(
> -			CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, &l3c_pmu->node);
> +			hisi_l3c_pmu_cpuhp_state, &l3c_pmu->node);
>   	}
>   
>   	return ret;
> @@ -869,7 +870,7 @@ static void hisi_l3c_pmu_remove(struct platform_device *pdev)
>   	struct hisi_pmu *l3c_pmu = platform_get_drvdata(pdev);
>   
>   	perf_pmu_unregister(&l3c_pmu->pmu);
> -	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
> +	cpuhp_state_remove_instance_nocalls(hisi_l3c_pmu_cpuhp_state,
>   					    &l3c_pmu->node);
>   }
>   
> @@ -939,20 +940,20 @@ static int hisi_l3c_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
>   
>   static int __init hisi_l3c_pmu_module_init(void)
>   {
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
> +	int ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
>   				      "AP_PERF_ARM_HISI_L3_ONLINE",
>   				      hisi_l3c_pmu_online_cpu,
>   				      hisi_l3c_pmu_offline_cpu);
> -	if (ret) {
> +	if (ret < 0) {
>   		pr_err("L3C PMU: Error setup hotplug, ret = %d\n", ret);
>   		return ret;
>   	}
>   
> +	hisi_l3c_pmu_cpuhp_state = ret;
> +
>   	ret = platform_driver_register(&hisi_l3c_pmu_driver);
>   	if (ret)
> -		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE);
> +		cpuhp_remove_multi_state(hisi_l3c_pmu_cpuhp_state);
>   
>   	return ret;
>   }
> @@ -961,7 +962,7 @@ module_init(hisi_l3c_pmu_module_init);
>   static void __exit hisi_l3c_pmu_module_exit(void)
>   {
>   	platform_driver_unregister(&hisi_l3c_pmu_driver);
> -	cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE);
> +	cpuhp_remove_multi_state(hisi_l3c_pmu_cpuhp_state);
>   }
>   module_exit(hisi_l3c_pmu_module_exit);
>   
> diff --git a/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
> index 246cc0333099..ad898153ff49 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
> @@ -13,9 +13,6 @@
>   
>   #include "hisi_uncore_pmu.h"
>   
> -/* Dynamic CPU hotplug state used by MN PMU */
> -static enum cpuhp_state hisi_mn_pmu_online;
> -
>   /* MN register definition */
>   #define HISI_MN_DYNAMIC_CTRL_REG	0x400
>   #define   HISI_MN_DYNAMIC_CTRL_EN	BIT(0)
> @@ -291,7 +288,7 @@ static int hisi_mn_pmu_dev_init(struct platform_device *pdev,
>   
>   static void hisi_mn_pmu_remove_cpuhp(void *hotplug_node)
>   {
> -	cpuhp_state_remove_instance_nocalls(hisi_mn_pmu_online, hotplug_node);
> +	cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state, hotplug_node);
>   }
>   
>   static void hisi_mn_pmu_unregister(void *pmu)
> @@ -320,7 +317,7 @@ static int hisi_mn_pmu_probe(struct platform_device *pdev)
>   	if (!name)
>   		return -ENOMEM;
>   
> -	ret = cpuhp_state_add_instance(hisi_mn_pmu_online, &mn_pmu->node);
> +	ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state, &mn_pmu->node);
>   	if (ret)
>   		return dev_err_probe(&pdev->dev, ret, "Failed to register cpu hotplug\n");
>   
> @@ -376,33 +373,7 @@ static struct platform_driver hisi_mn_pmu_driver = {
>   	.probe = hisi_mn_pmu_probe,
>   };
>   
> -static int __init hisi_mn_pmu_module_init(void)
> -{
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/mn:online",
> -				      hisi_uncore_pmu_online_cpu,
> -				      hisi_uncore_pmu_offline_cpu);
> -	if (ret < 0) {
> -		pr_err("hisi_mn_pmu: Failed to setup MN PMU hotplug: %d\n", ret);
> -		return ret;
> -	}
> -	hisi_mn_pmu_online = ret;
> -
> -	ret = platform_driver_register(&hisi_mn_pmu_driver);
> -	if (ret)
> -		cpuhp_remove_multi_state(hisi_mn_pmu_online);
> -
> -	return ret;
> -}
> -module_init(hisi_mn_pmu_module_init);
> -
> -static void __exit hisi_mn_pmu_module_exit(void)
> -{
> -	platform_driver_unregister(&hisi_mn_pmu_driver);
> -	cpuhp_remove_multi_state(hisi_mn_pmu_online);
> -}
> -module_exit(hisi_mn_pmu_module_exit);
> +module_platform_driver(hisi_mn_pmu_driver);
>   
>   MODULE_IMPORT_NS("HISI_PMU");
>   MODULE_DESCRIPTION("HiSilicon SoC MN uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
> index 616f4af57db7..abf44fa46d17 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
> @@ -41,9 +41,6 @@
>   HISI_PMU_EVENT_ATTR_EXTRACTOR(ch, config1, 2, 0);
>   HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_en, config1, 3, 3);
>   
> -/* Dynamic CPU hotplug state used by this PMU driver */
> -static enum cpuhp_state hisi_noc_pmu_cpuhp_state;
> -
>   struct hisi_noc_pmu_regs {
>   	u32 version;
>   	u32 pmu_ctrl;
> @@ -324,7 +321,7 @@ static int hisi_noc_pmu_dev_init(struct platform_device *pdev, struct hisi_pmu *
>   
>   static void hisi_noc_pmu_remove_cpuhp_instance(void *hotplug_node)
>   {
> -	cpuhp_state_remove_instance_nocalls(hisi_noc_pmu_cpuhp_state, hotplug_node);
> +	cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state, hotplug_node);
>   }
>   
>   static void hisi_noc_pmu_unregister_pmu(void *pmu)
> @@ -353,7 +350,7 @@ static int hisi_noc_pmu_probe(struct platform_device *pdev)
>   	if (ret)
>   		return ret;
>   
> -	ret = cpuhp_state_add_instance(hisi_noc_pmu_cpuhp_state, &noc_pmu->node);
> +	ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state, &noc_pmu->node);
>   	if (ret)
>   		return dev_err_probe(dev, ret, "Fail to register cpuhp instance\n");
>   
> @@ -408,33 +405,7 @@ static struct platform_driver hisi_noc_pmu_driver = {
>   	.probe = hisi_noc_pmu_probe,
>   };
>   
> -static int __init hisi_noc_pmu_module_init(void)
> -{
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/noc:online",
> -				      hisi_uncore_pmu_online_cpu,
> -				      hisi_uncore_pmu_offline_cpu);
> -	if (ret < 0) {
> -		pr_err("hisi_noc_pmu: Fail to setup cpuhp callbacks, ret = %d\n", ret);
> -		return ret;
> -	}
> -	hisi_noc_pmu_cpuhp_state = ret;
> -
> -	ret = platform_driver_register(&hisi_noc_pmu_driver);
> -	if (ret)
> -		cpuhp_remove_multi_state(hisi_noc_pmu_cpuhp_state);
> -
> -	return ret;
> -}
> -module_init(hisi_noc_pmu_module_init);
> -
> -static void __exit hisi_noc_pmu_module_exit(void)
> -{
> -	platform_driver_unregister(&hisi_noc_pmu_driver);
> -	cpuhp_remove_multi_state(hisi_noc_pmu_cpuhp_state);
> -}
> -module_exit(hisi_noc_pmu_module_exit);
> +module_platform_driver(hisi_noc_pmu_driver);
>   
>   MODULE_IMPORT_NS("HISI_PMU");
>   MODULE_DESCRIPTION("HiSilicon SoC Uncore NoC PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
> index 80108c63cb60..3d1e0af64260 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
> @@ -468,7 +468,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
>   	if (!name)
>   		return -ENOMEM;
>   
> -	ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> +	ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
>   				       &pa_pmu->node);
>   	if (ret) {
>   		dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> @@ -479,7 +479,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
>   	ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
>   	if (ret) {
>   		dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
> -		cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> +		cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
>   						    &pa_pmu->node);
>   		return ret;
>   	}
> @@ -493,7 +493,7 @@ static void hisi_pa_pmu_remove(struct platform_device *pdev)
>   	struct hisi_pmu *pa_pmu = platform_get_drvdata(pdev);
>   
>   	perf_pmu_unregister(&pa_pmu->pmu);
> -	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> +	cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
>   					    &pa_pmu->node);
>   }
>   
> @@ -515,33 +515,7 @@ static struct platform_driver hisi_pa_pmu_driver = {
>   	.remove = hisi_pa_pmu_remove,
>   };
>   
> -static int __init hisi_pa_pmu_module_init(void)
> -{
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> -				      "AP_PERF_ARM_HISI_PA_ONLINE",
> -				      hisi_uncore_pmu_online_cpu,
> -				      hisi_uncore_pmu_offline_cpu);
> -	if (ret) {
> -		pr_err("PA PMU: cpuhp state setup failed, ret = %d\n", ret);
> -		return ret;
> -	}
> -
> -	ret = platform_driver_register(&hisi_pa_pmu_driver);
> -	if (ret)
> -		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE);
> -
> -	return ret;
> -}
> -module_init(hisi_pa_pmu_module_init);
> -
> -static void __exit hisi_pa_pmu_module_exit(void)
> -{
> -	platform_driver_unregister(&hisi_pa_pmu_driver);
> -	cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE);
> -}
> -module_exit(hisi_pa_pmu_module_exit);
> +module_platform_driver(hisi_pa_pmu_driver);
>   
>   MODULE_IMPORT_NS("HISI_PMU");
>   MODULE_DESCRIPTION("HiSilicon Protocol Adapter uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
> index de71dcf11653..276785a79ae9 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
> @@ -23,6 +23,9 @@
>   
>   #define HISI_MAX_PERIOD(nr) (GENMASK_ULL((nr) - 1, 0))
>   
> +enum cpuhp_state hisi_uncore_pmu_cpuhp_state;
> +EXPORT_SYMBOL_NS_GPL(hisi_uncore_pmu_cpuhp_state, "HISI_PMU");
> +
>   /*
>    * PMU event attributes
>    */
> @@ -621,5 +624,27 @@ void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module)
>   }
>   EXPORT_SYMBOL_NS_GPL(hisi_pmu_init, "HISI_PMU");
>   
> +static int __init hisi_uncore_pmu_init(void)
> +{
> +	int ret;
> +
> +	ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/uncore:online",
> +				      hisi_uncore_pmu_online_cpu,
> +				      hisi_uncore_pmu_offline_cpu);
> +	if (ret < 0)
> +		return ret;
> +
> +	hisi_uncore_pmu_cpuhp_state = ret;
> +
> +	return 0;
> +}
> +module_init(hisi_uncore_pmu_init);
> +
> +static void __exit hisi_uncore_pmu_exit(void)
> +{
> +	cpuhp_remove_multi_state(hisi_uncore_pmu_cpuhp_state);
> +}
> +module_exit(hisi_uncore_pmu_exit);
> +
>   MODULE_DESCRIPTION("HiSilicon SoC uncore Performance Monitor driver framework");
>   MODULE_LICENSE("GPL v2");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
> index 3ffe6acda653..e5a4b3898865 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
> +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
> @@ -171,4 +171,6 @@ int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
>   void hisi_uncore_pmu_init_topology(struct hisi_pmu *hisi_pmu, struct device *dev);
>   
>   void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module);
> +
> +extern enum cpuhp_state hisi_uncore_pmu_cpuhp_state;
>   #endif /* __HISI_UNCORE_PMU_H__ */
> diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> index cd32d606df05..d01340ff2e5c 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> @@ -503,7 +503,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
>   	if (!name)
>   		return -ENOMEM;
>   
> -	ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> +	ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
>   				       &sllc_pmu->node);
>   	if (ret) {
>   		dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> @@ -515,7 +515,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
>   	ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
>   	if (ret) {
>   		dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret);
> -		cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> +		cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
>   						    &sllc_pmu->node);
>   		return ret;
>   	}
> @@ -530,7 +530,7 @@ static void hisi_sllc_pmu_remove(struct platform_device *pdev)
>   	struct hisi_pmu *sllc_pmu = platform_get_drvdata(pdev);
>   
>   	perf_pmu_unregister(&sllc_pmu->pmu);
> -	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> +	cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
>   					    &sllc_pmu->node);
>   }
>   
> @@ -551,33 +551,7 @@ static struct platform_driver hisi_sllc_pmu_driver = {
>   	.remove = hisi_sllc_pmu_remove,
>   };
>   
> -static int __init hisi_sllc_pmu_module_init(void)
> -{
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> -				      "AP_PERF_ARM_HISI_SLLC_ONLINE",
> -				      hisi_uncore_pmu_online_cpu,
> -				      hisi_uncore_pmu_offline_cpu);
> -	if (ret) {
> -		pr_err("SLLC PMU: cpuhp state setup failed, ret = %d\n", ret);
> -		return ret;
> -	}
> -
> -	ret = platform_driver_register(&hisi_sllc_pmu_driver);
> -	if (ret)
> -		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
> -
> -	return ret;
> -}
> -module_init(hisi_sllc_pmu_module_init);
> -
> -static void __exit hisi_sllc_pmu_module_exit(void)
> -{
> -	platform_driver_unregister(&hisi_sllc_pmu_driver);
> -	cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
> -}
> -module_exit(hisi_sllc_pmu_module_exit);
> +module_platform_driver(hisi_sllc_pmu_driver);
>   
>   MODULE_IMPORT_NS("HISI_PMU");
>   MODULE_DESCRIPTION("HiSilicon SLLC uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> index e8186b6e1687..b4d017a5d688 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> @@ -13,9 +13,6 @@
>   
>   #include "hisi_uncore_pmu.h"
>   
> -/* Dynamic CPU hotplug state used by UC PMU */
> -static enum cpuhp_state hisi_uc_pmu_online;
> -
>   /* UC register definition */
>   #define HISI_UC_INT_MASK_REG		0x0800
>   #define HISI_UC_INT_STS_REG		0x0808
> @@ -488,7 +485,7 @@ static int hisi_uc_pmu_dev_probe(struct platform_device *pdev,
>   
>   static void hisi_uc_pmu_remove_cpuhp_instance(void *hotplug_node)
>   {
> -	cpuhp_state_remove_instance_nocalls(hisi_uc_pmu_online, hotplug_node);
> +	cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state, hotplug_node);
>   }
>   
>   static void hisi_uc_pmu_unregister_pmu(void *pmu)
> @@ -518,7 +515,7 @@ static int hisi_uc_pmu_probe(struct platform_device *pdev)
>   	if (!name)
>   		return -ENOMEM;
>   
> -	ret = cpuhp_state_add_instance(hisi_uc_pmu_online, &uc_pmu->node);
> +	ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state, &uc_pmu->node);
>   	if (ret)
>   		return dev_err_probe(&pdev->dev, ret, "Error registering hotplug\n");
>   
> @@ -559,34 +556,7 @@ static struct platform_driver hisi_uc_pmu_driver = {
>   	.probe = hisi_uc_pmu_probe,
>   };
>   
> -static int __init hisi_uc_pmu_module_init(void)
> -{
> -	int ret;
> -
> -	ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
> -				      "perf/hisi/uc:online",
> -				      hisi_uncore_pmu_online_cpu,
> -				      hisi_uncore_pmu_offline_cpu);
> -	if (ret < 0) {
> -		pr_err("UC PMU: Error setup hotplug, ret = %d\n", ret);
> -		return ret;
> -	}
> -	hisi_uc_pmu_online = ret;
> -
> -	ret = platform_driver_register(&hisi_uc_pmu_driver);
> -	if (ret)
> -		cpuhp_remove_multi_state(hisi_uc_pmu_online);
> -
> -	return ret;
> -}
> -module_init(hisi_uc_pmu_module_init);
> -
> -static void __exit hisi_uc_pmu_module_exit(void)
> -{
> -	platform_driver_unregister(&hisi_uc_pmu_driver);
> -	cpuhp_remove_multi_state(hisi_uc_pmu_online);
> -}
> -module_exit(hisi_uc_pmu_module_exit);
> +module_platform_driver(hisi_uc_pmu_driver);
>   
>   MODULE_IMPORT_NS("HISI_PMU");
>   MODULE_DESCRIPTION("HiSilicon SoC UC uncore PMU driver");
> diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
> index 0fb3a2a62eb0..965d6ce02a29 100644
> --- a/include/linux/cpuhotplug.h
> +++ b/include/linux/cpuhotplug.h
> @@ -210,12 +210,6 @@ enum cpuhp_state {
>   	CPUHP_AP_PERF_S390_SF_ONLINE,
>   	CPUHP_AP_PERF_ARM_CCI_ONLINE,
>   	CPUHP_AP_PERF_ARM_CCN_ONLINE,
> -	CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
> -	CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
> -	CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
> -	CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
> -	CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> -	CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
>   	CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE,
>   	CPUHP_AP_PERF_ARM_HNS3_PMU_ONLINE,
>   	CPUHP_AP_PERF_ARM_L2X0_ONLINE,



^ permalink raw reply

* [RFC PATCH 7/9] arm64/kprobes: Drop the KPROBE_HIT_SS reentry special case
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>

From: Hongyan Xia <hongyan.xia@transsion.com>

With the debug exception path noinstr from the vectors down to the
kprobe handlers and the only instrumentable code in the flow confined to
instrumentation_begin()/end() windows, a kprobe hit while another probe
is in KPROBE_HIT_SS can no longer happen.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/include/asm/kprobes.h   |  6 ------
 arch/arm64/kernel/probes/kprobes.c | 21 +--------------------
 2 files changed, 1 insertion(+), 26 deletions(-)

diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index a694f7d34f45..bff8ba9c1689 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -26,12 +26,6 @@
 struct prev_kprobe {
 	struct kprobe *kp;
 	unsigned int status;
-
-	/*
-	 * The original DAIF state of the outer kprobe, saved here before
-	 * a nested kprobe overwrites kcb->saved_irqflag during reentry.
-	 */
-	unsigned long saved_irqflag;
 };
 
 /* per-cpu kprobe control block */
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 4172998d48d9..1658b6acd803 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -176,13 +176,6 @@ static void noinstr save_previous_kprobe(struct kprobe_ctlblk *kcb)
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
 
-	/*
-	 * Save the outer kprobe's original DAIF flags before the nested
-	 * kprobe calls kprobes_save_local_irqflag() and overwrites
-	 * kcb->saved_irqflag. Without this, the outer kprobe will restore
-	 * the wrong DAIF state and leave interrupts permanently masked.
-	 */
-	kcb->prev_kprobe.saved_irqflag = kcb->saved_irqflag;
 }
 
 static void noinstr restore_previous_kprobe(struct kprobe_ctlblk *kcb)
@@ -190,12 +183,6 @@ static void noinstr restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
 	kcb->kprobe_status = kcb->prev_kprobe.status;
 
-	/*
-	 * Restore the outer kprobe's saved_irqflag so that when its
-	 * single-step completes, kprobes_restore_local_irqflag() uses
-	 * the correct original DAIF value.
-	 */
-	kcb->saved_irqflag = kcb->prev_kprobe.saved_irqflag;
 }
 
 static void noinstr set_current_kprobe(struct kprobe *p)
@@ -258,18 +245,12 @@ static int noinstr reenter_kprobe(struct kprobe *p,
 	switch (kcb->kprobe_status) {
 	case KPROBE_HIT_SSDONE:
 	case KPROBE_HIT_ACTIVE:
-	case KPROBE_HIT_SS:
-		/*
-		 * A probe can be hit while another kprobe is preparing or
-		 * executing its XOL single-step instruction. This is still a
-		 * recoverable one-level reentry, so handle it in the same way as
-		 * reentry from KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE.
-		 */
 		instrumentation_begin();
 		kprobes_inc_nmissed_count(p);
 		instrumentation_end();
 		setup_singlestep(p, regs, kcb, 1);
 		break;
+	case KPROBE_HIT_SS:
 	case KPROBE_REENTER:
 		instrumentation_begin();
 		pr_warn("Failed to recover from reentered kprobes.\n");
-- 
2.47.3



^ permalink raw reply related

* Re: [PATCH v5 1/3] soc: qcom: smem: Use 'unsigned int' instead of 'unsigned'
From: Mukesh Ojha @ 2026-07-27 12:35 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Bjorn Andersson, Kees Cook, Gustavo A. R. Silva, Rob Clark,
	Sean Paul, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
	Alim Akhtar, Avri Altman, Bart Van Assche, James E.J. Bottomley,
	Martin K. Petersen, Matthias Brugger, AngeloGioacchino Del Regno,
	Suzuki K Poulose, Mike Leach, James Clark, Leo Yan, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yuanfang Zhang, Mao Jinlong,
	Jie Gan, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, linux-kernel, linux-arm-msm, linux-hardening,
	dri-devel, freedreno, Konrad Dybcio, linux-scsi, linux-arm-kernel,
	linux-mediatek, coresight, devicetree, linux-riscv
In-Reply-To: <20260727-topic-smem_dramc-v5-1-66188b3e338d@oss.qualcomm.com>

On Mon, Jul 27, 2026 at 11:59:27AM +0200, Konrad Dybcio wrote:
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> 
> checkpatch.pl reports:
> 
> WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
> 
> Convert the SMEM driver to use the less ambiguous type instead.
> 
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

Reviewed-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>

-- 
-Mukesh Ojha


^ permalink raw reply

* Re: [PATCH v9 0/5] Add SCDC information to connector debugfs
From: Nicolas Frattaroli @ 2026-07-27 12:28 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
	Daniel Stone, Hans Verkuil, Chen-Yu Tsai, Samuel Holland,
	Dave Stevenson, Maíra Canal, Raspberry Pi Kernel Maintenance,
	Jani Nikula
  Cc: dri-devel, linux-kernel, kernel, linux-arm-kernel, linux-sunxi,
	Dmitry Baryshkov
In-Reply-To: <1c9d3a50341129188242b1b2758fcee5eab243db@intel.com>

On Monday, 27 July 2026 10:35:15 Central European Summer Time Jani Nikula wrote:
> On Fri, 24 Jul 2026, Nicolas Frattaroli <nicolas.frattaroli@collabora.com> wrote:
> > HDMI uses the DDC I2C bus for communicating various bits of link status
> > out of band with the actual HDMI video signal. This information can be
> > useful for debugging issues like questionable cables sabotaged by feline
> > teeth, Enthusiast Grade cables made of cow fencing wire, and other such
> > problems that ruin one's media viewing plans.
> >
> > Consequently, this series exposes various bits of pertinent information
> > from the SCDC protocol in an HDMI connector's debugfs. To continually
> > poll the link status, userspace can poll the debugfs file.
> 
> Is there a reason we can't add a character device node for this similar
> to DP AUX? See config DRM_DISPLAY_DP_AUX_CHARDEV.

You already can just point tools at the ddc symlink to the i2c dev.

The idea here is to be able to read this out of debugfs without
any additional external tooling needed.

> It's ultimately more generic than deciphering everything in kernel.

The kernel will need to decipher this in the future anyway for HDMI 2.x
support, including so that it can set link status to bad when there's a
glut of errors.

> 
> 
> BR,
> Jani.
> 
> 
> 
> 
> 
> >
> > ---
> > Changes in v9:
> > - Unlock mode_config.mutex on disconnected connector early exit
> > - Calculate and print Reed-Solomon error corrections counter on != 4
> >   lane FRL as well. Technically a functional change to an already
> >   reviewed patch, but I kept the R-b because it's so minor.
> > - Link to v8: https://patch.msgid.link/20260722-scdc-link-health-v8-0-cd1dacbb85d9@collabora.com
> >
> > Changes in v8:
> > - Acquire mode_config mutex in an interruptible way during
> >   scdc_status_show to avoid racing connector state
> > - Remove scdc_debugfs_priv, use connector as debugfs entry priv instead
> > - Allocate and free state in scdc_status_show, since it doesn't need to
> >   persist across debugfs reads
> > - Check for NULL ddc in drm_scdc_read_state in the unlikely event an
> >   EDID with the SCDC flag was forced on a connector with no DDC
> > - Note: drm_connector_get() is omitted from drm_scdc_debugfs_init
> >   because drm_scdc_debugfs_init is called on connector construction and
> >   the debugfs is removed on connector destruction. Adding a redundant
> >   reference increase here would necessitate introducing a destruction
> >   callback to mirror the debugfs_init connector op for the sole purpose
> >   of decreasing the counter again.
> > - Link to v7: https://patch.msgid.link/20260721-scdc-link-health-v7-0-92df1b6ad5fc@collabora.com
> >
> > Changes in v7:
> > - Move HDMI debugfs registration to new state helper, fix up all users
> >   (sun4i, vc4, bridge)
> > - Register scdc debugfs in new hdmi debugfs helper
> > - Link to v6: https://patch.msgid.link/20260611-scdc-link-health-v6-0-6307875a6b5e@collabora.com
> >
> > Changes in v6:
> > - Fix off-by-one error in drm_scdc_read_state
> > - Link to v5: https://patch.msgid.link/20260604-scdc-link-health-v5-0-11173b0ac3de@collabora.com
> >
> > Changes in v5:
> > - Read all SCDC data regardless of update flags
> > - Dump SCDC data as hex before the human-readable output. It's separated
> >   with "\n----------------\n\n".
> > - No longer write 0 to read-only registers
> > - Add Reed-Solomon Corrections counter parsing
> > - Parsing has been kept. A desire was expressed to get this data without
> >   any external userspace tooling, and the kernel will need to parse it
> >   eventually anyway to set the link status.
> > - Functions have been made static as of right now, since external users
> >   may do another pass over the function signatures anyway.
> > - Link to v4: https://patch.msgid.link/20260527-scdc-link-health-v4-0-622ea40a1f59@collabora.com
> >
> > Changes in v4:
> > - Don't use C struct bitfields for parsing status flags. Switch to
> >   bitwise AND for boolean flags, and FIELD_GET for multi-bit values.
> > - Drop the superfluous !! and parens
> > - Drop the __pure attributes on static functions
> > - Initialise stack local arrays with {}, not { 0 }.
> > - I've kept the print macros and %-30s format. Reason being that I don't
> >   want to repeat the format specifier and str_yes_no(foo) a bunch, and I
> >   like the %-30s format because it means all values are aligned with the
> >   value of the longest field, which is 30 chars long.
> > - Link to v3: https://patch.msgid.link/20260526-scdc-link-health-v3-0-59e4a4aaead1@collabora.com
> >
> > Changes in v3:
> > - Add patch to change return type of drm_scdc_read/write.
> > - Rework error counter reading to duplicate less code.
> > - Also check lane 3 counter valid flag when reading its error counter.
> > - Use memset to clear buf for error counters, rather than doing it in
> >   the loop.
> > - Make read_error_counters not accept 0 as num_lanes; fix it up in the
> >   caller instead.
> > - Link to v2: https://patch.msgid.link/20260520-scdc-link-health-v2-0-511af18cd64b@collabora.com
> >
> > Changes in v2:
> > - Add HDMI 2.1 SCDC status reporting
> > - Link to v1: https://patch.msgid.link/20260415-scdc-link-health-v1-0-8e731e88eaf0@collabora.com
> >
> > To: Jani Nikula <jani.nikula@linux.intel.com>
> > To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > To: Maxime Ripard <mripard@kernel.org>
> > To: Thomas Zimmermann <tzimmermann@suse.de>
> > To: David Airlie <airlied@gmail.com>
> > To: Simona Vetter <simona@ffwll.ch>
> > To: Andrzej Hajda <andrzej.hajda@intel.com>
> > To: Neil Armstrong <neil.armstrong@linaro.org>
> > To: Robert Foss <rfoss@kernel.org>
> > To: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
> > To: Jonas Karlman <jonas@kwiboo.se>
> > To: Jernej Skrabec <jernej.skrabec@gmail.com>
> > To: Luca Ceresoli <luca.ceresoli@bootlin.com>
> > To: Daniel Stone <daniel@fooishbar.org>
> > To: Hans Verkuil <hverkuil+cisco@kernel.org>
> > To: Chen-Yu Tsai <wens@kernel.org>
> > To: Samuel Holland <samuel@sholland.org>
> > To: Dave Stevenson <dave.stevenson@raspberrypi.com>
> > To: Maíra Canal <mcanal@igalia.com>
> > To: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
> > Cc: dri-devel@lists.freedesktop.org
> > Cc: linux-kernel@vger.kernel.org
> > Cc: kernel@collabora.com
> > Cc: linux-arm-kernel@lists.infradead.org
> > Cc: linux-sunxi@lists.linux.dev
> > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> >
> > ---
> > Nicolas Frattaroli (5):
> >       drm/scdc-helper: Don't use ssize_t return type for scdc_read/write
> >       drm/scdc-helper: Add scdc_status debugfs entry
> >       drm/scdc-helper: Implement parsing and printing HDMI 2.1 fields
> >       drm/debugfs: Move HDMI debugfs registration to state helper
> >       drm/display: hdmi-state-helper: Init SCDC debugfs for HDMI
> >
> >  drivers/gpu/drm/display/drm_bridge_connector.c  |   3 +
> >  drivers/gpu/drm/display/drm_hdmi_state_helper.c | 156 +++++++++++++
> >  drivers/gpu/drm/display/drm_scdc_helper.c       | 289 +++++++++++++++++++++++-
> >  drivers/gpu/drm/drm_debugfs.c                   | 157 -------------
> >  drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c          |   1 +
> >  drivers/gpu/drm/vc4/vc4_hdmi.c                  |   1 +
> >  include/drm/display/drm_hdmi_state_helper.h     |   3 +
> >  include/drm/display/drm_scdc.h                  |  21 +-
> >  include/drm/display/drm_scdc_helper.h           | 103 ++++++++-
> >  9 files changed, 568 insertions(+), 166 deletions(-)
> > ---
> > base-commit: b747a63003130bef1a3d5d6ba97c94d0cee36f55
> > change-id: 20260413-scdc-link-health-89326013d96c
> >
> > Best regards,
> > --  
> > Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> >
> 
> 






^ permalink raw reply

* [PATCH v4 16/16] ARM: dts: microchip: sama7d65: add thermal zones node
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add thermal zones node for SAMA7D65 with trip points for passive
cooling and critical shutdown.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
---
 arch/arm/boot/dts/microchip/sama7d65.dtsi | 42 +++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
index 3aba73983c79..7743f9e8f692 100644
--- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
+++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
@@ -16,6 +16,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/mfd/at91-usart.h>
 #include <dt-bindings/nvmem/microchip,sama7g5-otpc.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	model = "Microchip SAMA7D65 family SoC";
@@ -38,6 +39,7 @@ cpu0: cpu@0 {
 			i-cache-size = <0x8000>;	// L1, 32 KB
 			next-level-cache = <&L2>;
 			operating-points-v2 = <&cpu_opp_table>;
+			#cooling-cells = <2>; /* min followed by max */
 
 			L2: l2-cache {
 				compatible = "cache";
@@ -126,6 +128,46 @@ thermal_sensor: thermal-sensor {
 		io-channel-names = "sensor-channel";
 	};
 
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			polling-delay-passive = <1000>;
+			polling-delay = <5000>;
+			thermal-sensors = <&thermal_sensor>;
+
+			trips {
+				cpu_normal: cpu-alert0 {
+					temperature = <90000>;
+					hysteresis = <0>;
+					type = "passive";
+				};
+
+				cpu_hot: cpu-alert1 {
+					temperature = <95000>;
+					hysteresis = <0>;
+					type = "passive";
+				};
+
+				cpu_critical: cpu-critical {
+					temperature = <100000>;
+					hysteresis = <0>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_normal>;
+					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+
+				map1 {
+					trip = <&cpu_hot>;
+					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+	};
+
 	soc {
 		compatible = "simple-bus";
 		ranges;
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 15/16] ARM: dts: microchip: sama7d65: add temperature sensor
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add the generic-adc-thermal temperature sensor node for SAMA7D65.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
---
 arch/arm/boot/dts/microchip/sama7d65.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
index a8b18ad0ef7f..3aba73983c79 100644
--- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
+++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
@@ -119,6 +119,13 @@ pmu {
 		interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	thermal_sensor: thermal-sensor {
+		compatible = "generic-adc-thermal";
+		#thermal-sensor-cells = <0>;
+		io-channels = <&adc AT91_SAMA7G5_ADC_TEMP_CHANNEL>;
+		io-channel-names = "sensor-channel";
+	};
+
 	soc {
 		compatible = "simple-bus";
 		ranges;
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH] drm/mediatek: mtk_dsi: enable hs clock during pre-enable
From: Thorsten Leemhuis @ 2026-07-27 12:28 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, Gary Bisson
  Cc: Chun-Kuang Hu, Esben Haabendal, Philipp Zabel, David Airlie,
	Simona Vetter, Matthias Brugger, dri-devel, linux-mediatek,
	linux-kernel, linux-arm-kernel, Adam Thiede,
	Linux kernel regressions list
In-Reply-To: <alpTEPsy-SIQv_Oc@owl5>

[top-posting to facilitate]

Gary, Angelo, what's the status here? It looks like this fell through
the cracks -- or was this issue fixed in between somehow? If yes: great!
If not: Would be good to finally resolve this, as we are long past "fix
within a week" rule of thumb from Linus:
https://www.kernel.org/doc/html/latest/process/handling-regressions.html#on-how-quickly-regressions-should-be-fixed

And also nearing -rc6, which is when Linus would like to see all known
regressions fixed.

Ciao, Thorsten

On 7/17/26 18:06, Gary Bisson wrote:
> On Wed, Jul 15, 2026 at 03:52:05PM +0200, Esben Haabendal wrote:
>> "AngeloGioacchino Del Regno" <angelogioacchino.delregno@collabora.com>
>> writes:
>>> On 7/15/26 15:36, Gary Bisson wrote:
>>>> On Wed, Jul 15, 2026 at 03:25:11PM +0200, AngeloGioacchino Del Regno wrote:
>>>>> On 7/15/26 14:53, Esben Haabendal wrote:
>>>>>> Gary Bisson <bisson.gary@gmail.com> writes:
>>>>>>
>>>>>>> Some bridges, such as the TI SN65DSI83, require the HS clock to be
>>>>>>> running in order to lock its PLL during its own pre-enable function.
>>>>>>>
>>>>>>> Without this change, the bridge gives the following error:
>>>>>>> sn65dsi83 14-002c: failed to lock PLL, ret=-110
>>>>>>> sn65dsi83 14-002c: Unexpected link status 0x01
>>>>>>> sn65dsi83 14-002c: reset the pipe
>>>>>>>
>>>>>>> Move the necessary functions from enable to pre-enable.
>>>>>>>>>>>> I have run into the same problem, but in combination with
another
>>>>>> pipeline. I am seeing same problem with an i.MX8 using the nwl-dsi
>>>>>> bridge and the dcss driver.
>>>>>>
>>>>>> I have submitted a fix that adresses the problem in the ti-sn65dsi83
>>>>>> driver instead. With a bit of luck, it can replace the fix proposed in
>>>>>> this thread.
>>>>>>
>>>>>> See https://lore.kernel.org/all/20260711-ti-sn65dsi83-fixes-v1-2-d85eb5342b98@geanix.com/
>>>>
>>>> Thanks, just tried it on 7.2-rc3 with my patch reverted and confirm that
>>>> it works too. My assumption was that the SN65DSI83 was locking the PLL
>>>> earlier for some specific reason and therefore was reluctant to change
>>>> it.
>>>>
>>>>> That clarifies a lot of things.
>>>>>
>>>>> The patch on mtk_dsi shall be reverted then.
>>>>
>>>> Angelo, do you want me to offer the revert patch? Should I wait to see
>>>> how the other thread goes?
>>>
>>> Gary, yes please, send a revert and make sure to explain the reason why
>>> we're reverting this in the commit description :-)
>>
>> Maybe test if my fix actually solves the problem with the mtk_dsi driver
>> also ;)
> 
> As mentioned in the other thread, your patch works but it might break
> the init sequence recommended by the bridge datasheet.
> 
> Moreover, the drm_bridge.c doc [1] does mention that the clock lane
> should be initialized during pre_enable. If we agree on this assumption
> I believe my patch should not be reverted.
> 
> Maybe Adam's bridge driver must be patched instead, just like the
> nwl-dsi driver should be updated to follow the drm recommendation.
> 
> Let me know your thoughts.


^ permalink raw reply

* [PATCH v4 14/16] ARM: dts: microchip: sama7d65: add cells for temperature calibration
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add nvmem-cells for temperature calibration data to the ADC node.
The calibration data is read from the OTPC.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
---
 arch/arm/boot/dts/microchip/sama7d65.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
index aac2e22d96cb..a8b18ad0ef7f 100644
--- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
+++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
@@ -318,6 +318,8 @@ adc: adc@e1000000 {
 			dmas = <&dma0 AT91_XDMAC_DT_PERID(0)>;
 			dma-names = "rx";
 			#io-channel-cells = <1>;
+			nvmem-cells = <&temperature_calib>;
+			nvmem-cell-names = "temperature_calib";
 			atmel,min-sample-rate-hz = <200000>;
 			atmel,max-sample-rate-hz = <20000000>;
 			atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 11/16] ARM: dts: microchip: sama7d65: Add ADC node
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add node for the ADC controller in sama7d65 SoC. Add the vddout25 fixed
regulator node which provides the 2.5V reference voltage for the ADC.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 arch/arm/boot/dts/microchip/sama7d65.dtsi | 28 +++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
index dfac17e34e65..c35f27615bc4 100644
--- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
+++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
@@ -11,6 +11,7 @@
 #include <dt-bindings/clock/at91.h>
 #include <dt-bindings/dma/at91.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/iio/adc/at91-sama5d2_adc.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/mfd/at91-usart.h>
@@ -95,6 +96,15 @@ slow_xtal: clock-slowxtal {
 		};
 	};
 
+	vddout25: fixed-regulator-vddout25 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDOUT25";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-boot-on;
+		status = "disabled";
+	};
+
 	ns_sram: sram@100000 {
 		compatible = "mmio-sram";
 		reg = <0x100000 0x20000>;
@@ -296,6 +306,24 @@ can4: can@e0838000 {
 			status = "disabled";
 		};
 
+		adc: adc@e1000000 {
+			compatible = "microchip,sama7d65-adc";
+			reg = <0xe1000000 0x200>;
+			interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_GCK 25>;
+			clock-names = "adc_clk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 25>;
+			assigned-clock-rates = <100000000>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(0)>;
+			dma-names = "rx";
+			#io-channel-cells = <1>;
+			atmel,min-sample-rate-hz = <200000>;
+			atmel,max-sample-rate-hz = <20000000>;
+			atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
+			atmel,startup-time-ms = <4>;
+			status = "disabled";
+		};
+
 		dma2: dma-controller@e1200000 {
 			compatible = "microchip,sama7d65-dma", "microchip,sama7g5-dma";
 			reg = <0xe1200000 0x1000>;
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 13/16] ARM: dts: microchip: sama7d65: add otpc node
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add OTPC node along with temperature calibration cell.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 arch/arm/boot/dts/microchip/sama7d65.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
index c35f27615bc4..aac2e22d96cb 100644
--- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
+++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
@@ -15,6 +15,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/mfd/at91-usart.h>
+#include <dt-bindings/nvmem/microchip,sama7g5-otpc.h>
 
 / {
 	model = "Microchip SAMA7D65 family SoC";
@@ -1111,6 +1112,21 @@ ddr3phy: ddr3phy@e3804000 {
 			reg = <0xe3804000 0x1000>;
 		};
 
+		otpc: efuse@e8c00000 {
+			compatible = "microchip,sama7d65-otpc", "microchip,sama7g5-otpc", "syscon";
+			reg = <0xe8c00000 0x100>;
+
+			nvmem-layout {
+				compatible = "fixed-layout";
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				temperature_calib: calib@41435354 {
+					reg = <0x41435354 0x2c>;	/* Temp calib data packet TAG */
+				};
+			};
+		};
+
 		gic: interrupt-controller@e8c11000 {
 			compatible = "arm,cortex-a7-gic";
 			reg = <0xe8c11000 0x1000>,
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH v2 2/2] arm64: dts: exynos850: Add acpm SRAM node
From: Alexey Klimov @ 2026-07-27 12:28 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Sam Protsenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Alim Akhtar, Peter Griffin, Tudor Ambarus, linux-samsung-soc,
	linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260724-hissing-fascinating-terrier-6b754f@quoll>

On Fri Jul 24, 2026 at 9:38 AM BST, Krzysztof Kozlowski wrote:
> On Thu, Jul 23, 2026 at 04:29:47PM +0100, Alexey Klimov wrote:
>> SRAM is used by the ACPM protocol to retrieve the ACPM channels
>> information and configuration data. Add the SRAM node.
>> 
>> Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
>> ---
>>  arch/arm64/boot/dts/exynos/exynos850.dtsi | 5 +++++
>>  1 file changed, 5 insertions(+)
>> 
>> diff --git a/arch/arm64/boot/dts/exynos/exynos850.dtsi b/arch/arm64/boot/dts/exynos/exynos850.dtsi
>> index 3881f573ec08..9a8d92aae9a8 100644
>> --- a/arch/arm64/boot/dts/exynos/exynos850.dtsi
>> +++ b/arch/arm64/boot/dts/exynos/exynos850.dtsi
>> @@ -917,6 +917,11 @@ spi_2: spi@11d20000 {
>>  			};
>>  		};
>>  	};
>> +
>> +	apm_sram: sram@2039000 {
>
> Looks oddly placed, suggesting this is not part of SoC, but all MMIO
> nodes must be part of the SoC if this is SoC. Compatible says this is
> SoC.

Thanks! Yep, I'll move it to SoC section then, in the beginning of it
according to sorting order and address.

Best regards,
Alexey


^ permalink raw reply

* [PATCH v4 12/16] ARM: dts: microchip: sama7d65_curiosity: Enable ADC, DVFS
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Enable ADC and DVFS on SAMA7D65 Curiosity board. Configure the necessary
power supply (vddana, vref) for the ADC, and enable cpu-supply for DVFS.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
---
 .../dts/microchip/at91-sama7d65_curiosity.dts | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dts
index 927c27260b6c..c2d1e5308170 100644
--- a/arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dts
@@ -79,6 +79,14 @@ reg_5v: regulator-5v {
 	};
 };
 
+&adc {
+	vddana-supply = <&vddout25>;
+	vref-supply = <&vddout25>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
+	status = "okay";
+};
+
 &can1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_can1_default>;
@@ -97,6 +105,10 @@ &can3 {
 	status = "okay";
 };
 
+&cpu0 {
+	cpu-supply = <&vddcpu>;
+};
+
 &dma0 {
 	status = "okay";
 };
@@ -334,6 +346,16 @@ &main_xtal {
 };
 
 &pioa {
+	pinctrl_adc_default: adc-default {
+		pinmux = <PIN_PC5__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_adtrg_default: adtrg-default {
+		pinmux = <PIN_PB7__ADTRG>;
+		bias-pull-up;
+	};
+
 	pinctrl_can1_default: can1-default {
 		pinmux = <PIN_PD10__CANTX1>,
 			 <PIN_PD11__CANRX1>;
@@ -457,3 +479,8 @@ input@0 {
 &slow_xtal {
 	clock-frequency = <32768>;
 };
+
+&vddout25 {
+	vin-supply = <&vdd_3v3>;
+	status = "okay";
+};
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 10/16] ARM: dts: microchip: sama7d65: add cpu opps
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add CPU OPPs table for SAMA7D65.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 arch/arm/boot/dts/microchip/sama7d65.dtsi | 36 +++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
index ec200848c153..dfac17e34e65 100644
--- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
+++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
@@ -35,6 +35,7 @@ cpu0: cpu@0 {
 			d-cache-size = <0x8000>;	// L1, 32 KB
 			i-cache-size = <0x8000>;	// L1, 32 KB
 			next-level-cache = <&L2>;
+			operating-points-v2 = <&cpu_opp_table>;
 
 			L2: l2-cache {
 				compatible = "cache";
@@ -45,6 +46,41 @@ L2: l2-cache {
 		};
 	};
 
+	cpu_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp-90000000 {
+			opp-hz = /bits/ 64 <90000000>;
+			opp-microvolt = <1050000 1050000 1225000>;
+			clock-latency-ns = <320000>;
+		};
+
+		opp-250000000 {
+			opp-hz = /bits/ 64 <250000000>;
+			opp-microvolt = <1050000 1050000 1225000>;
+			clock-latency-ns = <320000>;
+		};
+
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <1050000 1050000 1225000>;
+			clock-latency-ns = <320000>;
+			opp-suspend;
+		};
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <1150000 1125000 1225000>;
+			clock-latency-ns = <320000>;
+		};
+
+		opp-1000000002 {
+			opp-hz = /bits/ 64 <1000000002>;
+			opp-microvolt = <1250000 1225000 1300000>;
+			clock-latency-ns = <320000>;
+		};
+	};
+
 	clocks {
 		main_xtal: clock-mainxtal {
 			compatible = "fixed-clock";
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 08/16] nvmem: microchip-otpc: nvmem: microchip-otpc: add tag-based packet lookup
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add support for accessing OTP packets by their tag which is a FourCC
while preserving backward compatibility with the existing ID-based
lookup.

The OTP memory layout can vary across devices and may change over time,
making the packet ID approach unreliable when the memory map is not
known in advance. The packet tag provides a reliable way to identify
and access packets without prior knowledge of the OTP memory layout.

Two offset encodings are now supported:
  1. Legacy ID-based: offset = OTP_PKT(id) = id * 4
     Used in DT as: reg = <OTP_PKT(1) 76>;
  2. TAG-based: offset = 4-byte ASCII packet tag (FourCC)
     Used in DT as: reg = <0x41435354 0x4c>; (tag "ACST")

The driver resolves offsets matching valid legacy selectors (multiples
of 4 within the packet count) through ID lookup, falling back to tag
lookup for other valid values. This ensures existing device trees
continue to work while enabling new tag-based access. During probe,
packet meta data including the tag is read and cached.

The stride of the nvmem memory is set to 1 in order to support tag based
offsets, comment in the header file is updated accordingly.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 drivers/nvmem/microchip-otpc.c                | 117 ++++++++++++++++--
 .../nvmem/microchip,sama7g5-otpc.h            |   4 +-
 2 files changed, 110 insertions(+), 11 deletions(-)

diff --git a/drivers/nvmem/microchip-otpc.c b/drivers/nvmem/microchip-otpc.c
index df979e8549fd..a17f82afdc37 100644
--- a/drivers/nvmem/microchip-otpc.c
+++ b/drivers/nvmem/microchip-otpc.c
@@ -23,6 +23,8 @@
 #define MCHP_OTPC_SR_READ		BIT(6)
 #define MCHP_OTPC_HR			(0x20)
 #define MCHP_OTPC_HR_SIZE		GENMASK(15, 8)
+#define MCHP_OTPC_HR_PACKET		GENMASK(2, 0)
+#define MCHP_OTPC_HR_PACKET_REGULAR	1
 #define MCHP_OTPC_DR			(0x24)
 
 #define MCHP_OTPC_NAME			"mchp-otpc"
@@ -47,11 +49,13 @@ struct mchp_otpc {
  * @list: list head
  * @id: packet ID
  * @offset: packet offset (in words) in OTP memory
+ * @tag: 4-byte ASCII (FourCC) tag of the packet
  */
 struct mchp_otpc_packet {
 	struct list_head list;
 	u32 id;
 	u32 offset;
+	u32 tag;
 };
 
 static struct mchp_otpc_packet *mchp_otpc_id_to_packet(struct mchp_otpc *otpc,
@@ -70,6 +74,52 @@ static struct mchp_otpc_packet *mchp_otpc_id_to_packet(struct mchp_otpc *otpc,
 	return NULL;
 }
 
+static struct mchp_otpc_packet *mchp_otpc_tag_to_packet(struct mchp_otpc *otpc, u32 tag)
+{
+	struct mchp_otpc_packet *packet;
+
+	list_for_each_entry(packet, &otpc->packets, list) {
+		if (packet->tag == tag)
+			return packet;
+	}
+
+	return NULL;
+}
+
+static bool mchp_otpc_is_valid_fourcc(u32 tag)
+{
+	int i;
+	u8 c;
+
+	for (i = 0; i < 4; i++) {
+		c = (tag >> (i * 8)) & 0xff;
+		if (c < 0x20 || c > 0x7e)
+			return false;
+	}
+
+	return true;
+}
+
+static struct mchp_otpc_packet *mchp_otpc_resolve_packet(struct mchp_otpc *otpc, u32 off)
+{
+	/*
+	 * Legacy id based packet access: offset = id * 4
+	 * Inside the driver we use continuous unsigned integer numbers
+	 * for packet id, thus divide off by 4 before passing it to
+	 * mchp_otpc_id_to_packet().
+	 */
+	u32 remainder = off % 4;
+	u32 id = off / 4;
+
+	if (!remainder && id < otpc->npackets)
+		return mchp_otpc_id_to_packet(otpc, id);
+
+	/*
+	 * TAG-based packet access: offset is a 4-byte ASCII tag (FourCC)
+	 */
+	return mchp_otpc_tag_to_packet(otpc, off);
+}
+
 static int mchp_otpc_prepare_read(struct mchp_otpc *otpc,
 				  unsigned int offset)
 {
@@ -140,8 +190,29 @@ static int mchp_otpc_prepare_read(struct mchp_otpc *otpc,
  * offset returned by hardware.
  *
  * For this, the read function will return the first requested bytes in the
- * packet. The user will have to be aware of the memory footprint before doing
- * the read request.
+ * packet.
+ *
+ * Two offset encodings are supported:
+ *
+ * 1. Legacy ID-based: offset = OTP_PKT(id) = id * 4
+ *    Used in DT as: reg = <OTP_PKT(1) 76>;
+ * 2. TAG-based: offset = 4-byte ASCII packet tag (FourCC)
+ *    Used in DT as: reg = <0x41435354 0x4c>; (tag "ACST")
+ *
+ * To use the legacy ID based packet lookup the user will have to be aware of
+ * the memory footprint before doing the read request.
+ *
+ * But by using the TAG based packet lookup, the user won't have to be aware
+ * of the memory footprint before doing the read request since this driver has
+ * it abstracted and taken care of.
+ *
+ * Practically, there is no way of knowing the mapping of the OTP memory table
+ * in advance for every device. But by using the packet tag - the identifier
+ * ASCII value (FourCC), the packets can be recognized without being aware of the
+ * flashed OTP memory map table and the payload can be acquired reliably.
+ *
+ * While the legacy ID based lookup is still supported, TAG based approach is
+ * recommended.
  */
 static int mchp_otpc_read(void *priv, unsigned int off, void *val,
 			  size_t bytes)
@@ -154,12 +225,11 @@ static int mchp_otpc_read(void *priv, unsigned int off, void *val,
 	int ret, payload_size;
 
 	/*
-	 * We reach this point with off being multiple of stride = 4 to
-	 * be able to cross the subsystem. Inside the driver we use continuous
-	 * unsigned integer numbers for packet id, thus divide off by 4
-	 * before passing it to mchp_otpc_id_to_packet().
+	 * From this point the offset has to be translated into the actual
+	 * packet. For this we traverse the table of contents stored in a list
+	 * "packet" based on the access type - packet id or tag.
 	 */
-	packet = mchp_otpc_id_to_packet(otpc, off / 4);
+	packet = mchp_otpc_resolve_packet(otpc, off);
 	if (!packet)
 		return -EINVAL;
 	offset = packet->offset;
@@ -190,10 +260,25 @@ static int mchp_otpc_read(void *priv, unsigned int off, void *val,
 	return 0;
 }
 
+static int mchp_otpc_read_packet_tag(struct mchp_otpc *otpc, unsigned int offset,
+				     unsigned int *tag)
+{
+	int ret;
+
+	ret = mchp_otpc_prepare_read(otpc, offset);
+	if (ret)
+		return ret;
+
+	writel_relaxed(0, otpc->base + MCHP_OTPC_AR);
+	*tag = readl_relaxed(otpc->base + MCHP_OTPC_DR);
+
+	return 0;
+}
+
 static int mchp_otpc_init_packets_list(struct mchp_otpc *otpc, u32 *size)
 {
 	struct mchp_otpc_packet *packet;
-	u32 word, word_pos = 0, id = 0, npackets = 0, payload_size;
+	u32 word, word_pos = 0, id = 0, npackets = 0, payload_size, type;
 	int ret;
 
 	INIT_LIST_HEAD(&otpc->packets);
@@ -215,6 +300,20 @@ static int mchp_otpc_init_packets_list(struct mchp_otpc *otpc, u32 *size)
 
 		packet->id = id++;
 		packet->offset = word_pos;
+		type = FIELD_GET(MCHP_OTPC_HR_PACKET, word);
+
+		if (type == MCHP_OTPC_HR_PACKET_REGULAR) {
+			ret = mchp_otpc_read_packet_tag(otpc, packet->offset,
+							&packet->tag);
+			if (ret)
+				return ret;
+
+			if (!mchp_otpc_is_valid_fourcc(packet->tag))
+				packet->tag = 0;
+		} else {
+			packet->tag = 0;
+		}
+
 		INIT_LIST_HEAD(&packet->list);
 		list_add_tail(&packet->list, &otpc->packets);
 
@@ -236,7 +335,7 @@ static struct nvmem_config mchp_nvmem_config = {
 	.type = NVMEM_TYPE_OTP,
 	.read_only = true,
 	.word_size = 4,
-	.stride = 4,
+	.stride = 1,
 	.reg_read = mchp_otpc_read,
 };
 
diff --git a/include/dt-bindings/nvmem/microchip,sama7g5-otpc.h b/include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
index f570b23165a2..5f72e75ad091 100644
--- a/include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
+++ b/include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
@@ -4,8 +4,8 @@
 #define _DT_BINDINGS_NVMEM_MICROCHIP_OTPC_H
 
 /*
- * Need to have it as a multiple of 4 as NVMEM memory is registered with
- * stride = 4.
+ * Need to have it as a multiple of 4 for the legacy id based packet
+ * access.
  */
 #define OTP_PKT(id)			((id) * 4)
 
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 09/16] nvmem: microchip-otpc: nvmem: add emulation mode and OTP access validation
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add validation of OTP memory accessibility and emulation mode status
during probe.

When the boot packet is not configured, emulation mode allows access to
the other packets. When both are not available an informational message
is logged to help with debugging.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 drivers/nvmem/microchip-otpc.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/nvmem/microchip-otpc.c b/drivers/nvmem/microchip-otpc.c
index a17f82afdc37..6b0184423463 100644
--- a/drivers/nvmem/microchip-otpc.c
+++ b/drivers/nvmem/microchip-otpc.c
@@ -18,6 +18,7 @@
 #define MCHP_OTPC_CR_READ		BIT(6)
 #define MCHP_OTPC_MR			(0x4)
 #define MCHP_OTPC_MR_ADDR		GENMASK(31, 16)
+#define MCHP_OTPC_MR_EMUL		BIT(7)
 #define MCHP_OTPC_AR			(0x8)
 #define MCHP_OTPC_SR			(0xc)
 #define MCHP_OTPC_SR_READ		BIT(6)
@@ -343,7 +344,8 @@ static int mchp_otpc_probe(struct platform_device *pdev)
 {
 	struct nvmem_device *nvmem;
 	struct mchp_otpc *otpc;
-	u32 size;
+	bool emul_enable;
+	u32 size, mr_val;
 	int ret;
 
 	otpc = devm_kzalloc(&pdev->dev, sizeof(*otpc), GFP_KERNEL);
@@ -355,10 +357,22 @@ static int mchp_otpc_probe(struct platform_device *pdev)
 		return PTR_ERR(otpc->base);
 
 	otpc->dev = &pdev->dev;
+
+	mr_val = readl_relaxed(otpc->base + MCHP_OTPC_MR);
+	emul_enable = mr_val & MCHP_OTPC_MR_EMUL;
+	if (emul_enable)
+		dev_info(otpc->dev, "Emulation mode enabled\n");
+
 	ret = mchp_otpc_init_packets_list(otpc, &size);
 	if (ret)
 		return ret;
 
+	if (!size) {
+		dev_warn(otpc->dev, "Cannot access OTP memory\n");
+		if (!emul_enable)
+			dev_info(otpc->dev, "Boot packet not programmed and emulation mode disabled\n");
+	}
+
 	mchp_nvmem_config.dev = otpc->dev;
 	mchp_nvmem_config.add_legacy_fixed_of_cells = true;
 	mchp_nvmem_config.size = size;
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 07/16] dt-bindings: nvmem: microchip,sama7g5-otpc: add sama7d65 and dt node example
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
  Cc: Conor Dooley
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add support for sama7d65 and a dt node example that shows tag can be used
to reference a packet stored in the OTP memory.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
 .../nvmem/microchip,sama7g5-otpc.yaml         | 28 +++++++++++++++++--
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml b/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
index cc25f2927682..04b44660554e 100644
--- a/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
+++ b/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
@@ -20,9 +20,15 @@ allOf:
 
 properties:
   compatible:
-    items:
-      - const: microchip,sama7g5-otpc
-      - const: syscon
+    oneOf:
+      - items:
+          - const: microchip,sama7g5-otpc
+          - const: syscon
+      - items:
+          - enum:
+              - microchip,sama7d65-otpc
+          - const: microchip,sama7g5-otpc
+          - const: syscon
 
   reg:
     maxItems: 1
@@ -48,4 +54,20 @@ examples:
         };
     };
 
+  - |
+    efuse@e8c00000 {
+        compatible = "microchip,sama7d65-otpc", "microchip,sama7g5-otpc", "syscon";
+        reg = <0xe8c00000 0x100>;
+
+        nvmem-layout {
+            compatible = "fixed-layout";
+            #address-cells = <1>;
+            #size-cells = <1>;
+
+            calib@41435354 {
+                reg = <0x41435354 0x2c>;    /* Temp calib data packet TAG */
+            };
+        };
+    };
+
 ...
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 06/16] iio: adc: at91-sama5d2_adc: adapt the driver for sama7d65
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add support for sama7d65 ADC. The differences are highlighted with the
compatible. The calibration data layout is the main difference.

Update Kconfig help text to mention SAMA7 SoC family support.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 drivers/iio/adc/Kconfig            |  2 +-
 drivers/iio/adc/at91-sama5d2_adc.c | 30 ++++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 3755a81c1efd..85b443853a08 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -647,7 +647,7 @@ config AT91_SAMA5D2_ADC
 	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for Atmel SAMA5D2 ADC which is
-	  available on SAMA5D2 SoC family.
+	  available on SAMA5D2 and SAMA7 SoC families.
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called at91-sama5d2_adc.
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 63481ecb94f5..a54691b38244 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -530,6 +530,15 @@ static const struct at91_adc_temp_calib_layout sama7g5_temp_calib = {
 	.p1_scale = { .numerator = 1000, .denominator = 1 },
 };
 
+static const struct at91_adc_temp_calib_layout sama7d65_temp_calib = {
+	.tag_idx = 1,
+	.p1_idx = 3,
+	.p4_idx = 2,
+	.p6_idx = 5,
+	.min_len = 11,
+	.p1_scale = { .numerator = 1, .denominator = 1000 },
+};
+
 /* Temperature sensor calibration - Vtemp voltage sensitivity to temperature. */
 #define AT91_ADC_TS_VTEMP_DT		(2080U)
 
@@ -768,6 +777,24 @@ static const struct at91_adc_platform sama7g5_platform = {
 	.temp_calib_layout = &sama7g5_temp_calib,
 };
 
+static const struct at91_adc_platform sama7d65_platform = {
+	.layout = &sama7g5_layout,
+	.adc_channels = &at91_sama7g5_adc_channels,
+	.nr_channels = AT91_SAMA7G5_SINGLE_CHAN_CNT +
+		       AT91_SAMA7G5_DIFF_CHAN_CNT +
+		       AT91_SAMA7G5_TEMP_CHAN_CNT,
+	.max_channels = ARRAY_SIZE(at91_sama7g5_adc_channels),
+	.max_index = AT91_SAMA7G5_MAX_CHAN_IDX,
+	.hw_trig_cnt = AT91_SAMA7G5_HW_TRIG_CNT,
+	.osr_mask = GENMASK(18, 16),
+	.oversampling_avail = { 1, 4, 16, 64, 256 },
+	.oversampling_avail_no = 5,
+	.chan_realbits = 16,
+	.temp_sensor = true,
+	.temp_chan = AT91_SAMA7G5_ADC_TEMP_CHANNEL,
+	.temp_calib_layout = &sama7d65_temp_calib,
+};
+
 static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan)
 {
 	int i;
@@ -2632,6 +2659,9 @@ static const struct of_device_id at91_adc_dt_match[] = {
 	}, {
 		.compatible = "microchip,sama7g5-adc",
 		.data = &sama7g5_platform,
+	}, {
+		.compatible = "microchip,sama7d65-adc",
+		.data = &sama7d65_platform,
 	}, {
 		/* sentinel */
 	}
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 05/16] iio: adc: at91-sama5d2_adc: remove unnecessary casts in of_device_id
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

The .data field in struct of_device_id is 'const void *', so explicit
casts are unnecessary when assigning addresses of const structs.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 drivers/iio/adc/at91-sama5d2_adc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 15dc88f4961b..63481ecb94f5 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -2628,10 +2628,10 @@ static const struct dev_pm_ops at91_adc_pm_ops = {
 static const struct of_device_id at91_adc_dt_match[] = {
 	{
 		.compatible = "atmel,sama5d2-adc",
-		.data = (const void *)&sama5d2_platform,
+		.data = &sama5d2_platform,
 	}, {
 		.compatible = "microchip,sama7g5-adc",
-		.data = (const void *)&sama7g5_platform,
+		.data = &sama7g5_platform,
 	}, {
 		/* sentinel */
 	}
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 03/16] iio: adc: at91-sama5d2_adc: rework temp calibration layout handling
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Extend support to handle different temperature calibration layouts.

Add a temperature calibration data layout structure to describe indexes
of the factors P1, P4, P6, tag, minimum length of the packet and the
scaling factors for P1 (p1_scale) which are SoC-specific instead of the
older non scalable id structure. This helps handle the differences in the
same function flow and prepare the calibration data to be applied.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 drivers/iio/adc/at91-sama5d2_adc.c | 66 ++++++++++++++++++++++--------
 1 file changed, 48 insertions(+), 18 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 4a4a25f3c715..798e4d60bf69 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -16,6 +16,7 @@
 #include <linux/dmaengine.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/math.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
@@ -446,6 +447,27 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
 #define at91_adc_writel(st, reg, val)					\
 	writel_relaxed(val, (st)->base + (st)->soc_info.platform->layout->reg)
 
+/* Temperature calibration tag "ACST" in ASCII */
+#define AT91_TEMP_CALIB_TAG_ACST	0x41435354
+
+/**
+ * struct at91_adc_temp_calib_layout - temperature calibration packet layout
+ * @tag_idx:	index of Packet tag in the NVMEM cell buffer
+ * @p1_idx:	index of FT1_TEMP, equivalent to P1 in the NVMEM cell buffer
+ * @p4_idx:	index of FT1_VPAT, equivalent to P4 in the NVMEM cell buffer
+ * @p6_idx:	index of FT2_VBG, equivalent to P6 in the NVMEM cell buffer
+ * @min_len:	minimum number of u32 words expected in the NVMEM cell buffer
+ * @p1_scale:	scaling factor applied to P1 to convert to millicelcius
+ */
+struct at91_adc_temp_calib_layout {
+	unsigned int tag_idx;
+	unsigned int p1_idx;
+	unsigned int p4_idx;
+	unsigned int p6_idx;
+	unsigned int min_len;
+	struct u32_fract p1_scale;
+};
+
 /**
  * struct at91_adc_platform - at91-sama5d2 platform information struct
  * @layout:		pointer to the reg layout struct
@@ -464,6 +486,7 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
  * @oversampling_avail_no: number of available oversampling values
  * @chan_realbits:	realbits for registered channels
  * @temp_chan:		temperature channel index
+ * @temp_calib_layout:	temperature calibration packet layout
  * @temp_sensor:	temperature sensor supported
  */
 struct at91_adc_platform {
@@ -481,6 +504,7 @@ struct at91_adc_platform {
 	unsigned int				oversampling_avail_no;
 	unsigned int				chan_realbits;
 	unsigned int				temp_chan;
+	const struct at91_adc_temp_calib_layout	*temp_calib_layout;
 	bool					temp_sensor;
 };
 
@@ -497,18 +521,13 @@ struct at91_adc_temp_sensor_clb {
 	u32 p6;
 };
 
-/**
- * enum at91_adc_ts_clb_idx - calibration indexes in NVMEM buffer
- * @AT91_ADC_TS_CLB_IDX_P1: index for P1
- * @AT91_ADC_TS_CLB_IDX_P4: index for P4
- * @AT91_ADC_TS_CLB_IDX_P6: index for P6
- * @AT91_ADC_TS_CLB_IDX_MAX: max index for temperature calibration packet in OTP
- */
-enum at91_adc_ts_clb_idx {
-	AT91_ADC_TS_CLB_IDX_P1 = 2,
-	AT91_ADC_TS_CLB_IDX_P4 = 5,
-	AT91_ADC_TS_CLB_IDX_P6 = 7,
-	AT91_ADC_TS_CLB_IDX_MAX = 19,
+static const struct at91_adc_temp_calib_layout sama7g5_temp_calib = {
+	.tag_idx = 1,
+	.p1_idx = 2,
+	.p4_idx = 5,
+	.p6_idx = 7,
+	.min_len = 19,
+	.p1_scale = { .numerator = 1000, .denominator = 1 },
 };
 
 /* Temperature sensor calibration - Vtemp voltage sensitivity to temperature. */
@@ -746,6 +765,7 @@ static const struct at91_adc_platform sama7g5_platform = {
 	.chan_realbits = 16,
 	.temp_sensor = true,
 	.temp_chan = AT91_SAMA7G5_ADC_TEMP_CHANNEL,
+	.temp_calib_layout = &sama7g5_temp_calib,
 };
 
 static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan)
@@ -2251,11 +2271,18 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
 				     struct device *dev)
 {
 	struct at91_adc_temp_sensor_clb *clb = &st->soc_info.temp_sensor_clb;
+	const struct at91_adc_temp_calib_layout *layout;
 	size_t len;
 
 	if (!st->soc_info.platform->temp_sensor)
 		return 0;
 
+	layout = st->soc_info.platform->temp_calib_layout;
+	if (!layout)
+		return -ENODEV;
+	if (!layout->p1_scale.denominator)
+		return -EINVAL;
+
 	/* Get the calibration data from NVMEM. */
 	struct nvmem_cell *temp_calib __free(nvmem_cell_put) =
 		nvmem_cell_get(dev, "temperature_calib");
@@ -2270,20 +2297,23 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
 		return dev_err_probe(dev, PTR_ERR(buf),
 				     "Failed to read calibration data!\n");
 
-	if (len < AT91_ADC_TS_CLB_IDX_MAX * sizeof(*buf)) {
+	if (len < layout->min_len * sizeof(*buf)) {
 		dev_err(dev, "Invalid calibration data!\n");
 		return -EINVAL;
 	}
 
 	/* Store calibration data for later use. */
-	clb->p1 = buf[AT91_ADC_TS_CLB_IDX_P1];
-	clb->p4 = buf[AT91_ADC_TS_CLB_IDX_P4];
-	clb->p6 = buf[AT91_ADC_TS_CLB_IDX_P6];
+	clb->p1 = buf[layout->p1_idx];
+	clb->p4 = buf[layout->p4_idx];
+	clb->p6 = buf[layout->p6_idx];
 
 	/*
-	 * We prepare here the conversion to milli to avoid doing it on hotpath.
+	 * Here we prepare the conversion to milli to avoid doing it on hotpath.
+	 * The p1 value is multiplied and divided with a scaling factor as per
+	 * the SoC storage format described by per-platform calibration layout.
 	 */
-	clb->p1 = clb->p1 * 1000;
+	clb->p1 *= layout->p1_scale.numerator;
+	clb->p1 /= layout->p1_scale.denominator;
 
 	return 0;
 }
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 04/16] iio: adc: at91-sama5d2_adc: add condition to validate calibration data
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add additional condition to validate the calibration data read from the
NVMEM cell using the TAG of the packet.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 drivers/iio/adc/at91-sama5d2_adc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 798e4d60bf69..15dc88f4961b 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -2297,7 +2297,8 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
 		return dev_err_probe(dev, PTR_ERR(buf),
 				     "Failed to read calibration data!\n");
 
-	if (len < layout->min_len * sizeof(*buf)) {
+	if (len < layout->min_len * sizeof(*buf) ||
+	    buf[layout->tag_idx] != AT91_TEMP_CALIB_TAG_ACST) {
 		dev_err(dev, "Invalid calibration data!\n");
 		return -EINVAL;
 	}
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 02/16] iio: adc: at91-sama5d2_adc: use cleanup.h for NVMEM buffer
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
  Cc: Andy Shevchenko
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Use __free(kfree) and __free(nvmem_cell_put) cleanup helpers in
at91_adc_temp_sensor_init() to simplify error handling paths.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
 drivers/iio/adc/at91-sama5d2_adc.c | 33 +++++++++++++-----------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index e8a5285bb6d4..4a4a25f3c715 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -35,6 +35,8 @@
 
 #include <dt-bindings/iio/adc/at91-sama5d2_adc.h>
 
+DEFINE_FREE(nvmem_cell_put, struct nvmem_cell *, if (_T) nvmem_cell_put(_T))
+
 struct at91_adc_reg_layout {
 /* Control Register */
 	u16				CR;
@@ -2249,33 +2251,28 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
 				     struct device *dev)
 {
 	struct at91_adc_temp_sensor_clb *clb = &st->soc_info.temp_sensor_clb;
-	struct nvmem_cell *temp_calib;
-	u32 *buf;
 	size_t len;
-	int ret = 0;
 
 	if (!st->soc_info.platform->temp_sensor)
 		return 0;
 
 	/* Get the calibration data from NVMEM. */
-	temp_calib = nvmem_cell_get(dev, "temperature_calib");
+	struct nvmem_cell *temp_calib __free(nvmem_cell_put) =
+		nvmem_cell_get(dev, "temperature_calib");
 	if (IS_ERR(temp_calib)) {
-		ret = PTR_ERR(temp_calib);
-		if (ret != -ENOENT)
+		if (PTR_ERR(temp_calib) != -ENOENT)
 			dev_err(dev, "Failed to get temperature_calib cell!\n");
-		return ret;
+		return PTR_ERR(temp_calib);
 	}
 
-	buf = nvmem_cell_read(temp_calib, &len);
-	nvmem_cell_put(temp_calib);
-	if (IS_ERR(buf)) {
-		dev_err(dev, "Failed to read calibration data!\n");
-		return PTR_ERR(buf);
-	}
-	if (len < AT91_ADC_TS_CLB_IDX_MAX * 4) {
+	u32 *buf __free(kfree) = nvmem_cell_read(temp_calib, &len);
+	if (IS_ERR(buf))
+		return dev_err_probe(dev, PTR_ERR(buf),
+				     "Failed to read calibration data!\n");
+
+	if (len < AT91_ADC_TS_CLB_IDX_MAX * sizeof(*buf)) {
 		dev_err(dev, "Invalid calibration data!\n");
-		ret = -EINVAL;
-		goto free_buf;
+		return -EINVAL;
 	}
 
 	/* Store calibration data for later use. */
@@ -2288,9 +2285,7 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
 	 */
 	clb->p1 = clb->p1 * 1000;
 
-free_buf:
-	kfree(buf);
-	return ret;
+	return 0;
 }
 
 static int at91_adc_probe(struct platform_device *pdev)
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 00/16] Add thermal management support for sama7d65
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel

Thermal management system of sama7d65 includes:

- Temperature sensor as a part of ADC channel
- Temperature calibration data retrieved from the OTP memory for
  improved accuracy of the readings
- DVFS implementation
- Thermal system with DVFS as cooling cell.

This patch series adds support for the following:

- Tag-based packet lookup for the NVMEM OTPC driver while preserving
  backward compatibility with existing ID-based access
- Temperature calibration layout handling in the ADC driver to support
  different SoC-specific calibration data formats
- ADC driver adaptation for sama7d65
- DT nodes for OTP, ADC, temperature sensor, and thermal zones for
  sama7d65

Changes in v4:
	- Reworked cleanup.h usage: define and assign __free() variables at point
	  of use after early returns, add DEFINE_FREE(nvmem_cell_put, ...) for
	  nvmem_cell cleanup
	- Split patch 3/13 into two: refactoring (layout struct) and tag validation
	- Used struct u32_fract for p1 scaling factors
	- Return -ENODEV instead of -EINVAL when layout is missing
	- New precursor patch to remove unnecessary casts in of_device_id
	- Removed trailing comma from single-line initializer array
	- Moved emulation mode validation into a separate patch
	- Added FourCC validation for packet tags; invalid tags fall back to ID-only
	  access
	- Mentioned FourCC in commit message and comments
	- Used intermediate variable for off % 4
	- Rename tmp → mr_val, val→ tag
	- Addressed style issues: Removed comment blocks, put functions in
	  one line
	- Remove blank line after compatible in regulator node
	- Reorder properties.

Link to v3: https://lore.kernel.org/lkml/20260630093603.38663-1-varshini.rajendran@microchip.com/

Changes in v3:
    - Updated the commit message with reasoning for a new compatible
      without a fallback (sama7d65-adc)
    - Split patch 2/12 into two patches: a patch with cleanup.h changes only
      and the rework patch
    - Added comment explaining the TAG ACST
    - Fixed the holes identified in the at91_adc_platform struct by
      pahole tool
    - Dropped labels in the dt document example
    - Added temp variable in mchp_otpc_resolve_packet() to avoid % and /
      operations in the same instruction (avoiding compiler optimization)
    - Added the SoC details in the ADC driver Kconfig help section
    - Maintained reverse xmas ordering in declarations
    - Fixed node ordering (alphabetically) in the board dts file

Link to v2: https://lore.kernel.org/lkml/20260623105944.128840-1-varshini.rajendran@microchip.com/

Changes in v2:
    - Preserved backward compatibility with ID-based packet lookup to
      avoid breaking existing users
    - Removed sama7g5 DTS changes (not needed with backward compatible
      driver - will be sent later to update to the new access method)
    - Preserved the packet data structure returned not to break the
      consumers
    - Reworked ADC driver to use a calibration layout structure instead of
      hardcoded indexes, for scalability
    - Fixed kernel-doc Return section
    - Removed stray blank line in mchp_otpc_read()
    - Removed unnecessary UL suffix in writel_relaxed()
    - Dropped unused packet types
    - Fixed stray spaces before exclamation marks in error messages
    - Added ASCII representation to TAG macro definition
    - Removed odd MAX enum with trailing comma and refactored
    - Moved DTS patches to the end of series
    - Used cleanup.h helpers for NVMEM data buffer handling in ADC driver
    - Combined multiple v1 patches into logical units
    - Used correct subject prefixes for dt-bindings patches
    - Used fixed-layout NVMEM syntax for sama7d65 DTS and binding
      instead of deprecated syntax
    - Added cpu-supply linkage for proper DVFS voltage scaling
    - Updated stale stride=4 comment in dt-bindings header

Link to v1: https://lore.kernel.org/linux-arm-kernel/20250804100219.63325-1-varshini.rajendran@microchip.com/



Varshini Rajendran (16):
  dt-bindings: iio: adc: at91-sama5d2: document sama7d65
  iio: adc: at91-sama5d2_adc: use cleanup.h for NVMEM buffer
  iio: adc: at91-sama5d2_adc: rework temp calibration layout handling
  iio: adc: at91-sama5d2_adc: add condition to validate calibration data
  iio: adc: at91-sama5d2_adc: remove unnecessary casts in of_device_id
  iio: adc: at91-sama5d2_adc: adapt the driver for sama7d65
  dt-bindings: nvmem: microchip,sama7g5-otpc: add sama7d65 and dt node
    example
  nvmem: microchip-otpc: nvmem: microchip-otpc: add tag-based packet
    lookup
  nvmem: microchip-otpc: nvmem: add emulation mode and OTP access
    validation
  ARM: dts: microchip: sama7d65: add cpu opps
  ARM: dts: microchip: sama7d65: Add ADC node
  ARM: dts: microchip: sama7d65_curiosity: Enable ADC, DVFS
  ARM: dts: microchip: sama7d65: add otpc node
  ARM: dts: microchip: sama7d65: add cells for temperature calibration
  ARM: dts: microchip: sama7d65: add temperature sensor
  ARM: dts: microchip: sama7d65: add thermal zones node

 .../bindings/iio/adc/atmel,sama5d2-adc.yaml   |   1 +
 .../nvmem/microchip,sama7g5-otpc.yaml         |  28 +++-
 .../dts/microchip/at91-sama7d65_curiosity.dts |  27 ++++
 arch/arm/boot/dts/microchip/sama7d65.dtsi     | 131 +++++++++++++++++
 drivers/iio/adc/Kconfig                       |   2 +-
 drivers/iio/adc/at91-sama5d2_adc.c            | 132 ++++++++++++-----
 drivers/nvmem/microchip-otpc.c                | 133 ++++++++++++++++--
 .../nvmem/microchip,sama7g5-otpc.h            |   4 +-
 8 files changed, 404 insertions(+), 54 deletions(-)

-- 
2.34.1



^ permalink raw reply

* [PATCH v4 01/16] dt-bindings: iio: adc: at91-sama5d2: document sama7d65
From: Varshini Rajendran @ 2026-07-27 12:26 UTC (permalink / raw)
  To: ehristev, jic23, dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt,
	nicolas.ferre, alexandre.belloni, claudiu.beznea, srini,
	marcelo.schmitt, radu.sabau, Jonathan.Santos, jorge.marques,
	joshua.crofts1, jishnu.prakash, antoniu.miclaus,
	varshini.rajendran, mazziesaccount, linux-iio, devicetree,
	linux-arm-kernel, linux-kernel
  Cc: Krzysztof Kozlowski
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>

Add dt-binding documentation for sama7d65 ADC.

sama7d65 requires an individual compatible to address the differences
from its predecessor sama7g5. The main difference is the temperature
calibration layout and its handling.

Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml b/Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml
index 4817b840977a..e8a65fdcd018 100644
--- a/Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml
@@ -15,6 +15,7 @@ properties:
       - atmel,sama5d2-adc
       - microchip,sam9x60-adc
       - microchip,sama7g5-adc
+      - microchip,sama7d65-adc
 
   reg:
     maxItems: 1
-- 
2.34.1



^ permalink raw reply related

* [RFC PATCH 5/9] arm64/kprobes: Invoke pre/post handlers inside instrumentation
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>

From: Hongyan Xia <hongyan.xia@transsion.com>

The kprobe pre_handler() and post_handler() are arbitrary instrumentable
code and can themselves trace, fault, or hit other kprobes. They are
the only parts of the kprobe debug exception flow that legitimately
need instrumentation.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/include/asm/kprobes.h   |  9 +++------
 arch/arm64/kernel/probes/kprobes.c | 22 ++++++++++++++++++----
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 35ce2c94040e..a694f7d34f45 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -48,11 +48,8 @@ void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
 #endif /* CONFIG_KPROBES */
 
-int __kprobes kprobe_brk_handler(struct pt_regs *regs,
-				 unsigned long esr);
-int __kprobes kprobe_ss_brk_handler(struct pt_regs *regs,
-				 unsigned long esr);
-int __kprobes kretprobe_brk_handler(struct pt_regs *regs,
-				 unsigned long esr);
+int noinstr kprobe_brk_handler(struct pt_regs *regs, unsigned long esr);
+int noinstr kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr);
+int noinstr kretprobe_brk_handler(struct pt_regs *regs, unsigned long esr);
 
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 1b12341b2af3..e9fa66fa4217 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -301,8 +301,11 @@ post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_reg
 	}
 	/* call post handler */
 	kcb->kprobe_status = KPROBE_HIT_SSDONE;
+
+	instrumentation_begin();
 	if (cur->post_handler)
 		cur->post_handler(cur, regs, 0);
+	instrumentation_end();
 
 	reset_current_kprobe();
 }
@@ -359,24 +362,28 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
 	return 0;
 }
 
-int __kprobes
+int noinstr
 kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 {
 	struct kprobe *p, *cur_kprobe;
 	struct kprobe_ctlblk *kcb;
 	unsigned long addr = instruction_pointer(regs);
+	bool handled;
 
 	kcb = get_kprobe_ctlblk();
 	cur_kprobe = kprobe_running();
 
+	instrumentation_begin();
 	p = get_kprobe((kprobe_opcode_t *) addr);
 	if (WARN_ON_ONCE(!p)) {
+		instrumentation_end();
 		/*
 		 * Something went wrong. This BRK used an immediate reserved
 		 * for kprobes, but we couldn't find any corresponding probe.
 		 */
 		return DBG_HOOK_ERROR;
 	}
+	instrumentation_end();
 
 	if (cur_kprobe) {
 		/* Hit a kprobe inside another kprobe */
@@ -387,6 +394,10 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 		set_current_kprobe(p);
 		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
+		instrumentation_begin();
+		handled = p->pre_handler && p->pre_handler(p, regs);
+		instrumentation_end();
+
 		/*
 		 * If we have no pre-handler or it returned 0, we
 		 * continue with normal processing.  If we have a
@@ -394,7 +405,7 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 		 * modify the execution path and not need to single-step
 		 * Let's just reset current kprobe and exit.
 		 */
-		if (!p->pre_handler || !p->pre_handler(p, regs))
+		if (!handled)
 			setup_singlestep(p, regs, kcb, 0);
 		else
 			reset_current_kprobe();
@@ -403,7 +414,7 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 	return DBG_HOOK_HANDLED;
 }
 
-int __kprobes
+int noinstr
 kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr)
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -422,13 +433,16 @@ kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr)
 	return DBG_HOOK_ERROR;
 }
 
-int __kprobes
+int noinstr
 kretprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 {
 	if (regs->pc != (unsigned long)__kretprobe_trampoline)
 		return DBG_HOOK_ERROR;
 
+	instrumentation_begin();
 	regs->pc = kretprobe_trampoline_handler(regs, (void *)regs->regs[29]);
+	instrumentation_end();
+
 	return DBG_HOOK_HANDLED;
 }
 
-- 
2.47.3



^ permalink raw reply related

* [RFC PATCH 4/9] arm64/kprobes: Make the single-step machinery noinstr
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>

From: Hongyan Xia <hongyan.xia@transsion.com>

Convert the core of the arm64 kprobe single-step flow to noinstr:
save_previous_kprobe(), restore_previous_kprobe(), set_current_kprobe(),
kprobes_save_local_irqflag(), kprobes_restore_local_irqflag(),
setup_singlestep(), reenter_kprobe() and post_kprobe_handler().

These functions only touch per-cpu state, pt_regs and DAIF, except for:

- kprobes_inc_nmissed_count(), which is generic and instrumentable; add
  an arm64-local wrapper that calls it bounded by
  instrumentation_begin()/end();
- the instruction simulation path in setup_singlestep(), whose decode
  handlers are instrumentable; bound arch_simulate_insn() with an
  instrumentation window;
- the unrecoverable-reentry pr_warn()/dump_kprobe()/BUG() path and the
  default WARN_ON(), both bounded with instrumentation windows.

The __kprobes attribute (notrace + .kprobes.text) is replaced by
noinstr, which is a strict superset for these functions.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/kernel/probes/kprobes.c | 39 ++++++++++++++++++------------
 1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 4e0efad5caf2..1b12341b2af3 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -14,6 +14,7 @@
 #include <linux/extable.h>
 #include <linux/kasan.h>
 #include <linux/kernel.h>
+#include <linux/instrumentation.h>
 #include <linux/kprobes.h>
 #include <linux/sched/debug.h>
 #include <linux/set_memory.h>
@@ -39,7 +40,7 @@
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
-static void __kprobes
+static void noinstr
 post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *);
 
 void *alloc_insn_page(void)
@@ -170,7 +171,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
 	}
 }
 
-static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void noinstr save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -184,7 +185,7 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 	kcb->prev_kprobe.saved_irqflag = kcb->saved_irqflag;
 }
 
-static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void noinstr restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
 	kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -197,7 +198,7 @@ static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 	kcb->saved_irqflag = kcb->prev_kprobe.saved_irqflag;
 }
 
-static void __kprobes set_current_kprobe(struct kprobe *p)
+static void noinstr set_current_kprobe(struct kprobe *p)
 {
 	__this_cpu_write(current_kprobe, p);
 }
@@ -207,23 +208,23 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
  * simple and avoid nesting exceptions. Interrupts do have to be disabled since
  * the kprobe state is per-CPU and doesn't get migrated.
  */
-static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
-						struct pt_regs *regs)
+static void noinstr kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
+					       struct pt_regs *regs)
 {
 	kcb->saved_irqflag = regs->pstate & DAIF_MASK;
 	regs->pstate |= DAIF_MASK;
 }
 
-static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
-						struct pt_regs *regs)
+static void noinstr kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
+						  struct pt_regs *regs)
 {
 	regs->pstate &= ~DAIF_MASK;
 	regs->pstate |= kcb->saved_irqflag;
 }
 
-static void __kprobes setup_singlestep(struct kprobe *p,
-				       struct pt_regs *regs,
-				       struct kprobe_ctlblk *kcb, int reenter)
+static void noinstr setup_singlestep(struct kprobe *p,
+				     struct pt_regs *regs,
+				     struct kprobe_ctlblk *kcb, int reenter)
 {
 	unsigned long slot;
 
@@ -244,13 +245,15 @@ static void __kprobes setup_singlestep(struct kprobe *p,
 		instruction_pointer_set(regs, slot);
 	} else {
 		/* insn simulation */
+		instrumentation_begin();
 		arch_simulate_insn(p, regs);
+		instrumentation_end();
 	}
 }
 
-static int __kprobes reenter_kprobe(struct kprobe *p,
-				    struct pt_regs *regs,
-				    struct kprobe_ctlblk *kcb)
+static int noinstr reenter_kprobe(struct kprobe *p,
+				  struct pt_regs *regs,
+				  struct kprobe_ctlblk *kcb)
 {
 	switch (kcb->kprobe_status) {
 	case KPROBE_HIT_SSDONE:
@@ -262,23 +265,29 @@ static int __kprobes reenter_kprobe(struct kprobe *p,
 		 * recoverable one-level reentry, so handle it in the same way as
 		 * reentry from KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE.
 		 */
+		instrumentation_begin();
 		kprobes_inc_nmissed_count(p);
+		instrumentation_end();
 		setup_singlestep(p, regs, kcb, 1);
 		break;
 	case KPROBE_REENTER:
+		instrumentation_begin();
 		pr_warn("Failed to recover from reentered kprobes.\n");
 		dump_kprobe(p);
 		BUG();
+		instrumentation_end();
 		break;
 	default:
+		instrumentation_begin();
 		WARN_ON(1);
+		instrumentation_end();
 		return 0;
 	}
 
 	return 1;
 }
 
-static void __kprobes
+static void noinstr
 post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_regs *regs)
 {
 	/* return addr restore if non-branching insn */
-- 
2.47.3



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox