1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Renesas RZ/G2L IRQC Driver
4 *
5 * Copyright (C) 2022 Renesas Electronics Corporation.
6 *
7 * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
8 */
9
10#include <linux/bitfield.h>
11#include <linux/clk.h>
12#include <linux/err.h>
13#include <linux/io.h>
14#include <linux/irqchip.h>
15#include <linux/irqdomain.h>
16#include <linux/of_address.h>
17#include <linux/of_platform.h>
18#include <linux/pm_runtime.h>
19#include <linux/reset.h>
20#include <linux/spinlock.h>
21#include <linux/syscore_ops.h>
22
23#define IRQC_IRQ_START			1
24#define IRQC_IRQ_COUNT			8
25#define IRQC_TINT_START			(IRQC_IRQ_START + IRQC_IRQ_COUNT)
26#define IRQC_TINT_COUNT			32
27#define IRQC_NUM_IRQ			(IRQC_TINT_START + IRQC_TINT_COUNT)
28
29#define ISCR				0x10
30#define IITSR				0x14
31#define TSCR				0x20
32#define TITSR(n)			(0x24 + (n) * 4)
33#define TITSR0_MAX_INT			16
34#define TITSEL_WIDTH			0x2
35#define TSSR(n)				(0x30 + ((n) * 4))
36#define TIEN				BIT(7)
37#define TSSEL_SHIFT(n)			(8 * (n))
38#define TSSEL_MASK			GENMASK(7, 0)
39#define IRQ_MASK			0x3
40
41#define TSSR_OFFSET(n)			((n) % 4)
42#define TSSR_INDEX(n)			((n) / 4)
43
44#define TITSR_TITSEL_EDGE_RISING	0
45#define TITSR_TITSEL_EDGE_FALLING	1
46#define TITSR_TITSEL_LEVEL_HIGH		2
47#define TITSR_TITSEL_LEVEL_LOW		3
48
49#define IITSR_IITSEL(n, sense)		((sense) << ((n) * 2))
50#define IITSR_IITSEL_LEVEL_LOW		0
51#define IITSR_IITSEL_EDGE_FALLING	1
52#define IITSR_IITSEL_EDGE_RISING	2
53#define IITSR_IITSEL_EDGE_BOTH		3
54#define IITSR_IITSEL_MASK(n)		IITSR_IITSEL((n), 3)
55
56#define TINT_EXTRACT_HWIRQ(x)		FIELD_GET(GENMASK(15, 0), (x))
57#define TINT_EXTRACT_GPIOINT(x)		FIELD_GET(GENMASK(31, 16), (x))
58
59/**
60 * struct rzg2l_irqc_reg_cache - registers cache (necessary for suspend/resume)
61 * @iitsr: IITSR register
62 * @titsr: TITSR registers
63 */
64struct rzg2l_irqc_reg_cache {
65	u32	iitsr;
66	u32	titsr[2];
67};
68
69/**
70 * struct rzg2l_irqc_priv - IRQ controller private data structure
71 * @base:	Controller's base address
72 * @fwspec:	IRQ firmware specific data
73 * @lock:	Lock to serialize access to hardware registers
74 * @cache:	Registers cache for suspend/resume
75 */
76static struct rzg2l_irqc_priv {
77	void __iomem			*base;
78	struct irq_fwspec		fwspec[IRQC_NUM_IRQ];
79	raw_spinlock_t			lock;
80	struct rzg2l_irqc_reg_cache	cache;
81} *rzg2l_irqc_data;
82
83static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
84{
85	return data->domain->host_data;
86}
87
88static void rzg2l_clear_irq_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq)
89{
90	unsigned int hw_irq = hwirq - IRQC_IRQ_START;
91	u32 bit = BIT(hw_irq);
92	u32 iitsr, iscr;
93
94	iscr = readl_relaxed(priv->base + ISCR);
95	iitsr = readl_relaxed(priv->base + IITSR);
96
97	/*
98	 * ISCR can only be cleared if the type is falling-edge, rising-edge or
99	 * falling/rising-edge.
100	 */
101	if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq))) {
102		writel_relaxed(iscr & ~bit, priv->base + ISCR);
103		/*
104		 * Enforce that the posted write is flushed to prevent that the
105		 * just handled interrupt is raised again.
106		 */
107		readl_relaxed(priv->base + ISCR);
108	}
109}
110
111static void rzg2l_clear_tint_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq)
112{
113	u32 bit = BIT(hwirq - IRQC_TINT_START);
114	u32 reg;
115
116	reg = readl_relaxed(priv->base + TSCR);
117	if (reg & bit) {
118		writel_relaxed(reg & ~bit, priv->base + TSCR);
119		/*
120		 * Enforce that the posted write is flushed to prevent that the
121		 * just handled interrupt is raised again.
122		 */
123		readl_relaxed(priv->base + TSCR);
124	}
125}
126
127static void rzg2l_irqc_eoi(struct irq_data *d)
128{
129	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
130	unsigned int hw_irq = irqd_to_hwirq(d);
131
132	raw_spin_lock(&priv->lock);
133	if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT)
134		rzg2l_clear_irq_int(priv, hw_irq);
135	else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ)
136		rzg2l_clear_tint_int(priv, hw_irq);
137	raw_spin_unlock(&priv->lock);
138	irq_chip_eoi_parent(d);
139}
140
141static void rzg2l_irqc_irq_disable(struct irq_data *d)
142{
143	unsigned int hw_irq = irqd_to_hwirq(d);
144
145	if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) {
146		struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
147		u32 offset = hw_irq - IRQC_TINT_START;
148		u32 tssr_offset = TSSR_OFFSET(offset);
149		u8 tssr_index = TSSR_INDEX(offset);
150		u32 reg;
151
152		raw_spin_lock(&priv->lock);
153		reg = readl_relaxed(priv->base + TSSR(tssr_index));
154		reg &= ~(TIEN << TSSEL_SHIFT(tssr_offset));
155		writel_relaxed(reg, priv->base + TSSR(tssr_index));
156		raw_spin_unlock(&priv->lock);
157	}
158	irq_chip_disable_parent(d);
159}
160
161static void rzg2l_irqc_irq_enable(struct irq_data *d)
162{
163	unsigned int hw_irq = irqd_to_hwirq(d);
164
165	if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) {
166		struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
167		u32 offset = hw_irq - IRQC_TINT_START;
168		u32 tssr_offset = TSSR_OFFSET(offset);
169		u8 tssr_index = TSSR_INDEX(offset);
170		u32 reg;
171
172		raw_spin_lock(&priv->lock);
173		reg = readl_relaxed(priv->base + TSSR(tssr_index));
174		reg |= TIEN << TSSEL_SHIFT(tssr_offset);
175		writel_relaxed(reg, priv->base + TSSR(tssr_index));
176		raw_spin_unlock(&priv->lock);
177	}
178	irq_chip_enable_parent(d);
179}
180
181static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
182{
183	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
184	unsigned int hwirq = irqd_to_hwirq(d);
185	u32 iitseln = hwirq - IRQC_IRQ_START;
186	bool clear_irq_int = false;
187	u16 sense, tmp;
188
189	switch (type & IRQ_TYPE_SENSE_MASK) {
190	case IRQ_TYPE_LEVEL_LOW:
191		sense = IITSR_IITSEL_LEVEL_LOW;
192		break;
193
194	case IRQ_TYPE_EDGE_FALLING:
195		sense = IITSR_IITSEL_EDGE_FALLING;
196		clear_irq_int = true;
197		break;
198
199	case IRQ_TYPE_EDGE_RISING:
200		sense = IITSR_IITSEL_EDGE_RISING;
201		clear_irq_int = true;
202		break;
203
204	case IRQ_TYPE_EDGE_BOTH:
205		sense = IITSR_IITSEL_EDGE_BOTH;
206		clear_irq_int = true;
207		break;
208
209	default:
210		return -EINVAL;
211	}
212
213	raw_spin_lock(&priv->lock);
214	tmp = readl_relaxed(priv->base + IITSR);
215	tmp &= ~IITSR_IITSEL_MASK(iitseln);
216	tmp |= IITSR_IITSEL(iitseln, sense);
217	if (clear_irq_int)
218		rzg2l_clear_irq_int(priv, hwirq);
219	writel_relaxed(tmp, priv->base + IITSR);
220	raw_spin_unlock(&priv->lock);
221
222	return 0;
223}
224
225static u32 rzg2l_disable_tint_and_set_tint_source(struct irq_data *d, struct rzg2l_irqc_priv *priv,
226						  u32 reg, u32 tssr_offset, u8 tssr_index)
227{
228	u32 tint = (u32)(uintptr_t)irq_data_get_irq_chip_data(d);
229	u32 tien = reg & (TIEN << TSSEL_SHIFT(tssr_offset));
230
231	/* Clear the relevant byte in reg */
232	reg &= ~(TSSEL_MASK << TSSEL_SHIFT(tssr_offset));
233	/* Set TINT and leave TIEN clear */
234	reg |= tint << TSSEL_SHIFT(tssr_offset);
235	writel_relaxed(reg, priv->base + TSSR(tssr_index));
236
237	return reg | tien;
238}
239
240static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
241{
242	struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
243	unsigned int hwirq = irqd_to_hwirq(d);
244	u32 titseln = hwirq - IRQC_TINT_START;
245	u32 tssr_offset = TSSR_OFFSET(titseln);
246	u8 tssr_index = TSSR_INDEX(titseln);
247	u8 index, sense;
248	u32 reg, tssr;
249
250	switch (type & IRQ_TYPE_SENSE_MASK) {
251	case IRQ_TYPE_EDGE_RISING:
252		sense = TITSR_TITSEL_EDGE_RISING;
253		break;
254
255	case IRQ_TYPE_EDGE_FALLING:
256		sense = TITSR_TITSEL_EDGE_FALLING;
257		break;
258
259	default:
260		return -EINVAL;
261	}
262
263	index = 0;
264	if (titseln >= TITSR0_MAX_INT) {
265		titseln -= TITSR0_MAX_INT;
266		index = 1;
267	}
268
269	raw_spin_lock(&priv->lock);
270	tssr = readl_relaxed(priv->base + TSSR(tssr_index));
271	tssr = rzg2l_disable_tint_and_set_tint_source(d, priv, tssr, tssr_offset, tssr_index);
272	reg = readl_relaxed(priv->base + TITSR(index));
273	reg &= ~(IRQ_MASK << (titseln * TITSEL_WIDTH));
274	reg |= sense << (titseln * TITSEL_WIDTH);
275	writel_relaxed(reg, priv->base + TITSR(index));
276	rzg2l_clear_tint_int(priv, hwirq);
277	writel_relaxed(tssr, priv->base + TSSR(tssr_index));
278	raw_spin_unlock(&priv->lock);
279
280	return 0;
281}
282
283static int rzg2l_irqc_set_type(struct irq_data *d, unsigned int type)
284{
285	unsigned int hw_irq = irqd_to_hwirq(d);
286	int ret = -EINVAL;
287
288	if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT)
289		ret = rzg2l_irq_set_type(d, type);
290	else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ)
291		ret = rzg2l_tint_set_edge(d, type);
292	if (ret)
293		return ret;
294
295	return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
296}
297
298static int rzg2l_irqc_irq_suspend(void)
299{
300	struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache;
301	void __iomem *base = rzg2l_irqc_data->base;
302
303	cache->iitsr = readl_relaxed(base + IITSR);
304	for (u8 i = 0; i < 2; i++)
305		cache->titsr[i] = readl_relaxed(base + TITSR(i));
306
307	return 0;
308}
309
310static void rzg2l_irqc_irq_resume(void)
311{
312	struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache;
313	void __iomem *base = rzg2l_irqc_data->base;
314
315	/*
316	 * Restore only interrupt type. TSSRx will be restored at the
317	 * request of pin controller to avoid spurious interrupts due
318	 * to invalid PIN states.
319	 */
320	for (u8 i = 0; i < 2; i++)
321		writel_relaxed(cache->titsr[i], base + TITSR(i));
322	writel_relaxed(cache->iitsr, base + IITSR);
323}
324
325static struct syscore_ops rzg2l_irqc_syscore_ops = {
326	.suspend	= rzg2l_irqc_irq_suspend,
327	.resume		= rzg2l_irqc_irq_resume,
328};
329
330static const struct irq_chip irqc_chip = {
331	.name			= "rzg2l-irqc",
332	.irq_eoi		= rzg2l_irqc_eoi,
333	.irq_mask		= irq_chip_mask_parent,
334	.irq_unmask		= irq_chip_unmask_parent,
335	.irq_disable		= rzg2l_irqc_irq_disable,
336	.irq_enable		= rzg2l_irqc_irq_enable,
337	.irq_get_irqchip_state	= irq_chip_get_parent_state,
338	.irq_set_irqchip_state	= irq_chip_set_parent_state,
339	.irq_retrigger		= irq_chip_retrigger_hierarchy,
340	.irq_set_type		= rzg2l_irqc_set_type,
341	.irq_set_affinity	= irq_chip_set_affinity_parent,
342	.flags			= IRQCHIP_MASK_ON_SUSPEND |
343				  IRQCHIP_SET_TYPE_MASKED |
344				  IRQCHIP_SKIP_SET_WAKE,
345};
346
347static int rzg2l_irqc_alloc(struct irq_domain *domain, unsigned int virq,
348			    unsigned int nr_irqs, void *arg)
349{
350	struct rzg2l_irqc_priv *priv = domain->host_data;
351	unsigned long tint = 0;
352	irq_hw_number_t hwirq;
353	unsigned int type;
354	int ret;
355
356	ret = irq_domain_translate_twocell(domain, arg, &hwirq, &type);
357	if (ret)
358		return ret;
359
360	/*
361	 * For TINT interrupts ie where pinctrl driver is child of irqc domain
362	 * the hwirq and TINT are encoded in fwspec->param[0].
363	 * hwirq for TINT range from 9-40, hwirq is embedded 0-15 bits and TINT
364	 * from 16-31 bits. TINT from the pinctrl driver needs to be programmed
365	 * in IRQC registers to enable a given gpio pin as interrupt.
366	 */
367	if (hwirq > IRQC_IRQ_COUNT) {
368		tint = TINT_EXTRACT_GPIOINT(hwirq);
369		hwirq = TINT_EXTRACT_HWIRQ(hwirq);
370
371		if (hwirq < IRQC_TINT_START)
372			return -EINVAL;
373	}
374
375	if (hwirq > (IRQC_NUM_IRQ - 1))
376		return -EINVAL;
377
378	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &irqc_chip,
379					    (void *)(uintptr_t)tint);
380	if (ret)
381		return ret;
382
383	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]);
384}
385
386static const struct irq_domain_ops rzg2l_irqc_domain_ops = {
387	.alloc = rzg2l_irqc_alloc,
388	.free = irq_domain_free_irqs_common,
389	.translate = irq_domain_translate_twocell,
390};
391
392static int rzg2l_irqc_parse_interrupts(struct rzg2l_irqc_priv *priv,
393				       struct device_node *np)
394{
395	struct of_phandle_args map;
396	unsigned int i;
397	int ret;
398
399	for (i = 0; i < IRQC_NUM_IRQ; i++) {
400		ret = of_irq_parse_one(np, i, &map);
401		if (ret)
402			return ret;
403		of_phandle_args_to_fwspec(np, map.args, map.args_count,
404					  &priv->fwspec[i]);
405	}
406
407	return 0;
408}
409
410static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
411{
412	struct irq_domain *irq_domain, *parent_domain;
413	struct platform_device *pdev;
414	struct reset_control *resetn;
415	int ret;
416
417	pdev = of_find_device_by_node(node);
418	if (!pdev)
419		return -ENODEV;
420
421	parent_domain = irq_find_host(parent);
422	if (!parent_domain) {
423		dev_err(&pdev->dev, "cannot find parent domain\n");
424		return -ENODEV;
425	}
426
427	rzg2l_irqc_data = devm_kzalloc(&pdev->dev, sizeof(*rzg2l_irqc_data), GFP_KERNEL);
428	if (!rzg2l_irqc_data)
429		return -ENOMEM;
430
431	rzg2l_irqc_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
432	if (IS_ERR(rzg2l_irqc_data->base))
433		return PTR_ERR(rzg2l_irqc_data->base);
434
435	ret = rzg2l_irqc_parse_interrupts(rzg2l_irqc_data, node);
436	if (ret) {
437		dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
438		return ret;
439	}
440
441	resetn = devm_reset_control_get_exclusive(&pdev->dev, NULL);
442	if (IS_ERR(resetn))
443		return PTR_ERR(resetn);
444
445	ret = reset_control_deassert(resetn);
446	if (ret) {
447		dev_err(&pdev->dev, "failed to deassert resetn pin, %d\n", ret);
448		return ret;
449	}
450
451	pm_runtime_enable(&pdev->dev);
452	ret = pm_runtime_resume_and_get(&pdev->dev);
453	if (ret < 0) {
454		dev_err(&pdev->dev, "pm_runtime_resume_and_get failed: %d\n", ret);
455		goto pm_disable;
456	}
457
458	raw_spin_lock_init(&rzg2l_irqc_data->lock);
459
460	irq_domain = irq_domain_add_hierarchy(parent_domain, 0, IRQC_NUM_IRQ,
461					      node, &rzg2l_irqc_domain_ops,
462					      rzg2l_irqc_data);
463	if (!irq_domain) {
464		dev_err(&pdev->dev, "failed to add irq domain\n");
465		ret = -ENOMEM;
466		goto pm_put;
467	}
468
469	register_syscore_ops(&rzg2l_irqc_syscore_ops);
470
471	return 0;
472
473pm_put:
474	pm_runtime_put(&pdev->dev);
475pm_disable:
476	pm_runtime_disable(&pdev->dev);
477	reset_control_assert(resetn);
478	return ret;
479}
480
481IRQCHIP_PLATFORM_DRIVER_BEGIN(rzg2l_irqc)
482IRQCHIP_MATCH("renesas,rzg2l-irqc", rzg2l_irqc_init)
483IRQCHIP_PLATFORM_DRIVER_END(rzg2l_irqc)
484MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
485MODULE_DESCRIPTION("Renesas RZ/G2L IRQC Driver");
486