diff options
| author | Tom Rini <[email protected]> | 2025-11-07 16:04:16 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-11-07 16:45:09 -0600 |
| commit | 5e5b630eef2eecfe898b2ce3e719a6dc79211569 (patch) | |
| tree | 587e87d84e5251e9667e95c8c3c9ec58ee1409d9 /drivers | |
| parent | 928af44314a1a086e946ef3c0901d40bdb3e19a9 (diff) | |
| parent | 475dec28805bf0c84ce83ec06d452b4ee8b5f9a9 (diff) | |
Merge patch series "arm: airoha: add support for en7523 based boards"
Mikhail Kshevetskiy <[email protected]> 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/[email protected]/)
* Latest linux kernel is recommended to properly support flashes
with more than one plane per lun
(see: https://lore.kernel.org/lkml/[email protected]/)
* 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/[email protected]
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clk/airoha/clk-airoha.c | 127 | ||||
| -rw-r--r-- | drivers/net/airoha_eth.c | 78 | ||||
| -rw-r--r-- | drivers/reset/reset-airoha.c | 106 |
3 files changed, 256 insertions, 55 deletions
diff --git a/drivers/clk/airoha/clk-airoha.c b/drivers/clk/airoha/clk-airoha.c index 1b2c4c98de5..49dbca82135 100644 --- a/drivers/clk/airoha/clk-airoha.c +++ b/drivers/clk/airoha/clk-airoha.c @@ -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, }, diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c index 19c3d60044c..3234d875887 100644 --- a/drivers/net/airoha_eth.c +++ b/drivers/net/airoha_eth.c @@ -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", ð->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", ð->xsi_rsts.resets[0]); - if (ret) - return ret; - - ret = reset_get_by_name(dev, "hsi1-mac", ð->xsi_rsts.resets[1]); - if (ret) - return ret; - - ret = reset_get_by_name(dev, "hsi-mac", ð->xsi_rsts.resets[2]); - if (ret) - return ret; - - ret = reset_get_by_name(dev, "xfp-mac", ð->xsi_rsts.resets[3]); - if (ret) - return ret; + for (i = 0; i < data->num_xsi_rsts; i++) { + ret = reset_get_by_name(dev, data->xsi_rsts_names[i], + ð->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, + }, { } }; diff --git a/drivers/reset/reset-airoha.c b/drivers/reset/reset-airoha.c index e878af6167c..ef8c47a067b 100644 --- a/drivers/reset/reset-airoha.c +++ b/drivers/reset/reset-airoha.c @@ -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; - - val = readl(addr); - if (assert) - val |= BIT(id % RST_NR_PER_BANK); - else - val &= ~BIT(id % RST_NR_PER_BANK); - writel(val, addr); + u16 offset = priv->bank_ofs[id / RST_NR_PER_BANK]; - 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, |
