diff options
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, |
