Merge patch series "arm: airoha: add support for en7523 based boards"

Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu> says:

This patch series adds basic support for the boards based on Airoha
EN7523/EN7529/EN7562 SoCs. Due to ATF restrictions these boards are
able to run 32-bit OS only.

This patch series adds support for the following hardware:
 * console UART
 * ethernet controller/switch
 * spinand flash (in non-dma mode)

The following issues may be expected:
 * Extra slow UBI attaching in U-Boot (up to 20 sec with fastmap enabled).
   This is caused by the lack of DMA support in the U-Boot airoha-snfi driver.
 * Linux airoha-snfi driver in some cases might damage you flash data
   (see: https://lore.kernel.org/lkml/20251012121707.2296160-15-mikhail.kshevetskiy@iopsys.eu/)
 * Latest linux kernel is recommended to properly support flashes
   with more than one plane per lun
   (see: https://lore.kernel.org/lkml/20251012121707.2296160-7-mikhail.kshevetskiy@iopsys.eu/)
 * It's NOT recommended to use flashes working in continuous mode because
   U-Boot airoha-snfi driver does not support such flashes properly.

The patches was tested on the board:
 - SoC: Airoha EN7562
 - RAM: 512 MB
 - SPI NAND: 4 Gbit, made by Toshiba
 - Linux boot: was NOT tested

The U-Boot was chain-loaded from the running U-Boot. Airoha ATF-2.3 does
not allow easily chain-loading of U-Boot from U-Boot, so a special FIT
image (mimic linux kernel) was created

1) Create u-boot.its file with the following contents:

=== cut here ===
/dts-v1/;

/ {
	description = "ARM OpenWrt FIT (Flattened Image Tree)";
	#address-cells = <1>;

	images {
		u-boot-ram {
			description = "OpenWrt U-Boot RAM image";
			data = /incbin/("u-boot.bin.lzma");
			type = "kernel";
			arch = "arm";
			os = "linux";
			compression = "lzma";
			load = <0x81e00000>;
			entry = <0x81e00000>;
			hash@1 {
				algo = "crc32";
			};
			hash@2 {
				algo = "sha1";
			};
		};

		fdt-1 {
			description = "OpenWrt device tree blob";

			data = /incbin/("dts/upstream/src/arm/airoha/en7523-evb.dtb");
			type = "flat_dt";

			arch = "arm";
			compression = "none";
			hash@1 {
				algo = "crc32";
			};
			hash@2 {
				algo = "sha1";
			};
		};
	};

	configurations {
		default = "config-ram-uboot";
		config-ram-uboot {
			description = "OpenWrt RAM U-Boot";
			kernel = "u-boot-ram";
			fdt = "fdt-1";
		};
	};
};
==================

2) Create u-boot.itb image to chain-load new u-boot from the old one

  lzma_alone e u-boot.bin u-boot.bin.lzma
  mkimage -f u-boot.its u-boot.itb

3) Load new u-boot from the old one

  U-Boot> tftpboot u-boot.itb && bootm

Link: https://lore.kernel.org/r/20251101004503.2379529-1-mikhail.kshevetskiy@iopsys.eu
This commit is contained in:
Tom Rini
2025-11-07 16:04:16 -06:00
22 changed files with 646 additions and 55 deletions

View File

@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0+
/ {
/* When running as a first-stage bootloader this isn't filled in automatically */
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>;
};
};
#include "en7523-u-boot.dtsi"

View File

