On Thu, Feb 20, 2025 at 3:06 PM Fabrizio Castro <fabrizio.castro.jz@xxxxxxxxxxx> wrote: > > On the Renesas RZ/V2H(P) family of SoCs, DMAC IPs are connected > to the Interrupt Control Unit (ICU). > For DMA transfers, a request number and an ack number must be > registered with the ICU, which means that the DMAC driver has > to be able to instruct the ICU driver with the registration of > such ids. > > Export rzv2h_icu_register_dma_req_ack() so that the DMA driver > can register both ids in one go. > > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@xxxxxxxxxxx> > Reviewed-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > --- > v3->v4: > * No change. > v2->v3: > * Replaced rzv2h_icu_register_dma_req_ack with > rzv2h_icu_register_dma_req_ack() in changelog. > * Added dummy for rzv2h_icu_register_dma_req_ack(). > * Added Rb Thomas. > v1->v2: > * Improved macros. > * Shared new macros for minimum values. > --- > drivers/irqchip/irq-renesas-rzv2h.c | 56 +++++++++++++++++++++++ > include/linux/irqchip/irq-renesas-rzv2h.h | 26 +++++++++++ > 2 files changed, 82 insertions(+) > create mode 100644 include/linux/irqchip/irq-renesas-rzv2h.h > Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx> Cheers, Prabhakar > diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c > index fe2d29e91026..a8e9feda73b0 100644 > --- a/drivers/irqchip/irq-renesas-rzv2h.c > +++ b/drivers/irqchip/irq-renesas-rzv2h.c > @@ -15,6 +15,7 @@ > #include <linux/err.h> > #include <linux/io.h> > #include <linux/irqchip.h> > +#include <linux/irqchip/irq-renesas-rzv2h.h> > #include <linux/irqdomain.h> > #include <linux/of_address.h> > #include <linux/of_platform.h> > @@ -41,6 +42,8 @@ > #define ICU_TSCLR 0x24 > #define ICU_TITSR(k) (0x28 + (k) * 4) > #define ICU_TSSR(k) (0x30 + (k) * 4) > +#define ICU_DMkSELy(k, y) (0x420 + (k) * 0x20 + (y) * 4) > +#define ICU_DMACKSELk(k) (0x500 + (k) * 4) > > /* NMI */ > #define ICU_NMI_EDGE_FALLING 0 > @@ -80,6 +83,19 @@ > #define ICU_TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x)) > #define ICU_PB5_TINT 0x55 > > +/* DMAC */ > +#define ICU_DMAC_DkRQ_SEL_MASK GENMASK(9, 0) > + > +#define ICU_DMAC_DMAREQ_SHIFT(up) ((up) * 16) > +#define ICU_DMAC_DMAREQ_MASK(up) (ICU_DMAC_DkRQ_SEL_MASK \ > + << ICU_DMAC_DMAREQ_SHIFT(up)) > +#define ICU_DMAC_PREP_DMAREQ(sel, up) (FIELD_PREP(ICU_DMAC_DkRQ_SEL_MASK, (sel)) \ > + << ICU_DMAC_DMAREQ_SHIFT(up)) > + > +#define ICU_DMAC_DACK_SEL_SHIFT(field_no) ((field_no) * 8) > +#define ICU_DMAC_DACK_SEL_MASK(field_no) (GENMASK(6, 0) << ICU_DMAC_DACK_SEL_SHIFT(field_no)) > +#define ICU_DMAC_PREP_DACK_SEL(sel, field_no) ((sel) << ICU_DMAC_DACK_SEL_SHIFT(field_no)) > + > /** > * struct rzv2h_icu_priv - Interrupt Control Unit controller private data structure. > * @base: Controller's base address > @@ -94,6 +110,45 @@ struct rzv2h_icu_priv { > raw_spinlock_t lock; > }; > > +void rzv2h_icu_register_dma_req_ack(struct platform_device *icu_dev, u8 dmac_index, u8 dmac_channel, > + u16 req_no, u8 ack_no) > +{ > + struct rzv2h_icu_priv *priv = platform_get_drvdata(icu_dev); > + u32 icu_dmackselk, dmaack, dmaack_mask; > + u32 icu_dmksely, dmareq, dmareq_mask; > + u8 k, field_no; > + u8 y, upper; > + > + if (req_no >= RZV2H_ICU_DMAC_REQ_NO_MIN_FIX_OUTPUT) > + req_no = RZV2H_ICU_DMAC_REQ_NO_DEFAULT; > + > + if (ack_no >= RZV2H_ICU_DMAC_ACK_NO_MIN_FIX_OUTPUT) > + ack_no = RZV2H_ICU_DMAC_ACK_NO_DEFAULT; > + > + y = dmac_channel / 2; > + upper = dmac_channel % 2; > + > + dmareq = ICU_DMAC_PREP_DMAREQ(req_no, upper); > + dmareq_mask = ICU_DMAC_DMAREQ_MASK(upper); > + > + k = ack_no / 4; > + field_no = ack_no % 4; > + > + dmaack_mask = ICU_DMAC_DACK_SEL_MASK(field_no); > + dmaack = ICU_DMAC_PREP_DACK_SEL(ack_no, field_no); > + > + guard(raw_spinlock_irqsave)(&priv->lock); > + > + icu_dmksely = readl(priv->base + ICU_DMkSELy(dmac_index, y)); > + icu_dmksely = (icu_dmksely & ~dmareq_mask) | dmareq; > + writel(icu_dmksely, priv->base + ICU_DMkSELy(dmac_index, y)); > + > + icu_dmackselk = readl(priv->base + ICU_DMACKSELk(k)); > + icu_dmackselk = (icu_dmackselk & ~dmaack_mask) | dmaack; > + writel(icu_dmackselk, priv->base + ICU_DMACKSELk(k)); > +} > +EXPORT_SYMBOL_GPL(rzv2h_icu_register_dma_req_ack); > + > static inline struct rzv2h_icu_priv *irq_data_to_priv(struct irq_data *data) > { > return data->domain->host_data; > @@ -446,6 +501,7 @@ static int rzv2h_icu_init(struct device_node *node, struct device_node *parent) > goto put_dev; > } > > + platform_set_drvdata(pdev, rzv2h_icu_data); > rzv2h_icu_data->irqchip = &rzv2h_icu_chip; > > rzv2h_icu_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL); > diff --git a/include/linux/irqchip/irq-renesas-rzv2h.h b/include/linux/irqchip/irq-renesas-rzv2h.h > new file mode 100644 > index 000000000000..d06e01bf969b > --- /dev/null > +++ b/include/linux/irqchip/irq-renesas-rzv2h.h > @@ -0,0 +1,26 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Renesas RZ/V2H(P) Interrupt Control Unit (ICU) > + * > + * Copyright (C) 2025 Renesas Electronics Corporation. > + */ > + > +#ifndef __LINUX_IRQ_RENESAS_RZV2H > +#define __LINUX_IRQ_RENESAS_RZV2H > + > +#include <linux/platform_device.h> > + > +#define RZV2H_ICU_DMAC_REQ_NO_DEFAULT 0x3ff > +#define RZV2H_ICU_DMAC_ACK_NO_DEFAULT 0x7f > +#define RZV2H_ICU_DMAC_REQ_NO_MIN_FIX_OUTPUT 0x1b5 > +#define RZV2H_ICU_DMAC_ACK_NO_MIN_FIX_OUTPUT 0x50 > + > +#ifdef CONFIG_RENESAS_RZV2H_ICU > +void rzv2h_icu_register_dma_req_ack(struct platform_device *icu_dev, u8 dmac_index, u8 dmac_channel, > + u16 req_no, u8 ack_no); > +#else > +static inline void rzv2h_icu_register_dma_req_ack(struct platform_device *icu_dev, u8 dmac_index, > + u8 dmac_channel, u16 req_no, u8 ack_no) { } > +#endif > + > +#endif > -- > 2.34.1 > >