diff options
Diffstat (limited to 'drivers/net/ethernet/airoha/airoha_npu.c')
-rw-r--r-- | drivers/net/ethernet/airoha/airoha_npu.c | 198 |
1 files changed, 177 insertions, 21 deletions
diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c index a802f95df99d..8c883f2b2d36 100644 --- a/drivers/net/ethernet/airoha/airoha_npu.c +++ b/drivers/net/ethernet/airoha/airoha_npu.c @@ -13,7 +13,6 @@ #include <linux/regmap.h> #include "airoha_eth.h" -#include "airoha_npu.h" #define NPU_EN7581_FIRMWARE_DATA "airoha/en7581_npu_data.bin" #define NPU_EN7581_FIRMWARE_RV32 "airoha/en7581_npu_rv32.bin" @@ -42,6 +41,22 @@ #define REG_CR_MBQ8_CTRL(_n) (NPU_MBOX_BASE_ADDR + 0x0b0 + ((_n) << 2)) #define REG_CR_NPU_MIB(_n) (NPU_MBOX_BASE_ADDR + 0x140 + ((_n) << 2)) +#define NPU_WLAN_BASE_ADDR 0x30d000 + +#define REG_IRQ_STATUS (NPU_WLAN_BASE_ADDR + 0x030) +#define REG_IRQ_RXDONE(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 2) + 0x034) +#define NPU_IRQ_RX_MASK(_n) ((_n) == 1 ? BIT(17) : BIT(16)) + +#define REG_TX_BASE(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x080) +#define REG_TX_DSCP_NUM(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x084) +#define REG_TX_CPU_IDX(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x088) +#define REG_TX_DMA_IDX(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x08c) + +#define REG_RX_BASE(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x180) +#define REG_RX_DSCP_NUM(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x184) +#define REG_RX_CPU_IDX(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x188) +#define REG_RX_DMA_IDX(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x18c) + #define NPU_TIMER_BASE_ADDR 0x310100 #define REG_WDT_TIMER_CTRL(_n) (NPU_TIMER_BASE_ADDR + ((_n) * 0x100)) #define WDT_EN_MASK BIT(25) @@ -124,6 +139,13 @@ struct ppe_mbox_data { }; }; +struct wlan_mbox_data { + u32 ifindex:4; + u32 func_type:4; + u32 func_id; + DECLARE_FLEX_ARRAY(u8, d); +}; + static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, void *p, int size) { @@ -357,15 +379,13 @@ out: return err; } -static int airoha_npu_stats_setup(struct airoha_npu *npu, - dma_addr_t foe_stats_addr) +static int airoha_npu_ppe_stats_setup(struct airoha_npu *npu, + dma_addr_t foe_stats_addr, + u32 num_stats_entries) { - int err, size = PPE_STATS_NUM_ENTRIES * sizeof(*npu->stats); + int err, size = num_stats_entries * sizeof(*npu->stats); struct ppe_mbox_data *ppe_data; - if (!size) /* flow stats are disabled */ - return 0; - ppe_data = kzalloc(sizeof(*ppe_data), GFP_ATOMIC); if (!ppe_data) return -ENOMEM; @@ -390,7 +410,137 @@ out: return err; } -struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) +static int airoha_npu_wlan_msg_send(struct airoha_npu *npu, int ifindex, + enum airoha_npu_wlan_set_cmd func_id, + void *data, int data_len, gfp_t gfp) +{ + struct wlan_mbox_data *wlan_data; + int err, len; + + len = sizeof(*wlan_data) + data_len; + wlan_data = kzalloc(len, gfp); + if (!wlan_data) + return -ENOMEM; + + wlan_data->ifindex = ifindex; + wlan_data->func_type = NPU_OP_SET; + wlan_data->func_id = func_id; + memcpy(wlan_data->d, data, data_len); + + err = airoha_npu_send_msg(npu, NPU_FUNC_WIFI, wlan_data, len); + kfree(wlan_data); + + return err; +} + +static int airoha_npu_wlan_msg_get(struct airoha_npu *npu, int ifindex, + enum airoha_npu_wlan_get_cmd func_id, + void *data, int data_len, gfp_t gfp) +{ + struct wlan_mbox_data *wlan_data; + int err, len; + + len = sizeof(*wlan_data) + data_len; + wlan_data = kzalloc(len, gfp); + if (!wlan_data) + return -ENOMEM; + + wlan_data->ifindex = ifindex; + wlan_data->func_type = NPU_OP_GET; + wlan_data->func_id = func_id; + + err = airoha_npu_send_msg(npu, NPU_FUNC_WIFI, wlan_data, len); + if (!err) + memcpy(data, wlan_data->d, data_len); + kfree(wlan_data); + + return err; +} + +static int +airoha_npu_wlan_set_reserved_memory(struct airoha_npu *npu, + int ifindex, const char *name, + enum airoha_npu_wlan_set_cmd func_id) +{ + struct device *dev = npu->dev; + struct resource res; + int err; + u32 val; + + err = of_reserved_mem_region_to_resource_byname(dev->of_node, name, + &res); + if (err) + return err; + + val = res.start; + return airoha_npu_wlan_msg_send(npu, ifindex, func_id, &val, + sizeof(val), GFP_KERNEL); +} + +static int airoha_npu_wlan_init_memory(struct airoha_npu *npu) +{ + enum airoha_npu_wlan_set_cmd cmd = WLAN_FUNC_SET_WAIT_NPU_BAND0_ONCPU; + u32 val = 0; + int err; + + err = airoha_npu_wlan_msg_send(npu, 1, cmd, &val, sizeof(val), + GFP_KERNEL); + if (err) + return err; + + cmd = WLAN_FUNC_SET_WAIT_TX_BUF_CHECK_ADDR; + err = airoha_npu_wlan_set_reserved_memory(npu, 0, "tx-bufid", cmd); + if (err) + return err; + + cmd = WLAN_FUNC_SET_WAIT_PKT_BUF_ADDR; + err = airoha_npu_wlan_set_reserved_memory(npu, 0, "pkt", cmd); + if (err) + return err; + + cmd = WLAN_FUNC_SET_WAIT_TX_PKT_BUF_ADDR; + err = airoha_npu_wlan_set_reserved_memory(npu, 0, "tx-pkt", cmd); + if (err) + return err; + + cmd = WLAN_FUNC_SET_WAIT_IS_FORCE_TO_CPU; + return airoha_npu_wlan_msg_send(npu, 0, cmd, &val, sizeof(val), + GFP_KERNEL); +} + +static u32 airoha_npu_wlan_queue_addr_get(struct airoha_npu *npu, int qid, + bool xmit) +{ + if (xmit) + return REG_TX_BASE(qid + 2); + + return REG_RX_BASE(qid); +} + +static void airoha_npu_wlan_irq_status_set(struct airoha_npu *npu, u32 val) +{ + regmap_write(npu->regmap, REG_IRQ_STATUS, val); +} + +static u32 airoha_npu_wlan_irq_status_get(struct airoha_npu *npu, int q) +{ + u32 val; + + regmap_read(npu->regmap, REG_IRQ_STATUS, &val); + return val; +} + +static void airoha_npu_wlan_irq_enable(struct airoha_npu *npu, int q) +{ + regmap_set_bits(npu->regmap, REG_IRQ_RXDONE(q), NPU_IRQ_RX_MASK(q)); +} + +static void airoha_npu_wlan_irq_disable(struct airoha_npu *npu, int q) +{ + regmap_clear_bits(npu->regmap, REG_IRQ_RXDONE(q), NPU_IRQ_RX_MASK(q)); +} + +struct airoha_npu *airoha_npu_get(struct device *dev) { struct platform_device *pdev; struct device_node *np; @@ -429,17 +579,6 @@ struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) goto error_module_put; } - if (stats_addr) { - int err; - - err = airoha_npu_stats_setup(npu, *stats_addr); - if (err) { - dev_err(dev, "failed to allocate npu stats buffer\n"); - npu = ERR_PTR(err); - goto error_module_put; - } - } - return npu; error_module_put: @@ -491,8 +630,17 @@ static int airoha_npu_probe(struct platform_device *pdev) npu->dev = dev; npu->ops.ppe_init = airoha_npu_ppe_init; npu->ops.ppe_deinit = airoha_npu_ppe_deinit; + npu->ops.ppe_init_stats = airoha_npu_ppe_stats_setup; npu->ops.ppe_flush_sram_entries = airoha_npu_ppe_flush_sram_entries; npu->ops.ppe_foe_commit_entry = airoha_npu_foe_commit_entry; + npu->ops.wlan_init_reserved_memory = airoha_npu_wlan_init_memory; + npu->ops.wlan_send_msg = airoha_npu_wlan_msg_send; + npu->ops.wlan_get_msg = airoha_npu_wlan_msg_get; + npu->ops.wlan_get_queue_addr = airoha_npu_wlan_queue_addr_get; + npu->ops.wlan_set_irq_status = airoha_npu_wlan_irq_status_set; + npu->ops.wlan_get_irq_status = airoha_npu_wlan_irq_status_get; + npu->ops.wlan_enable_irq = airoha_npu_wlan_irq_enable; + npu->ops.wlan_disable_irq = airoha_npu_wlan_irq_disable; npu->regmap = devm_regmap_init_mmio(dev, base, ®map_config); if (IS_ERR(npu->regmap)) @@ -529,6 +677,15 @@ static int airoha_npu_probe(struct platform_device *pdev) INIT_WORK(&core->wdt_work, airoha_npu_wdt_work); } + /* wlan IRQ lines */ + for (i = 0; i < ARRAY_SIZE(npu->irqs); i++) { + irq = platform_get_irq(pdev, i + ARRAY_SIZE(npu->cores) + 1); + if (irq < 0) + return irq; + + npu->irqs[i] = irq; + } + err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); if (err) return err; @@ -550,8 +707,7 @@ static int airoha_npu_probe(struct platform_device *pdev) usleep_range(1000, 2000); /* enable NPU cores */ - /* do not start core3 since it is used for WiFi offloading */ - regmap_write(npu->regmap, REG_CR_BOOT_CONFIG, 0xf7); + regmap_write(npu->regmap, REG_CR_BOOT_CONFIG, 0xff); regmap_write(npu->regmap, REG_CR_BOOT_TRIGGER, 0x1); msleep(100); |