File Index
Files and directories
Sign in
FILE

spc.c

File preview with syntax highlighting.

linux-6.19.14/arch/arm/mach-versatile/spc.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Versatile Express Serial Power Controller (SPC) support
  4 *
  5 * Copyright (C) 2013 ARM Ltd.
  6 *
  7 * Authors: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
  8 *          Achin Gupta           <achin.gupta@arm.com>
  9 *          Lorenzo Pieralisi     <lorenzo.pieralisi@arm.com>
 10 */
 11
 12#include <linux/clk-provider.h>
 13#include <linux/clkdev.h>
 14#include <linux/cpu.h>
 15#include <linux/delay.h>
 16#include <linux/err.h>
 17#include <linux/interrupt.h>
 18#include <linux/io.h>
 19#include <linux/platform_device.h>
 20#include <linux/pm_opp.h>
 21#include <linux/slab.h>
 22#include <linux/semaphore.h>
 23
 24#include <asm/cacheflush.h>
 25
 26#include "spc.h"
 27
 28#define SPCLOG "vexpress-spc: "
 29
 30#define PERF_LVL_A15		0x00
 31#define PERF_REQ_A15		0x04
 32#define PERF_LVL_A7		0x08
 33#define PERF_REQ_A7		0x0c
 34#define COMMS			0x10
 35#define COMMS_REQ		0x14
 36#define PWC_STATUS		0x18
 37#define PWC_FLAG		0x1c
 38
 39/* SPC wake-up IRQs status and mask */
 40#define WAKE_INT_MASK		0x24
 41#define WAKE_INT_RAW		0x28
 42#define WAKE_INT_STAT		0x2c
 43/* SPC power down registers */
 44#define A15_PWRDN_EN		0x30
 45#define A7_PWRDN_EN		0x34
 46/* SPC per-CPU mailboxes */
 47#define A15_BX_ADDR0		0x68
 48#define A7_BX_ADDR0		0x78
 49
 50/* SPC CPU/cluster reset statue */
 51#define STANDBYWFI_STAT		0x3c
 52#define STANDBYWFI_STAT_A15_CPU_MASK(cpu)	(1 << (cpu))
 53#define STANDBYWFI_STAT_A7_CPU_MASK(cpu)	(1 << (3 + (cpu)))
 54
 55/* SPC system config interface registers */
 56#define SYSCFG_WDATA		0x70
 57#define SYSCFG_RDATA		0x74
 58
 59/* A15/A7 OPP virtual register base */
 60#define A15_PERFVAL_BASE	0xC10
 61#define A7_PERFVAL_BASE		0xC30
 62
 63/* Config interface control bits */
 64#define SYSCFG_START		BIT(31)
 65#define SYSCFG_SCC		(6 << 20)
 66#define SYSCFG_STAT		(14 << 20)
 67
 68/* wake-up interrupt masks */
 69#define GBL_WAKEUP_INT_MSK	(0x3 << 10)
 70
 71/* TC2 static dual-cluster configuration */
 72#define MAX_CLUSTERS		2
 73
 74/*
 75 * Even though the SPC takes max 3-5 ms to complete any OPP/COMMS
 76 * operation, the operation could start just before jiffy is about
 77 * to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz
 78 */
 79#define TIMEOUT_US	20000
 80
 81#define MAX_OPPS	8
 82#define CA15_DVFS	0
 83#define CA7_DVFS	1
 84#define SPC_SYS_CFG	2
 85#define STAT_COMPLETE(type)	((1 << 0) << (type << 2))
 86#define STAT_ERR(type)		((1 << 1) << (type << 2))
 87#define RESPONSE_MASK(type)	(STAT_COMPLETE(type) | STAT_ERR(type))
 88
 89struct ve_spc_opp {
 90	unsigned long freq;
 91	unsigned long u_volt;
 92};
 93
 94struct ve_spc_drvdata {
 95	void __iomem *baseaddr;
 96	/*
 97	 * A15s cluster identifier
 98	 * It corresponds to A15 processors MPIDR[15:8] bitfield
 99	 */
100	u32 a15_clusid;
101	uint32_t cur_rsp_mask;
102	uint32_t cur_rsp_stat;
103	struct semaphore sem;
104	struct completion done;
105	struct ve_spc_opp *opps[MAX_CLUSTERS];
106	int num_opps[MAX_CLUSTERS];
107};
108
109static struct ve_spc_drvdata *info;
110
111static inline bool cluster_is_a15(u32 cluster)
112{
113	return cluster == info->a15_clusid;
114}
115
116/**
117 * ve_spc_global_wakeup_irq() - sets/clears global wakeup IRQs
118 *
119 * @set: if true, global wake-up IRQs are set, if false they are cleared
120 *
121 * Function to set/clear global wakeup IRQs. Not protected by locking since
122 * it might be used in code paths where normal cacheable locks are not
123 * working. Locking must be provided by the caller to ensure atomicity.
124 */
125void ve_spc_global_wakeup_irq(bool set)
126{
127	u32 reg;
128
129	reg = readl_relaxed(info->baseaddr + WAKE_INT_MASK);
130
131	if (set)
132		reg |= GBL_WAKEUP_INT_MSK;
133	else
134		reg &= ~GBL_WAKEUP_INT_MSK;
135
136	writel_relaxed(reg, info->baseaddr + WAKE_INT_MASK);
137}
138
139/**
140 * ve_spc_cpu_wakeup_irq() - sets/clears per-CPU wake-up IRQs
141 *
142 * @cluster: mpidr[15:8] bitfield describing cluster affinity level
143 * @cpu: mpidr[7:0] bitfield describing cpu affinity level
144 * @set: if true, wake-up IRQs are set, if false they are cleared
145 *
146 * Function to set/clear per-CPU wake-up IRQs. Not protected by locking since
147 * it might be used in code paths where normal cacheable locks are not
148 * working. Locking must be provided by the caller to ensure atomicity.
149 */
150void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set)
151{
152	u32 mask, reg;
153
154	if (cluster >= MAX_CLUSTERS)
155		return;
156
157	mask = BIT(cpu);
158
159	if (!cluster_is_a15(cluster))
160		mask <<= 4;
161
162	reg = readl_relaxed(info->baseaddr + WAKE_INT_MASK);
163
164	if (set)
165		reg |= mask;
166	else
167		reg &= ~mask;
168
169	writel_relaxed(reg, info->baseaddr + WAKE_INT_MASK);
170}
171
172/**
173 * ve_spc_set_resume_addr() - set the jump address used for warm boot
174 *
175 * @cluster: mpidr[15:8] bitfield describing cluster affinity level
176 * @cpu: mpidr[7:0] bitfield describing cpu affinity level
177 * @addr: physical resume address
178 */
179void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr)
180{
181	void __iomem *baseaddr;
182
183	if (cluster >= MAX_CLUSTERS)
184		return;
185
186	if (cluster_is_a15(cluster))
187		baseaddr = info->baseaddr + A15_BX_ADDR0 + (cpu << 2);
188	else
189		baseaddr = info->baseaddr + A7_BX_ADDR0 + (cpu << 2);
190
191	writel_relaxed(addr, baseaddr);
192}
193
194/**
195 * ve_spc_powerdown() - enables/disables cluster powerdown
196 *
197 * @cluster: mpidr[15:8] bitfield describing cluster affinity level
198 * @enable: if true enables powerdown, if false disables it
199 *
200 * Function to enable/disable cluster powerdown. Not protected by locking
201 * since it might be used in code paths where normal cacheable locks are not
202 * working. Locking must be provided by the caller to ensure atomicity.
203 */
204void ve_spc_powerdown(u32 cluster, bool enable)
205{
206	u32 pwdrn_reg;
207
208	if (cluster >= MAX_CLUSTERS)
209		return;
210
211	pwdrn_reg = cluster_is_a15(cluster) ? A15_PWRDN_EN : A7_PWRDN_EN;
212	writel_relaxed(enable, info->baseaddr + pwdrn_reg);
213}
214
215static u32 standbywfi_cpu_mask(u32 cpu, u32 cluster)
216{
217	return cluster_is_a15(cluster) ?
218		  STANDBYWFI_STAT_A15_CPU_MASK(cpu)
219		: STANDBYWFI_STAT_A7_CPU_MASK(cpu);
220}
221
222/**
223 * ve_spc_cpu_in_wfi() - Checks if the specified CPU is in WFI or not
224 *
225 * @cpu: mpidr[7:0] bitfield describing CPU affinity level within cluster
226 * @cluster: mpidr[15:8] bitfield describing cluster affinity level
227 *
228 * @return: non-zero if and only if the specified CPU is in WFI
229 *
230 * Take care when interpreting the result of this function: a CPU might
231 * be in WFI temporarily due to idle, and is not necessarily safely
232 * parked.
233 */
234int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
235{
236	int ret;
237	u32 mask = standbywfi_cpu_mask(cpu, cluster);
238
239	if (cluster >= MAX_CLUSTERS)
240		return 1;
241
242	ret = readl_relaxed(info->baseaddr + STANDBYWFI_STAT);
243
244	pr_debug("%s: PCFGREG[0x%X] = 0x%08X, mask = 0x%X\n",
245		 __func__, STANDBYWFI_STAT, ret, mask);
246
247	return ret & mask;
248}
249
250static int ve_spc_get_performance(int cluster, u32 *freq)
251{
252	struct ve_spc_opp *opps = info->opps[cluster];
253	u32 perf_cfg_reg = 0;
254	u32 perf;
255
256	perf_cfg_reg = cluster_is_a15(cluster) ? PERF_LVL_A15 : PERF_LVL_A7;
257
258	perf = readl_relaxed(info->baseaddr + perf_cfg_reg);
259	if (perf >= info->num_opps[cluster])
260		return -EINVAL;
261
262	opps += perf;
263	*freq = opps->freq;
264
265	return 0;
266}
267
268/* find closest match to given frequency in OPP table */
269static int ve_spc_round_performance(int cluster, u32 freq)
270{
271	int idx, max_opp = info->num_opps[cluster];
272	struct ve_spc_opp *opps = info->opps[cluster];
273	u32 fmin = 0, fmax = ~0, ftmp;
274
275	freq /= 1000; /* OPP entries in kHz */
276	for (idx = 0; idx < max_opp; idx++, opps++) {
277		ftmp = opps->freq;
278		if (ftmp >= freq) {
279			if (ftmp <= fmax)
280				fmax = ftmp;
281		} else {
282			if (ftmp >= fmin)
283				fmin = ftmp;
284		}
285	}
286	if (fmax != ~0)
287		return fmax * 1000;
288	else
289		return fmin * 1000;
290}
291
292static int ve_spc_find_performance_index(int cluster, u32 freq)
293{
294	int idx, max_opp = info->num_opps[cluster];
295	struct ve_spc_opp *opps = info->opps[cluster];
296
297	for (idx = 0; idx < max_opp; idx++, opps++)
298		if (opps->freq == freq)
299			break;
300	return (idx == max_opp) ? -EINVAL : idx;
301}
302
303static int ve_spc_waitforcompletion(int req_type)
304{
305	int ret = wait_for_completion_interruptible_timeout(
306			&info->done, usecs_to_jiffies(TIMEOUT_US));
307	if (ret == 0)
308		ret = -ETIMEDOUT;
309	else if (ret > 0)
310		ret = info->cur_rsp_stat & STAT_COMPLETE(req_type) ? 0 : -EIO;
311	return ret;
312}
313
314static int ve_spc_set_performance(int cluster, u32 freq)
315{
316	u32 perf_cfg_reg;
317	int ret, perf, req_type;
318
319	if (cluster_is_a15(cluster)) {
320		req_type = CA15_DVFS;
321		perf_cfg_reg = PERF_LVL_A15;
322	} else {
323		req_type = CA7_DVFS;
324		perf_cfg_reg = PERF_LVL_A7;
325	}
326
327	perf = ve_spc_find_performance_index(cluster, freq);
328
329	if (perf < 0)
330		return perf;
331
332	if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
333		return -ETIME;
334
335	init_completion(&info->done);
336	info->cur_rsp_mask = RESPONSE_MASK(req_type);
337
338	writel(perf, info->baseaddr + perf_cfg_reg);
339	ret = ve_spc_waitforcompletion(req_type);
340
341	info->cur_rsp_mask = 0;
342	up(&info->sem);
343
344	return ret;
345}
346
347static int ve_spc_read_sys_cfg(int func, int offset, uint32_t *data)
348{
349	int ret;
350
351	if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
352		return -ETIME;
353
354	init_completion(&info->done);
355	info->cur_rsp_mask = RESPONSE_MASK(SPC_SYS_CFG);
356
357	/* Set the control value */
358	writel(SYSCFG_START | func | offset >> 2, info->baseaddr + COMMS);
359	ret = ve_spc_waitforcompletion(SPC_SYS_CFG);
360
361	if (ret == 0)
362		*data = readl(info->baseaddr + SYSCFG_RDATA);
363
364	info->cur_rsp_mask = 0;
365	up(&info->sem);
366
367	return ret;
368}
369
370static irqreturn_t ve_spc_irq_handler(int irq, void *data)
371{
372	struct ve_spc_drvdata *drv_data = data;
373	uint32_t status = readl_relaxed(drv_data->baseaddr + PWC_STATUS);
374
375	if (info->cur_rsp_mask & status) {
376		info->cur_rsp_stat = status;
377		complete(&drv_data->done);
378	}
379
380	return IRQ_HANDLED;
381}
382
383/*
384 *  +--------------------------+
385 *  | 31      20 | 19        0 |
386 *  +--------------------------+
387 *  |   m_volt   |  freq(kHz)  |
388 *  +--------------------------+
389 */
390#define MULT_FACTOR	20
391#define VOLT_SHIFT	20
392#define FREQ_MASK	(0xFFFFF)
393static int ve_spc_populate_opps(uint32_t cluster)
394{
395	uint32_t data = 0, off, ret, idx;
396	struct ve_spc_opp *opps;
397
398	opps = kcalloc(MAX_OPPS, sizeof(*opps), GFP_KERNEL);
399	if (!opps)
400		return -ENOMEM;
401
402	info->opps[cluster] = opps;
403
404	off = cluster_is_a15(cluster) ? A15_PERFVAL_BASE : A7_PERFVAL_BASE;
405	for (idx = 0; idx < MAX_OPPS; idx++, off += 4, opps++) {
406		ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data);
407		if (!ret) {
408			opps->freq = (data & FREQ_MASK) * MULT_FACTOR;
409			opps->u_volt = (data >> VOLT_SHIFT) * 1000;
410		} else {
411			break;
412		}
413	}
414	info->num_opps[cluster] = idx;
415
416	return ret;
417}
418
419static int ve_init_opp_table(struct device *cpu_dev)
420{
421	int cluster;
422	int idx, ret = 0, max_opp;
423	struct ve_spc_opp *opps;
424
425	cluster = topology_physical_package_id(cpu_dev->id);
426	cluster = cluster < 0 ? 0 : cluster;
427
428	max_opp = info->num_opps[cluster];
429	opps = info->opps[cluster];
430
431	for (idx = 0; idx < max_opp; idx++, opps++) {
432		ret = dev_pm_opp_add(cpu_dev, opps->freq * 1000, opps->u_volt);
433		if (ret) {
434			dev_warn(cpu_dev, "failed to add opp %lu %lu\n",
435				 opps->freq, opps->u_volt);
436			return ret;
437		}
438	}
439	return ret;
440}
441
442int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid, int irq)
443{
444	int ret;
445	info = kzalloc(sizeof(*info), GFP_KERNEL);
446	if (!info)
447		return -ENOMEM;
448
449	info->baseaddr = baseaddr;
450	info->a15_clusid = a15_clusid;
451
452	if (irq <= 0) {
453		pr_err(SPCLOG "Invalid IRQ %d\n", irq);
454		kfree(info);
455		return -EINVAL;
456	}
457
458	init_completion(&info->done);
459
460	readl_relaxed(info->baseaddr + PWC_STATUS);
461
462	ret = request_irq(irq, ve_spc_irq_handler, IRQF_TRIGGER_HIGH
463				| IRQF_ONESHOT, "vexpress-spc", info);
464	if (ret) {
465		pr_err(SPCLOG "IRQ %d request failed\n", irq);
466		kfree(info);
467		return -ENODEV;
468	}
469
470	sema_init(&info->sem, 1);
471	/*
472	 * Multi-cluster systems may need this data when non-coherent, during
473	 * cluster power-up/power-down. Make sure driver info reaches main
474	 * memory.
475	 */
476	sync_cache_w(info);
477	sync_cache_w(&info);
478
479	return 0;
480}
481
482struct clk_spc {
483	struct clk_hw hw;
484	int cluster;
485};
486
487#define to_clk_spc(spc) container_of(spc, struct clk_spc, hw)
488static unsigned long spc_recalc_rate(struct clk_hw *hw,
489		unsigned long parent_rate)
490{
491	struct clk_spc *spc = to_clk_spc(hw);
492	u32 freq;
493
494	if (ve_spc_get_performance(spc->cluster, &freq))
495		return -EIO;
496
497	return freq * 1000;
498}
499
500static int spc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
501{
502	struct clk_spc *spc = to_clk_spc(hw);
503
504	req->rate = ve_spc_round_performance(spc->cluster, req->rate);
505
506	return 0;
507}
508
509static int spc_set_rate(struct clk_hw *hw, unsigned long rate,
510		unsigned long parent_rate)
511{
512	struct clk_spc *spc = to_clk_spc(hw);
513
514	return ve_spc_set_performance(spc->cluster, rate / 1000);
515}
516
517static struct clk_ops clk_spc_ops = {
518	.recalc_rate = spc_recalc_rate,
519	.determine_rate = spc_determine_rate,
520	.set_rate = spc_set_rate,
521};
522
523static struct clk *ve_spc_clk_register(struct device *cpu_dev)
524{
525	struct clk_init_data init;
526	struct clk_spc *spc;
527
528	spc = kzalloc(sizeof(*spc), GFP_KERNEL);
529	if (!spc)
530		return ERR_PTR(-ENOMEM);
531
532	spc->hw.init = &init;
533	spc->cluster = topology_physical_package_id(cpu_dev->id);
534
535	spc->cluster = spc->cluster < 0 ? 0 : spc->cluster;
536
537	init.name = dev_name(cpu_dev);
538	init.ops = &clk_spc_ops;
539	init.flags = CLK_GET_RATE_NOCACHE;
540	init.num_parents = 0;
541
542	return devm_clk_register(cpu_dev, &spc->hw);
543}
544
545static int __init ve_spc_clk_init(void)
546{
547	int cpu, cluster;
548	struct clk *clk;
549	bool init_opp_table[MAX_CLUSTERS] = { false };
550
551	if (!info)
552		return 0; /* Continue only if SPC is initialised */
553
554	if (ve_spc_populate_opps(0) || ve_spc_populate_opps(1)) {
555		pr_err("failed to build OPP table\n");
556		return -ENODEV;
557	}
558
559	for_each_possible_cpu(cpu) {
560		struct device *cpu_dev = get_cpu_device(cpu);
561		if (!cpu_dev) {
562			pr_warn("failed to get cpu%d device\n", cpu);
563			continue;
564		}
565		clk = ve_spc_clk_register(cpu_dev);
566		if (IS_ERR(clk)) {
567			pr_warn("failed to register cpu%d clock\n", cpu);
568			continue;
569		}
570		if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
571			pr_warn("failed to register cpu%d clock lookup\n", cpu);
572			continue;
573		}
574
575		cluster = topology_physical_package_id(cpu_dev->id);
576		if (cluster < 0 || init_opp_table[cluster])
577			continue;
578
579		if (ve_init_opp_table(cpu_dev))
580			pr_warn("failed to initialise cpu%d opp table\n", cpu);
581		else if (dev_pm_opp_set_sharing_cpus(cpu_dev,
582			 topology_core_cpumask(cpu_dev->id)))
583			pr_warn("failed to mark OPPs shared for cpu%d\n", cpu);
584		else
585			init_opp_table[cluster] = true;
586	}
587
588	platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0);
589	return 0;
590}
591device_initcall(ve_spc_clk_init);
~/ Read-only file preview.