@@ -0,0 +1,70 @@
// SPDX-License-Identifier: GPL-2.0+
#include <dt-bindings/reset/airoha,en7523-reset.h>
/ {
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
atf-reserved-memory@80000000 {
no-map;
reg = <0x80000000 0x40000>;
};
};
scu: system-controller@1fa20000 {
compatible = "airoha,en7523-scu";
reg = <0x1fa20000 0x400>,
<0x1fb00000 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
eth: ethernet@1fb50000 {
compatible = "airoha,en7523-eth";
reg = <0x1fb50000 0x2600>,
<0x1fb54000 0x2000>,
<0x1fb56000 0x2000>;
reg-names = "fe", "qdma0", "qdma1";
resets = <&scu EN7523_FE_RST>,
<&scu EN7523_FE_PDMA_RST>,
<&scu EN7523_FE_QDMA_RST>,
<&scu EN7523_DUAL_HSI0_MAC_RST>,
<&scu EN7523_DUAL_HSI1_MAC_RST>,
<&scu EN7523_HSI_MAC_RST>;
reset-names = "fe", "pdma", "qdma",
"hsi0-mac", "hsi1-mac", "hsi-mac";
};
switch: switch@1fb58000 {
compatible = "airoha,en7523-switch";
reg = <0x1fb58000 0x8000>;
};
snfi: spi@1fa10000 {
compatible = "airoha,en7523-snand", "airoha,en7581-snand";
reg = <0x1fa10000 0x140>,
<0x1fa11000 0x600>;
clocks = <&scu EN7523_CLK_SPI>;
clock-names = "spi";
#address-cells = <1>;
#size-cells = <0>;
spi_nand: nand@0 {
compatible = "spi-nand";
reg = <0>;
spi-max-frequency = <50000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
};
};
};
&uart1 {
bootph-all;
};

View File

@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
*/
#ifndef __AIROHA_SCU_REGMAP__
#define __AIROHA_SCU_REGMAP__
#include <regmap.h>
struct regmap *airoha_get_scu_regmap(void);
struct regmap *airoha_get_chip_scu_regmap(void);
#endif

View File

@@ -0,0 +1 @@
arch-airoha

View File

@@ -0,0 +1 @@
arch-airoha

View File

@@ -6,6 +6,17 @@ config SYS_VENDOR
choice
prompt "Airoha board select"
config TARGET_EN7523
bool "Airoha EN7523 SoC"
select CPU_V7A
select ARMV7_SET_CORTEX_SMPEN
help
The Airoha EN7523 family (en7523/en7529/en7562) is an ARM-based
SoCs with a dual-core CPU. It comes with Wi-Fi 5/6 support and
connectivity to Ethernet PHY, DDR, PCIe, USB, UART and VoIP.
With advanced hardware design, EN7523 provides high processing
performance and low power consumption.
config TARGET_AN7581
bool "Airoha AN7581 SoC"
select ARM64
@@ -20,12 +31,15 @@ config TARGET_AN7581
endchoice
config SYS_SOC
default "en7523" if TARGET_EN7523
default "an7581" if TARGET_AN7581
config SYS_BOARD
default "en7523" if TARGET_EN7523
default "an7581" if TARGET_AN7581
config SYS_CONFIG_NAME
default "en7523" if TARGET_EN7523
default "an7581" if TARGET_AN7581
endif

View File

@@ -2,4 +2,5 @@
obj-y += cpu.o
obj-$(CONFIG_TARGET_EN7523) += en7523/
obj-$(CONFIG_TARGET_AN7581) += an7581/

View File

@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += init.o
obj-y += scu-regmap.o

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
*/
#include <syscon.h>
#include <linux/err.h>
#include <asm/arch/scu-regmap.h>
struct regmap *airoha_get_scu_regmap(void)
{
ofnode node;
node = ofnode_by_compatible(ofnode_null(), "airoha,en7581-scu");
if (!ofnode_valid(node))
return ERR_PTR(-EINVAL);
return syscon_node_to_regmap(node);
}
struct regmap *airoha_get_chip_scu_regmap(void)
{
ofnode node;
node = ofnode_by_compatible(ofnode_null(), "airoha,en7581-chip-scu");
if (!ofnode_valid(node))
return ERR_PTR(-EINVAL);
return syscon_node_to_regmap(node);
}

View File

@@ -0,0 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += init.o
obj-y += scu-regmap.o

View File

@@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
*/
#include <fdtdec.h>
#include <init.h>
#include <sysreset.h>
#include <asm/system.h>
#include <linux/io.h>
int print_cpuinfo(void)
{
printf("CPU: Airoha EN7523/EN7529/EN7562\n");
return 0;
}
int dram_init(void)
{
return fdtdec_setup_mem_size_base();
}
int dram_init_banksize(void)
{
return fdtdec_setup_memory_banksize();
}
void __noreturn reset_cpu(void)
{
writel(0x80000000, 0x1FB00040);
while (1) {
/* loop forever */
}
}

