Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (C) 2022-2024 Arm Limited
  3// NI-700 Network-on-Chip PMU driver
  4
  5#include <linux/acpi.h>
  6#include <linux/bitfield.h>
  7#include <linux/interrupt.h>
  8#include <linux/io.h>
  9#include <linux/io-64-nonatomic-lo-hi.h>
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/of.h>
 13#include <linux/perf_event.h>
 14#include <linux/platform_device.h>
 15#include <linux/slab.h>
 16
 17/* Common registers */
 18#define NI_NODE_TYPE		0x000
 19#define NI_NODE_TYPE_NODE_ID	GENMASK(31, 16)
 20#define NI_NODE_TYPE_NODE_TYPE	GENMASK(15, 0)
 21
 22#define NI_CHILD_NODE_INFO	0x004
 23#define NI_CHILD_PTR(n)		(0x008 + (n) * 4)
 24
 25#define NI700_PMUSELA		0x00c
 26
 27/* Config node */
 28#define NI_PERIPHERAL_ID0	0xfe0
 29#define NI_PIDR0_PART_7_0	GENMASK(7, 0)
 30#define NI_PERIPHERAL_ID1	0xfe4
 31#define NI_PIDR1_PART_11_8	GENMASK(3, 0)
 32#define NI_PERIPHERAL_ID2	0xfe8
 33#define NI_PIDR2_VERSION	GENMASK(7, 4)
 34
 35/* PMU node */
 36#define NI_PMEVCNTR(n)		(0x008 + (n) * 8)
 37#define NI_PMCCNTR_L		0x0f8
 38#define NI_PMCCNTR_U		0x0fc
 39#define NI_PMEVTYPER(n)		(0x400 + (n) * 4)
 40#define NI_PMEVTYPER_NODE_TYPE	GENMASK(12, 9)
 41#define NI_PMEVTYPER_NODE_ID	GENMASK(8, 0)
 42#define NI_PMCNTENSET		0xc00
 43#define NI_PMCNTENCLR		0xc20
 44#define NI_PMINTENSET		0xc40
 45#define NI_PMINTENCLR		0xc60
 46#define NI_PMOVSCLR		0xc80
 47#define NI_PMOVSSET		0xcc0
 48#define NI_PMCFGR		0xe00
 49#define NI_PMCR			0xe04
 50#define NI_PMCR_RESET_CCNT	BIT(2)
 51#define NI_PMCR_RESET_EVCNT	BIT(1)
 52#define NI_PMCR_ENABLE		BIT(0)
 53
 54#define NI_NUM_COUNTERS		8
 55#define NI_CCNT_IDX		31
 56
 57/* Event attributes */
 58#define NI_CONFIG_TYPE		GENMASK_ULL(15, 0)
 59#define NI_CONFIG_NODEID	GENMASK_ULL(31, 16)
 60#define NI_CONFIG_EVENTID	GENMASK_ULL(47, 32)
 61
 62#define NI_EVENT_TYPE(event)	FIELD_GET(NI_CONFIG_TYPE, (event)->attr.config)
 63#define NI_EVENT_NODEID(event)	FIELD_GET(NI_CONFIG_NODEID, (event)->attr.config)
 64#define NI_EVENT_EVENTID(event)	FIELD_GET(NI_CONFIG_EVENTID, (event)->attr.config)
 65
 66enum ni_part {
 67	PART_NI_700 = 0x43b,
 68	PART_NI_710AE = 0x43d,
 69};
 70
 71enum ni_node_type {
 72	NI_GLOBAL,
 73	NI_VOLTAGE,
 74	NI_POWER,
 75	NI_CLOCK,
 76	NI_ASNI,
 77	NI_AMNI,
 78	NI_PMU,
 79	NI_HSNI,
 80	NI_HMNI,
 81	NI_PMNI,
 82};
 83
 84struct arm_ni_node {
 85	void __iomem *base;
 86	enum ni_node_type type;
 87	u16 id;
 88	u32 num_components;
 89};
 90
 91struct arm_ni_unit {
 92	void __iomem *pmusela;
 93	enum ni_node_type type;
 94	u16 id;
 95	bool ns;
 96	union {
 97		__le64 pmusel;
 98		u8 event[8];
 99	};
100};
101
102struct arm_ni_cd {
103	void __iomem *pmu_base;
104	u16 id;
105	int num_units;
106	int irq;
107	int cpu;
108	struct hlist_node cpuhp_node;
109	struct pmu pmu;
110	struct arm_ni_unit *units;
111	struct perf_event *evcnt[NI_NUM_COUNTERS];
112	struct perf_event *ccnt;
113};
114
115struct arm_ni {
116	struct device *dev;
117	void __iomem *base;
118	enum ni_part part;
119	int id;
120	int num_cds;
121	struct arm_ni_cd cds[] __counted_by(num_cds);
122};
123
124#define cd_to_ni(cd) container_of((cd), struct arm_ni, cds[(cd)->id])
125#define pmu_to_cd(p) container_of((p), struct arm_ni_cd, pmu)
126
127#define cd_for_each_unit(cd, u) \
128	for (struct arm_ni_unit *u = cd->units; u < cd->units + cd->num_units; u++)
129
130static int arm_ni_hp_state;
131
132struct arm_ni_event_attr {
133	struct device_attribute attr;
134	enum ni_node_type type;
135};
136
137#define NI_EVENT_ATTR(_name, _type)					\
138	(&((struct arm_ni_event_attr[]) {{				\
139		.attr = __ATTR(_name, 0444, arm_ni_event_show, NULL),	\
140		.type = _type,						\
141	}})[0].attr.attr)
142
143static ssize_t arm_ni_event_show(struct device *dev,
144				 struct device_attribute *attr, char *buf)
145{
146	struct arm_ni_event_attr *eattr = container_of(attr, typeof(*eattr), attr);
147
148	if (eattr->type == NI_PMU)
149		return sysfs_emit(buf, "type=0x%x\n", eattr->type);
150
151	return sysfs_emit(buf, "type=0x%x,eventid=?,nodeid=?\n", eattr->type);
152}
153
154static umode_t arm_ni_event_attr_is_visible(struct kobject *kobj,
155					    struct attribute *attr, int unused)
156{
157	struct device *dev = kobj_to_dev(kobj);
158	struct arm_ni_cd *cd = pmu_to_cd(dev_get_drvdata(dev));
159	struct arm_ni_event_attr *eattr;
160
161	eattr = container_of(attr, typeof(*eattr), attr.attr);
162
163	cd_for_each_unit(cd, unit) {
164		if (unit->type == eattr->type && unit->ns)
165			return attr->mode;
166	}
167
168	return 0;
169}
170
171static struct attribute *arm_ni_event_attrs[] = {
172	NI_EVENT_ATTR(asni, NI_ASNI),
173	NI_EVENT_ATTR(amni, NI_AMNI),
174	NI_EVENT_ATTR(cycles, NI_PMU),
175	NI_EVENT_ATTR(hsni, NI_HSNI),
176	NI_EVENT_ATTR(hmni, NI_HMNI),
177	NI_EVENT_ATTR(pmni, NI_PMNI),
178	NULL
179};
180
181static const struct attribute_group arm_ni_event_attrs_group = {
182	.name = "events",
183	.attrs = arm_ni_event_attrs,
184	.is_visible = arm_ni_event_attr_is_visible,
185};
186
187struct arm_ni_format_attr {
188	struct device_attribute attr;
189	u64 field;
190};
191
192#define NI_FORMAT_ATTR(_name, _fld)					\
193	(&((struct arm_ni_format_attr[]) {{				\
194		.attr = __ATTR(_name, 0444, arm_ni_format_show, NULL),	\
195		.field = _fld,						\
196	}})[0].attr.attr)
197
198static ssize_t arm_ni_format_show(struct device *dev,
199				  struct device_attribute *attr, char *buf)
200{
201	struct arm_ni_format_attr *fmt = container_of(attr, typeof(*fmt), attr);
202
203	return sysfs_emit(buf, "config:%*pbl\n", 64, &fmt->field);
204}
205
206static struct attribute *arm_ni_format_attrs[] = {
207	NI_FORMAT_ATTR(type, NI_CONFIG_TYPE),
208	NI_FORMAT_ATTR(nodeid, NI_CONFIG_NODEID),
209	NI_FORMAT_ATTR(eventid, NI_CONFIG_EVENTID),
210	NULL
211};
212
213static const struct attribute_group arm_ni_format_attrs_group = {
214	.name = "format",
215	.attrs = arm_ni_format_attrs,
216};
217
218static ssize_t arm_ni_cpumask_show(struct device *dev,
219				   struct device_attribute *attr, char *buf)
220{
221	struct arm_ni_cd *cd = pmu_to_cd(dev_get_drvdata(dev));
222
223	return cpumap_print_to_pagebuf(true, buf, cpumask_of(cd->cpu));
224}
225
226static struct device_attribute arm_ni_cpumask_attr =
227		__ATTR(cpumask, 0444, arm_ni_cpumask_show, NULL);
228
229static ssize_t arm_ni_identifier_show(struct device *dev,
230				      struct device_attribute *attr, char *buf)
231{
232	struct arm_ni *ni = cd_to_ni(pmu_to_cd(dev_get_drvdata(dev)));
233	u32 reg = readl_relaxed(ni->base + NI_PERIPHERAL_ID2);
234	int version = FIELD_GET(NI_PIDR2_VERSION, reg);
235
236	return sysfs_emit(buf, "%03x%02x\n", ni->part, version);
237}
238
239static struct device_attribute arm_ni_identifier_attr =
240		__ATTR(identifier, 0444, arm_ni_identifier_show, NULL);
241
242static struct attribute *arm_ni_other_attrs[] = {
243	&arm_ni_cpumask_attr.attr,
244	&arm_ni_identifier_attr.attr,
245	NULL
246};
247
248static const struct attribute_group arm_ni_other_attr_group = {
249	.attrs = arm_ni_other_attrs,
250};
251
252static const struct attribute_group *arm_ni_attr_groups[] = {
253	&arm_ni_event_attrs_group,
254	&arm_ni_format_attrs_group,
255	&arm_ni_other_attr_group,
256	NULL
257};
258
259static void arm_ni_pmu_enable(struct pmu *pmu)
260{
261	writel_relaxed(NI_PMCR_ENABLE, pmu_to_cd(pmu)->pmu_base + NI_PMCR);
262}
263
264static void arm_ni_pmu_disable(struct pmu *pmu)
265{
266	writel_relaxed(0, pmu_to_cd(pmu)->pmu_base + NI_PMCR);
267}
268
269struct arm_ni_val {
270	unsigned int evcnt;
271	unsigned int ccnt;
272};
273
274static bool arm_ni_val_count_event(struct perf_event *evt, struct arm_ni_val *val)
275{
276	if (is_software_event(evt))
277		return true;
278
279	if (NI_EVENT_TYPE(evt) == NI_PMU) {
280		val->ccnt++;
281		return val->ccnt <= 1;
282	}
283
284	val->evcnt++;
285	return val->evcnt <= NI_NUM_COUNTERS;
286}
287
288static int arm_ni_validate_group(struct perf_event *event)
289{
290	struct perf_event *sibling, *leader = event->group_leader;
291	struct arm_ni_val val = { 0 };
292
293	if (leader == event)
294		return 0;
295
296	arm_ni_val_count_event(event, &val);
297	if (!arm_ni_val_count_event(leader, &val))
298		return -EINVAL;
299
300	for_each_sibling_event(sibling, leader) {
301		if (!arm_ni_val_count_event(sibling, &val))
302			return -EINVAL;
303	}
304	return 0;
305}
306
307static int arm_ni_event_init(struct perf_event *event)
308{
309	struct arm_ni_cd *cd = pmu_to_cd(event->pmu);
310
311	if (event->attr.type != event->pmu->type)
312		return -ENOENT;
313
314	if (is_sampling_event(event))
315		return -EINVAL;
316
317	event->cpu = cd->cpu;
318	if (NI_EVENT_TYPE(event) == NI_PMU)
319		return arm_ni_validate_group(event);
320
321	cd_for_each_unit(cd, unit) {
322		if (unit->type == NI_EVENT_TYPE(event) &&
323		    unit->id == NI_EVENT_NODEID(event) && unit->ns) {
324			event->hw.config_base = (unsigned long)unit;
325			return arm_ni_validate_group(event);
326		}
327	}
328	return -EINVAL;
329}
330
331static u64 arm_ni_read_ccnt(struct arm_ni_cd *cd)
332{
333	u64 l, u_old, u_new;
334	int retries = 3; /* 1st time unlucky, 2nd improbable, 3rd just broken */
335
336	u_new = readl_relaxed(cd->pmu_base + NI_PMCCNTR_U);
337	do {
338		u_old = u_new;
339		l = readl_relaxed(cd->pmu_base + NI_PMCCNTR_L);
340		u_new = readl_relaxed(cd->pmu_base + NI_PMCCNTR_U);
341	} while (u_new != u_old && --retries);
342	WARN_ON(!retries);
343
344	return (u_new << 32) | l;
345}
346
347static void arm_ni_event_read(struct perf_event *event)
348{
349	struct arm_ni_cd *cd = pmu_to_cd(event->pmu);
350	struct hw_perf_event *hw = &event->hw;
351	u64 count, prev;
352	bool ccnt = hw->idx == NI_CCNT_IDX;
353
354	do {
355		prev = local64_read(&hw->prev_count);
356		if (ccnt)
357			count = arm_ni_read_ccnt(cd);
358		else
359			count = readl_relaxed(cd->pmu_base + NI_PMEVCNTR(hw->idx));
360	} while (local64_cmpxchg(&hw->prev_count, prev, count) != prev);
361
362	count -= prev;
363	if (!ccnt)
364		count = (u32)count;
365	local64_add(count, &event->count);
366}
367
368static void arm_ni_event_start(struct perf_event *event, int flags)
369{
370	struct arm_ni_cd *cd = pmu_to_cd(event->pmu);
371
372	writel_relaxed(1U << event->hw.idx, cd->pmu_base + NI_PMCNTENSET);
373}
374
375static void arm_ni_event_stop(struct perf_event *event, int flags)
376{
377	struct arm_ni_cd *cd = pmu_to_cd(event->pmu);
378
379	writel_relaxed(1U << event->hw.idx, cd->pmu_base + NI_PMCNTENCLR);
380	if (flags & PERF_EF_UPDATE)
381		arm_ni_event_read(event);
382}
383
384static void arm_ni_init_ccnt(struct arm_ni_cd *cd)
385{
386	local64_set(&cd->ccnt->hw.prev_count, S64_MIN);
387	lo_hi_writeq_relaxed(S64_MIN, cd->pmu_base + NI_PMCCNTR_L);
388}
389
390static void arm_ni_init_evcnt(struct arm_ni_cd *cd, int idx)
391{
392	local64_set(&cd->evcnt[idx]->hw.prev_count, S32_MIN);
393	writel_relaxed(S32_MIN, cd->pmu_base + NI_PMEVCNTR(idx));
394}
395
396static int arm_ni_event_add(struct perf_event *event, int flags)
397{
398	struct arm_ni_cd *cd = pmu_to_cd(event->pmu);
399	struct hw_perf_event *hw = &event->hw;
400	struct arm_ni_unit *unit;
401	enum ni_node_type type = NI_EVENT_TYPE(event);
402	u32 reg;
403
404	if (type == NI_PMU) {
405		if (cd->ccnt)
406			return -ENOSPC;
407		hw->idx = NI_CCNT_IDX;
408		cd->ccnt = event;
409		arm_ni_init_ccnt(cd);
410	} else {
411		hw->idx = 0;
412		while (cd->evcnt[hw->idx]) {
413			if (++hw->idx == NI_NUM_COUNTERS)
414				return -ENOSPC;
415		}
416		cd->evcnt[hw->idx] = event;
417		unit = (void *)hw->config_base;
418		unit->event[hw->idx] = NI_EVENT_EVENTID(event);
419		arm_ni_init_evcnt(cd, hw->idx);
420		lo_hi_writeq_relaxed(le64_to_cpu(unit->pmusel), unit->pmusela);
421
422		reg = FIELD_PREP(NI_PMEVTYPER_NODE_TYPE, type) |
423		      FIELD_PREP(NI_PMEVTYPER_NODE_ID, NI_EVENT_NODEID(event));
424		writel_relaxed(reg, cd->pmu_base + NI_PMEVTYPER(hw->idx));
425	}
426	if (flags & PERF_EF_START)
427		arm_ni_event_start(event, 0);
428	return 0;
429}
430
431static void arm_ni_event_del(struct perf_event *event, int flags)
432{
433	struct arm_ni_cd *cd = pmu_to_cd(event->pmu);
434	struct hw_perf_event *hw = &event->hw;
435
436	arm_ni_event_stop(event, PERF_EF_UPDATE);
437
438	if (hw->idx == NI_CCNT_IDX)
439		cd->ccnt = NULL;
440	else
441		cd->evcnt[hw->idx] = NULL;
442}
443
444static irqreturn_t arm_ni_handle_irq(int irq, void *dev_id)
445{
446	struct arm_ni_cd *cd = dev_id;
447	irqreturn_t ret = IRQ_NONE;
448	u32 reg = readl_relaxed(cd->pmu_base + NI_PMOVSCLR);
449
450	if (reg & (1U << NI_CCNT_IDX)) {
451		ret = IRQ_HANDLED;
452		if (!(WARN_ON(!cd->ccnt))) {
453			arm_ni_event_read(cd->ccnt);
454			arm_ni_init_ccnt(cd);
455		}
456	}
457	for (int i = 0; i < NI_NUM_COUNTERS; i++) {
458		if (!(reg & (1U << i)))
459			continue;
460		ret = IRQ_HANDLED;
461		if (!(WARN_ON(!cd->evcnt[i]))) {
462			arm_ni_event_read(cd->evcnt[i]);
463			arm_ni_init_evcnt(cd, i);
464		}
465	}
466	writel_relaxed(reg, cd->pmu_base + NI_PMOVSCLR);
467	return ret;
468}
469
470static int arm_ni_init_cd(struct arm_ni *ni, struct arm_ni_node *node, u64 res_start)
471{
472	struct arm_ni_cd *cd = ni->cds + node->id;
473	const char *name;
474	int err;
475
476	cd->id = node->id;
477	cd->num_units = node->num_components;
478	cd->units = devm_kcalloc(ni->dev, cd->num_units, sizeof(*(cd->units)), GFP_KERNEL);
479	if (!cd->units)
480		return -ENOMEM;
481
482	for (int i = 0; i < cd->num_units; i++) {
483		u32 reg = readl_relaxed(node->base + NI_CHILD_PTR(i));
484		void __iomem *unit_base = ni->base + reg;
485		struct arm_ni_unit *unit = cd->units + i;
486
487		reg = readl_relaxed(unit_base + NI_NODE_TYPE);
488		unit->type = FIELD_GET(NI_NODE_TYPE_NODE_TYPE, reg);
489		unit->id = FIELD_GET(NI_NODE_TYPE_NODE_ID, reg);
490
491		switch (unit->type) {
492		case NI_PMU:
493			reg = readl_relaxed(unit_base + NI_PMCFGR);
494			if (!reg) {
495				dev_info(ni->dev, "No access to PMU %d\n", cd->id);
496				devm_kfree(ni->dev, cd->units);
497				return 0;
498			}
499			unit->ns = true;
500			cd->pmu_base = unit_base;
501			break;
502		case NI_ASNI:
503		case NI_AMNI:
504		case NI_HSNI:
505		case NI_HMNI:
506		case NI_PMNI:
507			unit->pmusela = unit_base + NI700_PMUSELA;
508			writel_relaxed(1, unit->pmusela);
509			if (readl_relaxed(unit->pmusela) != 1)
510				dev_info(ni->dev, "No access to node 0x%04x%04x\n", unit->id, unit->type);
511			else
512				unit->ns = true;
513			break;
514		default:
515			/*
516			 * e.g. FMU - thankfully bits 3:2 of FMU_ERR_FR0 are RES0 so
517			 * can't alias any of the leaf node types we're looking for.
518			 */
519			dev_dbg(ni->dev, "Mystery node 0x%04x%04x\n", unit->id, unit->type);
520			break;
521		}
522	}
523
524	res_start += cd->pmu_base - ni->base;
525	if (!devm_request_mem_region(ni->dev, res_start, SZ_4K, dev_name(ni->dev))) {
526		dev_err(ni->dev, "Failed to request PMU region 0x%llx\n", res_start);
527		return -EBUSY;
528	}
529
530	writel_relaxed(NI_PMCR_RESET_CCNT | NI_PMCR_RESET_EVCNT,
531		       cd->pmu_base + NI_PMCR);
532	writel_relaxed(U32_MAX, cd->pmu_base + NI_PMCNTENCLR);
533	writel_relaxed(U32_MAX, cd->pmu_base + NI_PMOVSCLR);
534	writel_relaxed(U32_MAX, cd->pmu_base + NI_PMINTENSET);
535
536	cd->irq = platform_get_irq(to_platform_device(ni->dev), cd->id);
537	if (cd->irq < 0)
538		return cd->irq;
539
540	err = devm_request_irq(ni->dev, cd->irq, arm_ni_handle_irq,
541			       IRQF_NOBALANCING | IRQF_NO_THREAD,
542			       dev_name(ni->dev), cd);
543	if (err)
544		return err;
545
546	cd->cpu = cpumask_local_spread(0, dev_to_node(ni->dev));
547	cd->pmu = (struct pmu) {
548		.module = THIS_MODULE,
549		.parent = ni->dev,
550		.attr_groups = arm_ni_attr_groups,
551		.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
552		.task_ctx_nr = perf_invalid_context,
553		.pmu_enable = arm_ni_pmu_enable,
554		.pmu_disable = arm_ni_pmu_disable,
555		.event_init = arm_ni_event_init,
556		.add = arm_ni_event_add,
557		.del = arm_ni_event_del,
558		.start = arm_ni_event_start,
559		.stop = arm_ni_event_stop,
560		.read = arm_ni_event_read,
561	};
562
563	name = devm_kasprintf(ni->dev, GFP_KERNEL, "arm_ni_%d_cd_%d", ni->id, cd->id);
564	if (!name)
565		return -ENOMEM;
566
567	err = cpuhp_state_add_instance_nocalls(arm_ni_hp_state, &cd->cpuhp_node);
568	if (err)
569		return err;
570
571	err = perf_pmu_register(&cd->pmu, name, -1);
572	if (err)
573		cpuhp_state_remove_instance_nocalls(arm_ni_hp_state, &cd->cpuhp_node);
574
575	return err;
576}
577
578static void arm_ni_probe_domain(void __iomem *base, struct arm_ni_node *node)
579{
580	u32 reg = readl_relaxed(base + NI_NODE_TYPE);
581
582	node->base = base;
583	node->type = FIELD_GET(NI_NODE_TYPE_NODE_TYPE, reg);
584	node->id = FIELD_GET(NI_NODE_TYPE_NODE_ID, reg);
585	node->num_components = readl_relaxed(base + NI_CHILD_NODE_INFO);
586}
587
588static int arm_ni_probe(struct platform_device *pdev)
589{
590	struct arm_ni_node cfg, vd, pd, cd;
591	struct arm_ni *ni;
592	struct resource *res;
593	void __iomem *base;
594	static atomic_t id;
595	int num_cds;
596	u32 reg, part;
597
598	/*
599	 * We want to map the whole configuration space for ease of discovery,
600	 * but the PMU pages are the only ones for which we can honestly claim
601	 * exclusive ownership, so we'll request them explicitly once found.
602	 */
603	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
604	base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
605	if (!base)
606		return -ENOMEM;
607
608	arm_ni_probe_domain(base, &cfg);
609	if (cfg.type != NI_GLOBAL)
610		return -ENODEV;
611
612	reg = readl_relaxed(cfg.base + NI_PERIPHERAL_ID0);
613	part = FIELD_GET(NI_PIDR0_PART_7_0, reg);
614	reg = readl_relaxed(cfg.base + NI_PERIPHERAL_ID1);
615	part |= FIELD_GET(NI_PIDR1_PART_11_8, reg) << 8;
616
617	switch (part) {
618	case PART_NI_700:
619	case PART_NI_710AE:
620		break;
621	default:
622		dev_WARN(&pdev->dev, "Unknown part number: 0x%03x, this may go badly\n", part);
623		break;
624	}
625
626	num_cds = 0;
627	for (int v = 0; v < cfg.num_components; v++) {
628		reg = readl_relaxed(cfg.base + NI_CHILD_PTR(v));
629		arm_ni_probe_domain(base + reg, &vd);
630		for (int p = 0; p < vd.num_components; p++) {
631			reg = readl_relaxed(vd.base + NI_CHILD_PTR(p));
632			arm_ni_probe_domain(base + reg, &pd);
633			num_cds += pd.num_components;
634		}
635	}
636
637	ni = devm_kzalloc(&pdev->dev, struct_size(ni, cds, num_cds), GFP_KERNEL);
638	if (!ni)
639		return -ENOMEM;
640
641	ni->dev = &pdev->dev;
642	ni->base = base;
643	ni->num_cds = num_cds;
644	ni->part = part;
645	ni->id = atomic_fetch_inc(&id);
646
647	for (int v = 0; v < cfg.num_components; v++) {
648		reg = readl_relaxed(cfg.base + NI_CHILD_PTR(v));
649		arm_ni_probe_domain(base + reg, &vd);
650		for (int p = 0; p < vd.num_components; p++) {
651			reg = readl_relaxed(vd.base + NI_CHILD_PTR(p));
652			arm_ni_probe_domain(base + reg, &pd);
653			for (int c = 0; c < pd.num_components; c++) {
654				int ret;
655
656				reg = readl_relaxed(pd.base + NI_CHILD_PTR(c));
657				arm_ni_probe_domain(base + reg, &cd);
658				ret = arm_ni_init_cd(ni, &cd, res->start);
659				if (ret)
660					return ret;
661			}
662		}
663	}
664
665	return 0;
666}
667
668static void arm_ni_remove(struct platform_device *pdev)
669{
670	struct arm_ni *ni = platform_get_drvdata(pdev);
671
672	for (int i = 0; i < ni->num_cds; i++) {
673		struct arm_ni_cd *cd = ni->cds + i;
674
675		if (!cd->pmu_base)
676			continue;
677
678		writel_relaxed(0, cd->pmu_base + NI_PMCR);
679		writel_relaxed(U32_MAX, cd->pmu_base + NI_PMINTENCLR);
680		perf_pmu_unregister(&cd->pmu);
681		cpuhp_state_remove_instance_nocalls(arm_ni_hp_state, &cd->cpuhp_node);
682	}
683}
684
685#ifdef CONFIG_OF
686static const struct of_device_id arm_ni_of_match[] = {
687	{ .compatible = "arm,ni-700" },
688	{}
689};
690MODULE_DEVICE_TABLE(of, arm_ni_of_match);
691#endif
692
693#ifdef CONFIG_ACPI
694static const struct acpi_device_id arm_ni_acpi_match[] = {
695	{ "ARMHCB70" },
696	{}
697};
698MODULE_DEVICE_TABLE(acpi, arm_ni_acpi_match);
699#endif
700
701static struct platform_driver arm_ni_driver = {
702	.driver = {
703		.name = "arm-ni",
704		.of_match_table = of_match_ptr(arm_ni_of_match),
705		.acpi_match_table = ACPI_PTR(arm_ni_acpi_match),
706	},
707	.probe = arm_ni_probe,
708	.remove = arm_ni_remove,
709};
710
711static void arm_ni_pmu_migrate(struct arm_ni_cd *cd, unsigned int cpu)
712{
713	perf_pmu_migrate_context(&cd->pmu, cd->cpu, cpu);
714	irq_set_affinity(cd->irq, cpumask_of(cpu));
715	cd->cpu = cpu;
716}
717
718static int arm_ni_pmu_online_cpu(unsigned int cpu, struct hlist_node *cpuhp_node)
719{
720	struct arm_ni_cd *cd;
721	int node;
722
723	cd = hlist_entry_safe(cpuhp_node, struct arm_ni_cd, cpuhp_node);
724	node = dev_to_node(cd_to_ni(cd)->dev);
725	if (cpu_to_node(cd->cpu) != node && cpu_to_node(cpu) == node)
726		arm_ni_pmu_migrate(cd, cpu);
727	return 0;
728}
729
730static int arm_ni_pmu_offline_cpu(unsigned int cpu, struct hlist_node *cpuhp_node)
731{
732	struct arm_ni_cd *cd;
733	unsigned int target;
734	int node;
735
736	cd = hlist_entry_safe(cpuhp_node, struct arm_ni_cd, cpuhp_node);
737	if (cpu != cd->cpu)
738		return 0;
739
740	node = dev_to_node(cd_to_ni(cd)->dev);
741	target = cpumask_any_and_but(cpumask_of_node(node), cpu_online_mask, cpu);
742	if (target >= nr_cpu_ids)
743		target = cpumask_any_but(cpu_online_mask, cpu);
744
745	if (target < nr_cpu_ids)
746		arm_ni_pmu_migrate(cd, target);
747	return 0;
748}
749
750static int __init arm_ni_init(void)
751{
752	int ret;
753
754	ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
755				      "perf/arm/ni:online",
756				      arm_ni_pmu_online_cpu,
757				      arm_ni_pmu_offline_cpu);
758	if (ret < 0)
759		return ret;
760
761	arm_ni_hp_state = ret;
762
763	ret = platform_driver_register(&arm_ni_driver);
764	if (ret)
765		cpuhp_remove_multi_state(arm_ni_hp_state);
766	return ret;
767}
768
769static void __exit arm_ni_exit(void)
770{
771	platform_driver_unregister(&arm_ni_driver);
772	cpuhp_remove_multi_state(arm_ni_hp_state);
773}
774
775module_init(arm_ni_init);
776module_exit(arm_ni_exit);
777
778MODULE_AUTHOR("Robin Murphy <robin.murphy@arm.com>");
779MODULE_DESCRIPTION("Arm NI-700 PMU driver");
780MODULE_LICENSE("GPL v2");