[PATCH v2 1/2] sunxi: A523: Move NSI init routine into generic function
Jernej Škrabec
jernej.skrabec at gmail.com
Sun May 3 10:07:05 CEST 2026
Dne četrtek, 30. april 2026 ob 15:58:37 Srednjeevropski poletni čas je Andre Przywara napisal(a):
> In previous generations of Allwinner SoCs, the memory bus (MBUS) access
> arbitration was configured as part of the DRAM top registers. This is no
> longer the case with for instance the A133 or A523, which have a dedicated
> base address for the bus arbiter that is now called NSI instead of MBUS.
>
> NSI appears to be a later iteration of MBUS design, with new dedicated
> registers that resemble the previous MBUS ones. Despite NSI not being
> documented in the manual, the A133 BSP includes a nsi driver with some
> description of the registers. Like previous generations, it implements
> port arbitration priority for DRAM access and also supports an optional
> QoS mode based on bandwidth limits.
>
> In preparation for re-using code for other SoCs, factor out the existing
> NSI init routine from the A523 DRAM code, which was a bit ad-hoc and A523
> specific, into a separate function, and abstract the settings a bit.
> No functional change.
>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Co-develeoped-by: Paul Kocialkowski <paulk at sys-base.io>
> Suggested-by: Jernej Škrabec <jernej.skrabec at gmail.com>
> Sponsored-by: MEC Electronics GmbH <https://www.mec.at/>
> ---
> .../include/asm/arch-sunxi/cpu_sunxi_ncat2.h | 1 +
> .../include/asm/arch-sunxi/dram_sun55i_a523.h | 29 +++++++++++
> arch/arm/include/asm/arch-sunxi/sunxi_nsi.h | 25 ++++++++++
> arch/arm/mach-sunxi/Makefile | 2 +-
> arch/arm/mach-sunxi/dram_sun55i_a523.c | 49 +++++++++----------
> arch/arm/mach-sunxi/sunxi_nsi.c | 31 ++++++++++++
> 6 files changed, 110 insertions(+), 27 deletions(-)
> create mode 100644 arch/arm/include/asm/arch-sunxi/sunxi_nsi.h
> create mode 100644 arch/arm/mach-sunxi/sunxi_nsi.c
>
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
> index 7cee7efe8b4..fd7d9b22058 100644
> --- a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
> +++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
> @@ -9,6 +9,7 @@
>
> #define SUNXI_TZPC_BASE 0x02000800
> #define SUNXI_CCM_BASE 0x02001000
> +#define SUNXI_NSI_BASE 0x02020000
> #define SUNXI_TIMER_BASE 0x02050000
>
> #define SUNXI_TWI0_BASE 0x02502000
> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun55i_a523.h b/arch/arm/include/asm/arch-sunxi/dram_sun55i_a523.h
> index 08bfe462856..462d4726a21 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram_sun55i_a523.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun55i_a523.h
> @@ -20,6 +20,35 @@ enum sunxi_dram_type {
> #define MCTL_COM_UNK_008 0x008
> #define MCTL_COM_MAER0 0x020
>
> +enum sunxi_nsi_port {
> + SUNXI_NSI_PORT_GPU = 0,
> + SUNXI_NSI_PORT_GIC, = 1,
> + SUNXI_NSI_PORT_USB3, = 2,
> + SUNXI_NSI_PORT_PCIE, = 3,
> + SUNXI_NSI_PORT_CE, = 4,
> + SUNXI_NSI_PORT_NPU, = 5,
> + SUNXI_NSI_PORT_ISP, = 6,
> + SUNXI_NSI_PORT_DSP, = 7,
> + SUNXI_NSI_PORT_G2D, = 8,
> + SUNXI_NSI_PORT_DI, = 9,
> + SUNXI_NSI_PORT_IOMMU, = 10,
> + SUNXI_NSI_PORT_VE_R, = 11,
> + SUNXI_NSI_PORT_VE_RW, = 12,
> + SUNXI_NSI_PORT_DE, = 13,
> + SUNXI_NSI_PORT_CSI, = 14,
> + SUNXI_NSI_PORT_GMAC0, = 18,
> + SUNXI_NSI_PORT_GMAC1, = 19,
> + SUNXI_NSI_PORT_MMC0, = 20,
> + SUNXI_NSI_PORT_MMC1, = 21,
> + SUNXI_NSI_PORT_MMC2, = 22,
> + SUNXI_NSI_PORT_USB0, = 23,
> + SUNXI_NSI_PORT_USB1, = 24,
> + SUNXI_NSI_PORT_USB2, = 25,
> + SUNXI_NSI_PORT_NPD, = 26,
> + SUNXI_NSI_PORT_DMAC, = 27,
> + SUNXI_NSI_PORT_DMA, = 28,
> +};
> +
> /*
> * Controller registers seems to be the same or at least very similar
> * to those in H6.
> diff --git a/arch/arm/include/asm/arch-sunxi/sunxi_nsi.h b/arch/arm/include/asm/arch-sunxi/sunxi_nsi.h
> new file mode 100644
> index 00000000000..7d41f9318b5
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/sunxi_nsi.h
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * A133/A523 NSI interconnect register and constant defines
> + *
> + * (C) Copyright 2026 Arm Ltd.
> + */
> +
> +#ifndef SUNXI_NSI_H__
> +#define SUNXI_NSI_H__
> +
> +#define SUNXI_NSI_PRI_CFG_LOWEST 0
> +#define SUNXI_NSI_PRI_CFG_LOW 1
> +#define SUNXI_NSI_PRI_CFG_HIGH 2
> +#define SUNXI_NSI_PRI_CFG_HIGHEST 3
> +
> +#define SUNXI_NSI_IO_CFG_QOS_SEL_OUTPUT 0
> +#define SUNXI_NSI_IO_CFG_QOS_SEL_INPUT 1
> +
> +#define NSI_CONF(port, pri, qos_sel) \
> + { SUNXI_NSI_PORT_ ## port, SUNXI_NSI_PRI_CFG_ ## pri, \
> + SUNXI_NSI_IO_CFG_QOS_SEL_ ## qos_sel }
> +
> +void nsi_configure_port(unsigned int port, u8 pri, u8 qos_sel);
> +
> +#endif /* SUNXI_NSI_H__ */
> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> index 0bee04d660f..3ef0113ea43 100644
> --- a/arch/arm/mach-sunxi/Makefile
> +++ b/arch/arm/mach-sunxi/Makefile
> @@ -50,6 +50,6 @@ obj-$(CONFIG_DRAM_SUN50I_H616) += dram_sun50i_h616.o dram_dw_helpers.o
> obj-$(CONFIG_DRAM_SUN50I_H616) += dram_timings/
> obj-$(CONFIG_DRAM_SUN50I_A133) += dram_sun50i_a133.o
> obj-$(CONFIG_DRAM_SUN50I_A133) += dram_timings/
> -obj-$(CONFIG_MACH_SUN55I_A523) += dram_sun55i_a523.o dram_dw_helpers.o
> +obj-$(CONFIG_MACH_SUN55I_A523) += dram_sun55i_a523.o dram_dw_helpers.o sunxi_nsi.o
> obj-$(CONFIG_DRAM_SUN55I_A523) += dram_timings/
> endif
> diff --git a/arch/arm/mach-sunxi/dram_sun55i_a523.c b/arch/arm/mach-sunxi/dram_sun55i_a523.c
> index 1ffb62863e2..9fb054cea84 100644
> --- a/arch/arm/mach-sunxi/dram_sun55i_a523.c
> +++ b/arch/arm/mach-sunxi/dram_sun55i_a523.c
> @@ -15,6 +15,7 @@
> #include <asm/arch/dram_dw_helpers.h>
> #include <asm/arch/cpu.h>
> #include <asm/arch/prcm.h>
> +#include <asm/arch/sunxi_nsi.h>
> #include <linux/bitops.h>
> #include <linux/delay.h>
>
> @@ -1412,40 +1413,36 @@ static const struct dram_para para = {
> .tpr10 = CONFIG_DRAM_SUNXI_TPR10,
> };
>
> -static void sunxi_nsi_init(void)
> +static void nsi_set_master_priority(void)
> {
> - /* IOMMU prio 3 */
> - writel(0x1, 0x02021418);
> - writel(0xf, 0x02021414);
> - /* DE prio 2 */
> - writel(0x1, 0x02021a18);
> - writel(0xa, 0x02021a14);
> - /* VE R prio 2 */
> - writel(0x1, 0x02021618);
> - writel(0xa, 0x02021614);
> - /* VE RW prio 2 */
> - writel(0x1, 0x02021818);
> - writel(0xa, 0x02021814);
> - /* ISP prio 2 */
> - writel(0x1, 0x02020c18);
> - writel(0xa, 0x02020c14);
> - /* CSI prio 2 */
> - writel(0x1, 0x02021c18);
> - writel(0xa, 0x02021c14);
> - /* NPU prio 2 */
> - writel(0x1, 0x02020a18);
> - writel(0xa, 0x02020a14);
> + struct {
> + unsigned int port;
> + u8 pri;
> + u8 qos_sel;
What about introducing above struct in sunxi_nsi.h? I imagine same pattern
will be used in future code.
> + } ports[] = {
> + NSI_CONF(NPU, HIGH, INPUT),
> + NSI_CONF(ISP, HIGH, INPUT),
> + NSI_CONF(IOMMU, HIGHEST, INPUT),
> + NSI_CONF(VE_R, HIGH, INPUT),
> + NSI_CONF(VE_RW, HIGH, INPUT),
> + NSI_CONF(DE, HIGH, INPUT),
> + NSI_CONF(CSI, HIGH, INPUT),
> + };
> + unsigned int i;
> +
> + for (i = 0; i < ARRAY_SIZE(ports); i++)
> + nsi_configure_port(ports[i].port, ports[i].pri,
> + ports[i].qos_sel);
>
> /* close ra0 autogating */
> - writel(0x0, 0x02023c00);
> + writel(0x0, 0x02023c00); /* port 30 */
> /* close ta autogating */
> - writel(0x0, 0x02023e00);
> + writel(0x0, 0x02023e00); /* port 31 */
> /* close pcie autogating */
> writel(0x0, 0x02020600);
Use SUNXI_NSI_BASE + ... above
Best regards,
Jernej
> }
>
> static void init_something(void)
> -
> {
> u32 *ptr = (u32 *)0x02000804;
>
> @@ -1507,7 +1504,7 @@ unsigned long sunxi_dram_init(void)
>
> size = mctl_calc_size(&config);
>
> - sunxi_nsi_init();
> + nsi_set_master_priority();
> init_something();
>
> return size;
> diff --git a/arch/arm/mach-sunxi/sunxi_nsi.c b/arch/arm/mach-sunxi/sunxi_nsi.c
> new file mode 100644
> index 00000000000..3d7eb43df46
> --- /dev/null
> +++ b/arch/arm/mach-sunxi/sunxi_nsi.c
> @@ -0,0 +1,31 @@
> +#include <asm/io.h>
> +#include <asm/arch/cpu.h>
> +#include <asm/arch/sunxi_nsi.h>
> +
> +#define SUNXI_NSI_MODE_REG(i) ((i) * 0x200 + 0x10)
> +#define SUNXI_NSI_PRI_CFG_REG(i) ((i) * 0x200 + 0x14)
> +#define SUNXI_NSI_PRI_CFG_RD(v) (((v) & 0x3) << 2)
> +#define SUNXI_NSI_PRI_CFG_WR(v) ((v) & 0x3)
> +#define SUNXI_NSI_IO_CFG_REG(i) ((i) * 0x200 + 0x18)
> +#define SUNXI_NSI_ENABLE_REG(i) ((i) * 0x200 + 0xc0)
> +
> +void nsi_configure_port(unsigned int port, u8 pri, u8 qos_sel)
> +{
> + void *base = (void *)SUNXI_NSI_BASE;
> + u32 pri_cfg;
> +
> + /* QoS with bandwidth limits is not supported, disable it. */
> + writel(0, base + SUNXI_NSI_MODE_REG(port));
> + writel(0, base + SUNXI_NSI_ENABLE_REG(port));
> +
> + /*
> + * QoS direction selection should not be in use, but set it nevertheless
> + * to match the BSP behavior (in case it has some other meaning).
> + */
> + writel(qos_sel, base + SUNXI_NSI_IO_CFG_REG(port));
> +
> + /* Port priority is always active. */
> + pri_cfg = SUNXI_NSI_PRI_CFG_RD(pri) | SUNXI_NSI_PRI_CFG_WR(pri);
> +
> + writel(pri_cfg, base + SUNXI_NSI_PRI_CFG_REG(port));
> +}
>
More information about the U-Boot
mailing list