View File

@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
*/
#include <dm/ofnode.h>
#include <linux/err.h>
#include <asm/arch/scu-regmap.h>
static struct regmap *airoha_scu_node_regmap_by_index(unsigned int index)
{
struct regmap *map;
ofnode node;
int err;
node = ofnode_by_compatible(ofnode_null(), "airoha,en7523-scu");
if (!ofnode_valid(node))
return ERR_PTR(-EINVAL);
/* CHIP_SCU (index=0), SCU (index=1) */
err = regmap_init_mem_index(node, &map, index);
if (err)
return ERR_PTR(err);
return map;
}
struct regmap *airoha_get_scu_regmap(void)
{
/* CHIP_SCU (index=0), SCU (index=1) */
return airoha_scu_node_regmap_by_index(1);
}
struct regmap *airoha_get_chip_scu_regmap(void)
{
/* CHIP_SCU (index=0), SCU (index=1) */
return airoha_scu_node_regmap_by_index(0);
}

View File

@@ -0,0 +1,4 @@
EN7523
M: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
S: Maintained
N: en7523

View File

@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += en7523_rfb.o

View File

@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Author: Christian Marangi <ansuelsmth@gmail.com>
*/
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
int board_init(void)
{
/* address of boot parameters */
gd->bd->bi_boot_params = CFG_SYS_SDRAM_BASE + 0x100;
return 0;
}

View File

@@ -1,5 +1,6 @@
CONFIG_ARM=y
CONFIG_ARCH_AIROHA=y
CONFIG_TARGET_AN7581=y
CONFIG_TEXT_BASE=0x81E00000
CONFIG_SYS_MALLOC_F_LEN=0x4000
CONFIG_NR_DRAM_BANKS=1

View File

@@ -0,0 +1,67 @@
CONFIG_ARM=y
CONFIG_SYS_ARCH_TIMER=y
CONFIG_ARCH_AIROHA=y
CONFIG_TARGET_EN7523=y
CONFIG_TEXT_BASE=0x81E00000
CONFIG_SYS_MALLOC_F_LEN=0x4000
CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_MTD_DEV="spi-nand0"
CONFIG_ENV_SIZE=0x4000
CONFIG_ENV_OFFSET=0x7c000
CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="airoha/en7523-evb"
CONFIG_SYS_LOAD_ADDR=0x81800000
CONFIG_BUILD_TARGET="u-boot.bin"
# CONFIG_EFI_LOADER is not set
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_BOOTDELAY=3
CONFIG_DEFAULT_FDT_FILE="en7523-evb"
CONFIG_SYS_PBSIZE=1049
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="U-Boot> "
CONFIG_SYS_MAXARGS=8
CONFIG_CMD_BOOTZ=y
CONFIG_CMD_BOOTMENU=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
CONFIG_CMD_BIND=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_MTD=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_PING=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_CMD_MTDPARTS=y
CONFIG_CMD_LOG=y
CONFIG_OF_UPSTREAM=y
CONFIG_ENV_OVERWRITE=y
CONFIG_ENV_IS_IN_MTD=y
CONFIG_ENV_RELOC_GD_ENV_ADDR=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SYS_RX_ETH_BUFFER=8
CONFIG_REGMAP=y
CONFIG_CLK=y
CONFIG_DM_RESET=y
CONFIG_DMA=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
# CONFIG_MMC is not set
CONFIG_MTD=y
CONFIG_DM_MTD=y
CONFIG_MTD_SPI_NAND=y
CONFIG_AIROHA_ETH=y
CONFIG_PHY=y
CONFIG_PINCTRL=y
CONFIG_PINCONF=y
CONFIG_RAM=y
CONFIG_DM_SERIAL=y
CONFIG_SYS_NS16550=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_AIROHA_SNFI_SPI=y
CONFIG_SHA512=y

View File

