File Index
Files and directories
Sign in
FILE

airoha-cpu-pmdomain.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <linux/arm-smccc.h>
  4#include <linux/bitfield.h>
  5#include <linux/clk-provider.h>
  6#include <linux/module.h>
  7#include <linux/platform_device.h>
  8#include <linux/pm_domain.h>
  9#include <linux/slab.h>
 10
 11#define AIROHA_SIP_AVS_HANDLE			0x82000301
 12#define AIROHA_AVS_OP_BASE			0xddddddd0
 13#define AIROHA_AVS_OP_MASK			GENMASK(1, 0)
 14#define AIROHA_AVS_OP_FREQ_DYN_ADJ		(AIROHA_AVS_OP_BASE | \
 15						 FIELD_PREP(AIROHA_AVS_OP_MASK, 0x1))
 16#define AIROHA_AVS_OP_GET_FREQ			(AIROHA_AVS_OP_BASE | \
 17						 FIELD_PREP(AIROHA_AVS_OP_MASK, 0x2))
 18
 19struct airoha_cpu_pmdomain_priv {
 20	struct clk_hw hw;
 21	struct generic_pm_domain pd;
 22};
 23
 24static int airoha_cpu_pmdomain_clk_determine_rate(struct clk_hw *hw,
 25						  struct clk_rate_request *req)
 26{
 27	return 0;
 28}
 29
 30static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw,
 31						 unsigned long parent_rate)
 32{
 33	struct arm_smccc_res res;
 34
 35	arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_GET_FREQ,
 36			     0, 0, 0, 0, 0, 0, &res);
 37
 38	/* SMCCC returns freq in MHz */
 39	return (int)(res.a0 * 1000 * 1000);
 40}
 41
 42/* Airoha CPU clk SMCC is always enabled */
 43static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw)
 44{
 45	return true;
 46}
 47
 48static const struct clk_ops airoha_cpu_pmdomain_clk_ops = {
 49	.recalc_rate = airoha_cpu_pmdomain_clk_get,
 50	.is_enabled = airoha_cpu_pmdomain_clk_is_enabled,
 51	.determine_rate = airoha_cpu_pmdomain_clk_determine_rate,
 52};
 53
 54static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain,
 55						     unsigned int state)
 56{
 57	struct arm_smccc_res res;
 58
 59	arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_FREQ_DYN_ADJ,
 60			     0, state, 0, 0, 0, 0, &res);
 61
 62	/* SMC signal correct apply by unsetting BIT 0 */
 63	return res.a0 & BIT(0) ? -EINVAL : 0;
 64}
 65
 66static int airoha_cpu_pmdomain_probe(struct platform_device *pdev)
 67{
 68	struct airoha_cpu_pmdomain_priv *priv;
 69	struct device *dev = &pdev->dev;
 70	const struct clk_init_data init = {
 71		.name = "cpu",
 72		.ops = &airoha_cpu_pmdomain_clk_ops,
 73		/* Clock with no set_rate, can't cache */
 74		.flags = CLK_GET_RATE_NOCACHE,
 75	};
 76	struct generic_pm_domain *pd;
 77	int ret;
 78
 79	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 80	if (!priv)
 81		return -ENOMEM;
 82
 83	/* Init and register a get-only clk for Cpufreq */
 84	priv->hw.init = &init;
 85	ret = devm_clk_hw_register(dev, &priv->hw);
 86	if (ret)
 87		return ret;
 88
 89	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
 90					  &priv->hw);
 91	if (ret)
 92		return ret;
 93
 94	/* Init and register a PD for CPU */
 95	pd = &priv->pd;
 96	pd->name = "cpu_pd";
 97	pd->flags = GENPD_FLAG_ALWAYS_ON;
 98	pd->set_performance_state = airoha_cpu_pmdomain_set_performance_state;
 99
100	ret = pm_genpd_init(pd, NULL, false);
101	if (ret)
102		return ret;
103
104	ret = of_genpd_add_provider_simple(dev->of_node, pd);
105	if (ret)
106		goto err_add_provider;
107
108	platform_set_drvdata(pdev, priv);
109
110	return 0;
111
112err_add_provider:
113	pm_genpd_remove(pd);
114
115	return ret;
116}
117
118static void airoha_cpu_pmdomain_remove(struct platform_device *pdev)
119{
120	struct airoha_cpu_pmdomain_priv *priv = platform_get_drvdata(pdev);
121
122	of_genpd_del_provider(pdev->dev.of_node);
123	pm_genpd_remove(&priv->pd);
124}
125
126static const struct of_device_id airoha_cpu_pmdomain_of_match[] = {
127	{ .compatible = "airoha,en7581-cpufreq" },
128	{ },
129};
130MODULE_DEVICE_TABLE(of, airoha_cpu_pmdomain_of_match);
131
132static struct platform_driver airoha_cpu_pmdomain_driver = {
133	.probe = airoha_cpu_pmdomain_probe,
134	.remove = airoha_cpu_pmdomain_remove,
135	.driver = {
136		.name = "airoha-cpu-pmdomain",
137		.of_match_table = airoha_cpu_pmdomain_of_match,
138	},
139};
140module_platform_driver(airoha_cpu_pmdomain_driver);
141
142MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
143MODULE_DESCRIPTION("CPU PM domain driver for Airoha SoCs");
144MODULE_LICENSE("GPL");
~/ Read-only file preview.