@@ -16,7 +16,7 @@
#include <dm/device_compat.h>
#include <dm/lists.h>
#include <regmap.h>
#include <syscon.h>
#include <asm/arch/scu-regmap.h>
#include <dt-bindings/clock/en7523-clk.h>
@@ -26,6 +26,7 @@
#define REG_SPI_CLK_DIV_SEL 0x1c4
#define REG_SPI_CLK_FREQ_SEL 0x1c8
#define REG_NPU_CLK_DIV_SEL 0x1fc
#define REG_CRYPTO_CLKSRC 0x200
#define REG_NP_SCU_PCIC 0x88
#define REG_NP_SCU_SSTR 0x9c
@@ -33,6 +34,7 @@
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
#define REG_CRYPTO_CLKSRC2 0x20c
#define EN7523_MAX_CLKS 8
#define EN7581_MAX_CLKS 9
struct airoha_clk_desc {
@@ -66,14 +68,119 @@ struct airoha_clk_soc_data {
};
static const u32 gsw_base[] = { 400000000, 500000000 };
static const u32 emi_base[] = { 333000000, 400000000 };
static const u32 bus_base[] = { 500000000, 540000000 };
static const u32 slic_base[] = { 100000000, 3125000 };
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
/* EN7581 */
static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
static const u32 bus7581_base[] = { 600000000, 540000000 };
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
static const u32 crypto_base[] = { 540000000, 480000000 };
static const u32 emmc7581_base[] = { 200000000, 150000000 };
static const struct airoha_clk_desc en7523_base_clks[EN7523_MAX_CLKS] = {
[EN7523_CLK_GSW] = {
.id = EN7523_CLK_GSW,
.name = "gsw",
.base_reg = REG_GSW_CLK_DIV_SEL,
.base_bits = 1,
.base_shift = 8,
.base_values = gsw_base,
.n_base_values = ARRAY_SIZE(gsw_base),
.div_bits = 3,
.div_shift = 0,
.div_step = 1,
.div_offset = 1,
},
[EN7523_CLK_EMI] = {
.id = EN7523_CLK_EMI,
.name = "emi",
.base_reg = REG_EMI_CLK_DIV_SEL,
.base_bits = 1,
.base_shift = 8,
.base_values = emi_base,
.n_base_values = ARRAY_SIZE(emi_base),
.div_bits = 3,
.div_shift = 0,
.div_step = 1,
.div_offset = 1,
},
[EN7523_CLK_BUS] = {
.id = EN7523_CLK_BUS,
.name = "bus",
.base_reg = REG_BUS_CLK_DIV_SEL,
.base_bits = 1,
.base_shift = 8,
.base_values = bus_base,
.n_base_values = ARRAY_SIZE(bus_base),
.div_bits = 3,
.div_shift = 0,
.div_step = 1,
.div_offset = 1,
},
[EN7523_CLK_SLIC] = {
.id = EN7523_CLK_SLIC,
.name = "slic",
.base_reg = REG_SPI_CLK_FREQ_SEL,
.base_bits = 1,
.base_shift = 0,
.base_values = slic_base,
.n_base_values = ARRAY_SIZE(slic_base),
.div_reg = REG_SPI_CLK_DIV_SEL,
.div_bits = 5,
.div_shift = 24,
.div_val0 = 20,
.div_step = 2,
},
[EN7523_CLK_SPI] = {
.id = EN7523_CLK_SPI,
.name = "spi",
.base_reg = REG_SPI_CLK_DIV_SEL,
.base_value = 400000000,
.div_bits = 5,
.div_shift = 8,
.div_val0 = 40,
.div_step = 2,
},
[EN7523_CLK_NPU] = {
.id = EN7523_CLK_NPU,
.name = "npu",
.base_reg = REG_NPU_CLK_DIV_SEL,
.base_bits = 2,
.base_shift = 8,
.base_values = npu_base,
.n_base_values = ARRAY_SIZE(npu_base),
.div_bits = 3,
.div_shift = 0,
.div_step = 1,
.div_offset = 1,
},
[EN7523_CLK_CRYPTO] = {
.id = EN7523_CLK_CRYPTO,
.name = "crypto",
.base_reg = REG_CRYPTO_CLKSRC,
.base_bits = 1,
.base_shift = 0,
.base_values = emi_base,
.n_base_values = ARRAY_SIZE(emi_base),
}
};
static const struct airoha_clk_desc en7581_base_clks[EN7581_MAX_CLKS] = {
[EN7523_CLK_GSW] = {
.id = EN7523_CLK_GSW,
@@ -400,14 +507,8 @@ const struct clk_ops airoha_clk_ops = {
static int airoha_clk_probe(struct udevice *dev)
{
struct airoha_clk_priv *priv = dev_get_priv(dev);
ofnode chip_scu_node;
chip_scu_node = ofnode_by_compatible(ofnode_null(),
"airoha,en7581-chip-scu");
if (!ofnode_valid(chip_scu_node))
return -EINVAL;
priv->chip_scu_map = syscon_node_to_regmap(chip_scu_node);
priv->chip_scu_map = airoha_get_chip_scu_regmap();
if (IS_ERR(priv->chip_scu_map))
return PTR_ERR(priv->chip_scu_map);
@@ -431,12 +532,20 @@ static int airoha_clk_bind(struct udevice *dev)
return ret;
}
static const struct airoha_clk_soc_data en7523_data = {
.num_clocks = ARRAY_SIZE(en7523_base_clks),
.descs = en7523_base_clks,
};
static const struct airoha_clk_soc_data en7581_data = {
.num_clocks = ARRAY_SIZE(en7581_base_clks),
.descs = en7581_base_clks,
};
static const struct udevice_id airoha_clk_ids[] = {
{ .compatible = "airoha,en7523-scu",
.data = (ulong)&en7523_data,
},
{ .compatible = "airoha,en7581-scu",
.data = (ulong)&en7581_data,
},

View File

@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/time.h>
#include <asm/arch/scu-regmap.h>
#define AIROHA_MAX_NUM_GDM_PORTS 1
#define AIROHA_MAX_NUM_QDMA 1
@@ -312,6 +313,25 @@ struct airoha_eth {
struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
};
struct airoha_eth_soc_data {
int num_xsi_rsts;
const char * const *xsi_rsts_names;
const char *switch_compatible;
};
static const char * const en7523_xsi_rsts_names[] = {
"hsi0-mac",
"hsi1-mac",
"hsi-mac",
};
static const char * const en7581_xsi_rsts_names[] = {
"hsi0-mac",
"hsi1-mac",
"hsi-mac",
"xfp-mac",
};
static u32 airoha_rr(void __iomem *base, u32 offset)
{
return readl(base + offset);
@@ -678,10 +698,12 @@ static int airoha_hw_init(struct udevice *dev,
static int airoha_switch_init(struct udevice *dev, struct airoha_eth *eth)
{
struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev);
ofnode switch_node;
fdt_addr_t addr;
switch_node = ofnode_by_compatible(ofnode_null(), "airoha,en7581-switch");
switch_node = ofnode_by_compatible(ofnode_null(),
data->switch_compatible);
if (!ofnode_valid(switch_node))
return -EINVAL;
@@ -718,16 +740,12 @@ static int airoha_switch_init(struct udevice *dev, struct airoha_eth *eth)
static int airoha_eth_probe(struct udevice *dev)
{
struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev);
struct airoha_eth *eth = dev_get_priv(dev);
struct regmap *scu_regmap;
ofnode scu_node;
int ret;
int i, ret;
scu_node = ofnode_by_compatible(ofnode_null(), "airoha,en7581-scu");
if (!ofnode_valid(scu_node))
return -EINVAL;
scu_regmap = syscon_node_to_regmap(scu_node);
scu_regmap = airoha_get_scu_regmap();
if (IS_ERR(scu_regmap))
return PTR_ERR(scu_regmap);
@@ -747,11 +765,11 @@ static int airoha_eth_probe(struct udevice *dev)
return -ENOMEM;
eth->rsts.count = AIROHA_MAX_NUM_RSTS;
eth->xsi_rsts.resets = devm_kcalloc(dev, AIROHA_MAX_NUM_XSI_RSTS,
eth->xsi_rsts.resets = devm_kcalloc(dev, data->num_xsi_rsts,
sizeof(struct reset_ctl), GFP_KERNEL);
if (!eth->xsi_rsts.resets)
return -ENOMEM;
eth->xsi_rsts.count = AIROHA_MAX_NUM_XSI_RSTS;
eth->xsi_rsts.count = data->num_xsi_rsts;
ret = reset_get_by_name(dev, "fe", &eth->rsts.resets[0]);
if (ret)
@@ -765,21 +783,12 @@ static int airoha_eth_probe(struct udevice *dev)
if (ret)
return ret;
ret = reset_get_by_name(dev, "hsi0-mac", &eth->xsi_rsts.resets[0]);
if (ret)
return ret;
ret = reset_get_by_name(dev, "hsi1-mac", &eth->xsi_rsts.resets[1]);
if (ret)
return ret;
ret = reset_get_by_name(dev, "hsi-mac", &eth->xsi_rsts.resets[2]);
if (ret)
return ret;
ret = reset_get_by_name(dev, "xfp-mac", &eth->xsi_rsts.resets[3]);
for (i = 0; i < data->num_xsi_rsts; i++) {
ret = reset_get_by_name(dev, data->xsi_rsts_names[i],
&eth->xsi_rsts.resets[i]);
if (ret)
return ret;
}
ret = airoha_hw_init(dev, eth);
if (ret)
@@ -973,8 +982,25 @@ static int arht_eth_write_hwaddr(struct udevice *dev)
return 0;
}
static const struct airoha_eth_soc_data en7523_data = {
.xsi_rsts_names = en7523_xsi_rsts_names,
.num_xsi_rsts = ARRAY_SIZE(en7523_xsi_rsts_names),
.switch_compatible = "airoha,en7523-switch",
};
static const struct airoha_eth_soc_data en7581_data = {
.xsi_rsts_names = en7581_xsi_rsts_names,
.num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names),
.switch_compatible = "airoha,en7581-switch",
};
static const struct udevice_id airoha_eth_ids[] = {
{ .compatible = "airoha,en7581-eth" },
{ .compatible = "airoha,en7523-eth",
.data = (ulong)&en7523_data,
},
{ .compatible = "airoha,en7581-eth",
.data = (ulong)&en7581_data,
},
{ }
};

View File

@@ -10,7 +10,10 @@
#include <dm.h>
#include <linux/io.h>
#include <reset-uclass.h>
#include <regmap.h>
#include <asm/arch/scu-regmap.h>
#include <dt-bindings/reset/airoha,en7523-reset.h>
#include <dt-bindings/reset/airoha,en7581-reset.h>
#define RST_NR_PER_BANK 32
@@ -21,7 +24,8 @@
struct airoha_reset_priv {
const u16 *bank_ofs;
const u16 *idx_map;
void __iomem *base;
int num_rsts;
struct regmap *map;
};
static const u16 en7581_rst_ofs[] = {
@@ -29,6 +33,53 @@ static const u16 en7581_rst_ofs[] = {
REG_RESET_CONTROL1,
};
static const u16 en7523_rst_map[] = {
/* RST_CTRL2 */
[EN7523_XPON_PHY_RST] = 0,
[EN7523_XSI_MAC_RST] = 7,
[EN7523_XSI_PHY_RST] = 8,
[EN7523_NPU_RST] = 9,
[EN7523_I2S_RST] = 10,
[EN7523_TRNG_RST] = 11,
[EN7523_TRNG_MSTART_RST] = 12,
[EN7523_DUAL_HSI0_RST] = 13,
[EN7523_DUAL_HSI1_RST] = 14,
[EN7523_HSI_RST] = 15,
[EN7523_DUAL_HSI0_MAC_RST] = 16,
[EN7523_DUAL_HSI1_MAC_RST] = 17,
[EN7523_HSI_MAC_RST] = 18,
[EN7523_WDMA_RST] = 19,
[EN7523_WOE0_RST] = 20,
[EN7523_WOE1_RST] = 21,
[EN7523_HSDMA_RST] = 22,
[EN7523_I2C2RBUS_RST] = 23,
[EN7523_TDMA_RST] = 24,
/* RST_CTRL1 */
[EN7523_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
[EN7523_FE_PDMA_RST] = RST_NR_PER_BANK + 1,
[EN7523_FE_QDMA_RST] = RST_NR_PER_BANK + 2,
[EN7523_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4,
[EN7523_CRYPTO_RST] = RST_NR_PER_BANK + 6,
[EN7523_TIMER_RST] = RST_NR_PER_BANK + 8,
[EN7523_PCM1_RST] = RST_NR_PER_BANK + 11,
[EN7523_UART_RST] = RST_NR_PER_BANK + 12,
[EN7523_GPIO_RST] = RST_NR_PER_BANK + 13,
[EN7523_GDMA_RST] = RST_NR_PER_BANK + 14,
[EN7523_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
[EN7523_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
[EN7523_SFC_RST] = RST_NR_PER_BANK + 18,
[EN7523_UART2_RST] = RST_NR_PER_BANK + 19,
[EN7523_GDMP_RST] = RST_NR_PER_BANK + 20,
[EN7523_FE_RST] = RST_NR_PER_BANK + 21,
[EN7523_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
[EN7523_GSW_RST] = RST_NR_PER_BANK + 23,
[EN7523_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
[EN7523_PCIE0_RST] = RST_NR_PER_BANK + 26,
[EN7523_PCIE1_RST] = RST_NR_PER_BANK + 27,
[EN7523_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
[EN7523_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
};
static const u16 en7581_rst_map[] = {
/* RST_CTRL2 */
[EN7581_XPON_PHY_RST] = 0,
@@ -90,17 +141,11 @@ static const u16 en7581_rst_map[] = {
static int airoha_reset_update(struct airoha_reset_priv *priv,
unsigned long id, bool assert)
{
void __iomem *addr = priv->base + priv->bank_ofs[id / RST_NR_PER_BANK];
u32 val;
u16 offset = priv->bank_ofs[id / RST_NR_PER_BANK];
val = readl(addr);
if (assert)
val |= BIT(id % RST_NR_PER_BANK);
else
val &= ~BIT(id % RST_NR_PER_BANK);
writel(val, addr);
return 0;
return regmap_update_bits(priv->map, offset,
BIT(id % RST_NR_PER_BANK),
assert ? BIT(id % RST_NR_PER_BANK) : 0);
}
static int airoha_reset_assert(struct reset_ctl *reset_ctl)
@@ -123,11 +168,16 @@ static int airoha_reset_status(struct reset_ctl *reset_ctl)
{
struct airoha_reset_priv *priv = dev_get_priv(reset_ctl->dev);
int id = reset_ctl->id;
void __iomem *addr;
u16 offset;
u32 val;
int ret;
addr = priv->base + priv->bank_ofs[id / RST_NR_PER_BANK];
offset = priv->bank_ofs[id / RST_NR_PER_BANK];
ret = regmap_read(priv->map, offset, &val);
if (ret)
return ret;
return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
return !!(val & BIT(id % RST_NR_PER_BANK));
}
static int airoha_reset_xlate(struct reset_ctl *reset_ctl,
@@ -135,7 +185,7 @@ static int airoha_reset_xlate(struct reset_ctl *reset_ctl,
{
struct airoha_reset_priv *priv = dev_get_priv(reset_ctl->dev);
if (args->args[0] >= ARRAY_SIZE(en7581_rst_map))
if (args->args[0] >= priv->num_rsts)
return -EINVAL;
reset_ctl->id = priv->idx_map[args->args[0]];
@@ -150,20 +200,36 @@ static struct reset_ops airoha_reset_ops = {
.rst_status = airoha_reset_status,
};
static int airoha_reset_probe(struct udevice *dev)
static int reset_init(struct udevice *dev, const u16 *rst_map, int num_rsts)
{
struct airoha_reset_priv *priv = dev_get_priv(dev);
priv->base = dev_remap_addr(dev);
if (!priv->base)
return -ENOMEM;
priv->map = airoha_get_scu_regmap();
if (IS_ERR(priv->map))
return PTR_ERR(priv->map);
priv->bank_ofs = en7581_rst_ofs;
priv->idx_map = en7581_rst_map;
priv->idx_map = rst_map;
priv->num_rsts = num_rsts;
return 0;
}
static int airoha_reset_probe(struct udevice *dev)
{
if (ofnode_device_is_compatible(dev_ofnode(dev),
"airoha,en7523-scu"))
return reset_init(dev, en7523_rst_map,
ARRAY_SIZE(en7523_rst_map));
if (ofnode_device_is_compatible(dev_ofnode(dev),
"airoha,en7581-scu"))
return reset_init(dev, en7581_rst_map,
ARRAY_SIZE(en7581_rst_map));
return -ENODEV;
}
U_BOOT_DRIVER(airoha_reset) = {
.name = "airoha-reset",
.id = UCLASS_RESET,

21
include/configs/en7523.h Normal file
View File

@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Configuration for Airoha EN7523
*
* Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
*/
#ifndef __EN7523_H
#define __EN7523_H
#include <linux/sizes.h>
#define CFG_SYS_UBOOT_BASE CONFIG_TEXT_BASE
#define CFG_SYS_INIT_RAM_ADDR CONFIG_TEXT_BASE
#define CFG_SYS_INIT_RAM_SIZE SZ_2M
/* DRAM */
#define CFG_SYS_SDRAM_BASE 0x80000000
#endif

View File

@@ -0,0 +1,61 @@
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
/*
* Copyright (C) 2024 iopsys Software Solutions AB.
* Copyright (C) 2025 Genexis AB.
*
* Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
*
* based on
* dts/upstream/include/dt-bindings/reset/airoha,en7581-reset.h
* by Lorenzo Bianconi <lorenzo@kernel.org>
*/
#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_
#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_
/* RST_CTRL2 */
#define EN7523_XPON_PHY_RST 0
#define EN7523_XSI_MAC_RST 1
#define EN7523_XSI_PHY_RST 2
#define EN7523_NPU_RST 3
#define EN7523_I2S_RST 4
#define EN7523_TRNG_RST 5
#define EN7523_TRNG_MSTART_RST 6
#define EN7523_DUAL_HSI0_RST 7
#define EN7523_DUAL_HSI1_RST 8
#define EN7523_HSI_RST 9
#define EN7523_DUAL_HSI0_MAC_RST 10
#define EN7523_DUAL_HSI1_MAC_RST 11
#define EN7523_HSI_MAC_RST 12
#define EN7523_WDMA_RST 13
#define EN7523_WOE0_RST 14
#define EN7523_WOE1_RST 15
#define EN7523_HSDMA_RST 16
#define EN7523_I2C2RBUS_RST 17
#define EN7523_TDMA_RST 18
/* RST_CTRL1 */
#define EN7523_PCM1_ZSI_ISI_RST 19
#define EN7523_FE_PDMA_RST 20
#define EN7523_FE_QDMA_RST 21
#define EN7523_PCM_SPIWP_RST 22
#define EN7523_CRYPTO_RST 23
#define EN7523_TIMER_RST 24
#define EN7523_PCM1_RST 25
#define EN7523_UART_RST 26
#define EN7523_GPIO_RST 27
#define EN7523_GDMA_RST 28
#define EN7523_I2C_MASTER_RST 29
#define EN7523_PCM2_ZSI_ISI_RST 30
#define EN7523_SFC_RST 31
#define EN7523_UART2_RST 32
#define EN7523_GDMP_RST 33
#define EN7523_FE_RST 34
#define EN7523_USB_HOST_P0_RST 35
#define EN7523_GSW_RST 36
#define EN7523_SFC2_PCM_RST 37
#define EN7523_PCIE0_RST 38
#define EN7523_PCIE1_RST 39
#define EN7523_PCIE_HB_RST 40
#define EN7523_XPON_MAC_RST 41
#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ */