xref: /linux/drivers/net/ethernet/airoha/airoha_npu.c (revision c284d3e423382be3591d5b1e402e330e6c3f726c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2025 AIROHA Inc
4  * Author: Lorenzo Bianconi <lorenzo@kernel.org>
5  */
6 
7 #include <linux/devcoredump.h>
8 #include <linux/firmware.h>
9 #include <linux/platform_device.h>
10 #include <linux/of_net.h>
11 #include <linux/of_platform.h>
12 #include <linux/of_reserved_mem.h>
13 #include <linux/regmap.h>
14 
15 #include "airoha_npu.h"
16 
17 #define NPU_EN7581_FIRMWARE_DATA		"airoha/en7581_npu_data.bin"
18 #define NPU_EN7581_FIRMWARE_RV32		"airoha/en7581_npu_rv32.bin"
19 #define NPU_EN7581_FIRMWARE_RV32_MAX_SIZE	0x200000
20 #define NPU_EN7581_FIRMWARE_DATA_MAX_SIZE	0x10000
21 #define NPU_DUMP_SIZE				512
22 
23 #define REG_NPU_LOCAL_SRAM		0x0
24 
25 #define NPU_PC_BASE_ADDR		0x305000
26 #define REG_PC_DBG(_n)			(0x305000 + ((_n) * 0x100))
27 
28 #define NPU_CLUSTER_BASE_ADDR		0x306000
29 
30 #define REG_CR_BOOT_TRIGGER		(NPU_CLUSTER_BASE_ADDR + 0x000)
31 #define REG_CR_BOOT_CONFIG		(NPU_CLUSTER_BASE_ADDR + 0x004)
32 #define REG_CR_BOOT_BASE(_n)		(NPU_CLUSTER_BASE_ADDR + 0x020 + ((_n) << 2))
33 
34 #define NPU_MBOX_BASE_ADDR		0x30c000
35 
36 #define REG_CR_MBOX_INT_STATUS		(NPU_MBOX_BASE_ADDR + 0x000)
37 #define MBOX_INT_STATUS_MASK		BIT(8)
38 
39 #define REG_CR_MBOX_INT_MASK(_n)	(NPU_MBOX_BASE_ADDR + 0x004 + ((_n) << 2))
40 #define REG_CR_MBQ0_CTRL(_n)		(NPU_MBOX_BASE_ADDR + 0x030 + ((_n) << 2))
41 #define REG_CR_MBQ8_CTRL(_n)		(NPU_MBOX_BASE_ADDR + 0x0b0 + ((_n) << 2))
42 #define REG_CR_NPU_MIB(_n)		(NPU_MBOX_BASE_ADDR + 0x140 + ((_n) << 2))
43 
44 #define NPU_TIMER_BASE_ADDR		0x310100
45 #define REG_WDT_TIMER_CTRL(_n)		(NPU_TIMER_BASE_ADDR + ((_n) * 0x100))
46 #define WDT_EN_MASK			BIT(25)
47 #define WDT_INTR_MASK			BIT(21)
48 
49 enum {
50 	NPU_OP_SET = 1,
51 	NPU_OP_SET_NO_WAIT,
52 	NPU_OP_GET,
53 	NPU_OP_GET_NO_WAIT,
54 };
55 
56 enum {
57 	NPU_FUNC_WIFI,
58 	NPU_FUNC_TUNNEL,
59 	NPU_FUNC_NOTIFY,
60 	NPU_FUNC_DBA,
61 	NPU_FUNC_TR471,
62 	NPU_FUNC_PPE,
63 };
64 
65 enum {
66 	NPU_MBOX_ERROR,
67 	NPU_MBOX_SUCCESS,
68 };
69 
70 enum {
71 	PPE_FUNC_SET_WAIT,
72 	PPE_FUNC_SET_WAIT_HWNAT_INIT,
73 	PPE_FUNC_SET_WAIT_HWNAT_DEINIT,
74 	PPE_FUNC_SET_WAIT_API,
75 };
76 
77 enum {
78 	PPE2_SRAM_SET_ENTRY,
79 	PPE_SRAM_SET_ENTRY,
80 	PPE_SRAM_SET_VAL,
81 	PPE_SRAM_RESET_VAL,
82 };
83 
84 enum {
85 	QDMA_WAN_ETHER = 1,
86 	QDMA_WAN_PON_XDSL,
87 };
88 
89 #define MBOX_MSG_FUNC_ID	GENMASK(14, 11)
90 #define MBOX_MSG_STATIC_BUF	BIT(5)
91 #define MBOX_MSG_STATUS		GENMASK(4, 2)
92 #define MBOX_MSG_DONE		BIT(1)
93 #define MBOX_MSG_WAIT_RSP	BIT(0)
94 
95 #define PPE_TYPE_L2B_IPV4	2
96 #define PPE_TYPE_L2B_IPV4_IPV6	3
97 
98 struct ppe_mbox_data {
99 	u32 func_type;
100 	u32 func_id;
101 	union {
102 		struct {
103 			u8 cds;
104 			u8 xpon_hal_api;
105 			u8 wan_xsi;
106 			u8 ct_joyme4;
107 			int ppe_type;
108 			int wan_mode;
109 			int wan_sel;
110 		} init_info;
111 		struct {
112 			int func_id;
113 			u32 size;
114 			u32 data;
115 		} set_info;
116 	};
117 };
118 
119 static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,
120 			       void *p, int size)
121 {
122 	u16 core = 0; /* FIXME */
123 	u32 val, offset = core << 4;
124 	dma_addr_t dma_addr;
125 	void *addr;
126 	int ret;
127 
128 	addr = kmemdup(p, size, GFP_ATOMIC);
129 	if (!addr)
130 		return -ENOMEM;
131 
132 	dma_addr = dma_map_single(npu->dev, addr, size, DMA_TO_DEVICE);
133 	ret = dma_mapping_error(npu->dev, dma_addr);
134 	if (ret)
135 		goto out;
136 
137 	spin_lock_bh(&npu->cores[core].lock);
138 
139 	regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(0) + offset, dma_addr);
140 	regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(1) + offset, size);
141 	regmap_read(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, &val);
142 	regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, val + 1);
143 	val = FIELD_PREP(MBOX_MSG_FUNC_ID, func_id) | MBOX_MSG_WAIT_RSP;
144 	regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(3) + offset, val);
145 
146 	ret = regmap_read_poll_timeout_atomic(npu->regmap,
147 					      REG_CR_MBQ0_CTRL(3) + offset,
148 					      val, (val & MBOX_MSG_DONE),
149 					      100, 100 * MSEC_PER_SEC);
150 	if (!ret && FIELD_GET(MBOX_MSG_STATUS, val) != NPU_MBOX_SUCCESS)
151 		ret = -EINVAL;
152 
153 	spin_unlock_bh(&npu->cores[core].lock);
154 
155 	dma_unmap_single(npu->dev, dma_addr, size, DMA_TO_DEVICE);
156 out:
157 	kfree(addr);
158 
159 	return ret;
160 }
161 
162 static int airoha_npu_run_firmware(struct device *dev, void __iomem *base,
163 				   struct reserved_mem *rmem)
164 {
165 	const struct firmware *fw;
166 	void __iomem *addr;
167 	int ret;
168 
169 	ret = request_firmware(&fw, NPU_EN7581_FIRMWARE_RV32, dev);
170 	if (ret)
171 		return ret == -ENOENT ? -EPROBE_DEFER : ret;
172 
173 	if (fw->size > NPU_EN7581_FIRMWARE_RV32_MAX_SIZE) {
174 		dev_err(dev, "%s: fw size too overlimit (%zu)\n",
175 			NPU_EN7581_FIRMWARE_RV32, fw->size);
176 		ret = -E2BIG;
177 		goto out;
178 	}
179 
180 	addr = devm_ioremap(dev, rmem->base, rmem->size);
181 	if (!addr) {
182 		ret = -ENOMEM;
183 		goto out;
184 	}
185 
186 	memcpy_toio(addr, fw->data, fw->size);
187 	release_firmware(fw);
188 
189 	ret = request_firmware(&fw, NPU_EN7581_FIRMWARE_DATA, dev);
190 	if (ret)
191 		return ret == -ENOENT ? -EPROBE_DEFER : ret;
192 
193 	if (fw->size > NPU_EN7581_FIRMWARE_DATA_MAX_SIZE) {
194 		dev_err(dev, "%s: fw size too overlimit (%zu)\n",
195 			NPU_EN7581_FIRMWARE_DATA, fw->size);
196 		ret = -E2BIG;
197 		goto out;
198 	}
199 
200 	memcpy_toio(base + REG_NPU_LOCAL_SRAM, fw->data, fw->size);
201 out:
202 	release_firmware(fw);
203 
204 	return ret;
205 }
206 
207 static irqreturn_t airoha_npu_mbox_handler(int irq, void *npu_instance)
208 {
209 	struct airoha_npu *npu = npu_instance;
210 
211 	/* clear mbox interrupt status */
212 	regmap_write(npu->regmap, REG_CR_MBOX_INT_STATUS,
213 		     MBOX_INT_STATUS_MASK);
214 
215 	/* acknowledge npu */
216 	regmap_update_bits(npu->regmap, REG_CR_MBQ8_CTRL(3),
217 			   MBOX_MSG_STATUS | MBOX_MSG_DONE, MBOX_MSG_DONE);
218 
219 	return IRQ_HANDLED;
220 }
221 
222 static void airoha_npu_wdt_work(struct work_struct *work)
223 {
224 	struct airoha_npu_core *core;
225 	struct airoha_npu *npu;
226 	void *dump;
227 	u32 val[3];
228 	int c;
229 
230 	core = container_of(work, struct airoha_npu_core, wdt_work);
231 	npu = core->npu;
232 
233 	dump = vzalloc(NPU_DUMP_SIZE);
234 	if (!dump)
235 		return;
236 
237 	c = core - &npu->cores[0];
238 	regmap_bulk_read(npu->regmap, REG_PC_DBG(c), val, ARRAY_SIZE(val));
239 	snprintf(dump, NPU_DUMP_SIZE, "PC: %08x SP: %08x LR: %08x\n",
240 		 val[0], val[1], val[2]);
241 
242 	dev_coredumpv(npu->dev, dump, NPU_DUMP_SIZE, GFP_KERNEL);
243 }
244 
245 static irqreturn_t airoha_npu_wdt_handler(int irq, void *core_instance)
246 {
247 	struct airoha_npu_core *core = core_instance;
248 	struct airoha_npu *npu = core->npu;
249 	int c = core - &npu->cores[0];
250 	u32 val;
251 
252 	regmap_set_bits(npu->regmap, REG_WDT_TIMER_CTRL(c), WDT_INTR_MASK);
253 	if (!regmap_read(npu->regmap, REG_WDT_TIMER_CTRL(c), &val) &&
254 	    FIELD_GET(WDT_EN_MASK, val))
255 		schedule_work(&core->wdt_work);
256 
257 	return IRQ_HANDLED;
258 }
259 
260 static int airoha_npu_ppe_init(struct airoha_npu *npu)
261 {
262 	struct ppe_mbox_data ppe_data = {
263 		.func_type = NPU_OP_SET,
264 		.func_id = PPE_FUNC_SET_WAIT_HWNAT_INIT,
265 		.init_info = {
266 			.ppe_type = PPE_TYPE_L2B_IPV4_IPV6,
267 			.wan_mode = QDMA_WAN_ETHER,
268 		},
269 	};
270 
271 	return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
272 				   sizeof(struct ppe_mbox_data));
273 }
274 
275 static int airoha_npu_ppe_deinit(struct airoha_npu *npu)
276 {
277 	struct ppe_mbox_data ppe_data = {
278 		.func_type = NPU_OP_SET,
279 		.func_id = PPE_FUNC_SET_WAIT_HWNAT_DEINIT,
280 	};
281 
282 	return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
283 				   sizeof(struct ppe_mbox_data));
284 }
285 
286 static int airoha_npu_ppe_flush_sram_entries(struct airoha_npu *npu,
287 					     dma_addr_t foe_addr,
288 					     int sram_num_entries)
289 {
290 	struct ppe_mbox_data ppe_data = {
291 		.func_type = NPU_OP_SET,
292 		.func_id = PPE_FUNC_SET_WAIT_API,
293 		.set_info = {
294 			.func_id = PPE_SRAM_RESET_VAL,
295 			.data = foe_addr,
296 			.size = sram_num_entries,
297 		},
298 	};
299 
300 	return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
301 				   sizeof(struct ppe_mbox_data));
302 }
303 
304 static int airoha_npu_foe_commit_entry(struct airoha_npu *npu,
305 				       dma_addr_t foe_addr,
306 				       u32 entry_size, u32 hash, bool ppe2)
307 {
308 	struct ppe_mbox_data ppe_data = {
309 		.func_type = NPU_OP_SET,
310 		.func_id = PPE_FUNC_SET_WAIT_API,
311 		.set_info = {
312 			.data = foe_addr,
313 			.size = entry_size,
314 		},
315 	};
316 	int err;
317 
318 	ppe_data.set_info.func_id = ppe2 ? PPE2_SRAM_SET_ENTRY
319 					 : PPE_SRAM_SET_ENTRY;
320 
321 	err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
322 				  sizeof(struct ppe_mbox_data));
323 	if (err)
324 		return err;
325 
326 	ppe_data.set_info.func_id = PPE_SRAM_SET_VAL;
327 	ppe_data.set_info.data = hash;
328 	ppe_data.set_info.size = sizeof(u32);
329 
330 	return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
331 				   sizeof(struct ppe_mbox_data));
332 }
333 
334 struct airoha_npu *airoha_npu_get(struct device *dev)
335 {
336 	struct platform_device *pdev;
337 	struct device_node *np;
338 	struct airoha_npu *npu;
339 
340 	np = of_parse_phandle(dev->of_node, "airoha,npu", 0);
341 	if (!np)
342 		return ERR_PTR(-ENODEV);
343 
344 	pdev = of_find_device_by_node(np);
345 	of_node_put(np);
346 
347 	if (!pdev) {
348 		dev_err(dev, "cannot find device node %s\n", np->name);
349 		return ERR_PTR(-ENODEV);
350 	}
351 
352 	if (!try_module_get(THIS_MODULE)) {
353 		dev_err(dev, "failed to get the device driver module\n");
354 		npu = ERR_PTR(-ENODEV);
355 		goto error_pdev_put;
356 	}
357 
358 	npu = platform_get_drvdata(pdev);
359 	if (!npu) {
360 		npu = ERR_PTR(-ENODEV);
361 		goto error_module_put;
362 	}
363 
364 	if (!device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER)) {
365 		dev_err(&pdev->dev,
366 			"failed to create device link to consumer %s\n",
367 			dev_name(dev));
368 		npu = ERR_PTR(-EINVAL);
369 		goto error_module_put;
370 	}
371 
372 	return npu;
373 
374 error_module_put:
375 	module_put(THIS_MODULE);
376 error_pdev_put:
377 	platform_device_put(pdev);
378 
379 	return npu;
380 }
381 EXPORT_SYMBOL_GPL(airoha_npu_get);
382 
383 void airoha_npu_put(struct airoha_npu *npu)
384 {
385 	module_put(THIS_MODULE);
386 	put_device(npu->dev);
387 }
388 EXPORT_SYMBOL_GPL(airoha_npu_put);
389 
390 static const struct of_device_id of_airoha_npu_match[] = {
391 	{ .compatible = "airoha,en7581-npu" },
392 	{ /* sentinel */ }
393 };
394 MODULE_DEVICE_TABLE(of, of_airoha_npu_match);
395 
396 static const struct regmap_config regmap_config = {
397 	.name			= "npu",
398 	.reg_bits		= 32,
399 	.val_bits		= 32,
400 	.reg_stride		= 4,
401 	.disable_locking	= true,
402 };
403 
404 static int airoha_npu_probe(struct platform_device *pdev)
405 {
406 	struct device *dev = &pdev->dev;
407 	struct reserved_mem *rmem;
408 	struct airoha_npu *npu;
409 	struct device_node *np;
410 	void __iomem *base;
411 	int i, irq, err;
412 
413 	base = devm_platform_ioremap_resource(pdev, 0);
414 	if (IS_ERR(base))
415 		return PTR_ERR(base);
416 
417 	npu = devm_kzalloc(dev, sizeof(*npu), GFP_KERNEL);
418 	if (!npu)
419 		return -ENOMEM;
420 
421 	npu->dev = dev;
422 	npu->ops.ppe_init = airoha_npu_ppe_init;
423 	npu->ops.ppe_deinit = airoha_npu_ppe_deinit;
424 	npu->ops.ppe_flush_sram_entries = airoha_npu_ppe_flush_sram_entries;
425 	npu->ops.ppe_foe_commit_entry = airoha_npu_foe_commit_entry;
426 
427 	npu->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
428 	if (IS_ERR(npu->regmap))
429 		return PTR_ERR(npu->regmap);
430 
431 	np = of_parse_phandle(dev->of_node, "memory-region", 0);
432 	if (!np)
433 		return -ENODEV;
434 
435 	rmem = of_reserved_mem_lookup(np);
436 	of_node_put(np);
437 
438 	if (!rmem)
439 		return -ENODEV;
440 
441 	irq = platform_get_irq(pdev, 0);
442 	if (irq < 0)
443 		return irq;
444 
445 	err = devm_request_irq(dev, irq, airoha_npu_mbox_handler,
446 			       IRQF_SHARED, "airoha-npu-mbox", npu);
447 	if (err)
448 		return err;
449 
450 	for (i = 0; i < ARRAY_SIZE(npu->cores); i++) {
451 		struct airoha_npu_core *core = &npu->cores[i];
452 
453 		spin_lock_init(&core->lock);
454 		core->npu = npu;
455 
456 		irq = platform_get_irq(pdev, i + 1);
457 		if (irq < 0)
458 			return irq;
459 
460 		err = devm_request_irq(dev, irq, airoha_npu_wdt_handler,
461 				       IRQF_SHARED, "airoha-npu-wdt", core);
462 		if (err)
463 			return err;
464 
465 		INIT_WORK(&core->wdt_work, airoha_npu_wdt_work);
466 	}
467 
468 	err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
469 	if (err)
470 		return err;
471 
472 	err = airoha_npu_run_firmware(dev, base, rmem);
473 	if (err)
474 		return dev_err_probe(dev, err, "failed to run npu firmware\n");
475 
476 	regmap_write(npu->regmap, REG_CR_NPU_MIB(10),
477 		     rmem->base + NPU_EN7581_FIRMWARE_RV32_MAX_SIZE);
478 	regmap_write(npu->regmap, REG_CR_NPU_MIB(11), 0x40000); /* SRAM 256K */
479 	regmap_write(npu->regmap, REG_CR_NPU_MIB(12), 0);
480 	regmap_write(npu->regmap, REG_CR_NPU_MIB(21), 1);
481 	msleep(100);
482 
483 	/* setting booting address */
484 	for (i = 0; i < NPU_NUM_CORES; i++)
485 		regmap_write(npu->regmap, REG_CR_BOOT_BASE(i), rmem->base);
486 	usleep_range(1000, 2000);
487 
488 	/* enable NPU cores */
489 	/* do not start core3 since it is used for WiFi offloading */
490 	regmap_write(npu->regmap, REG_CR_BOOT_CONFIG, 0xf7);
491 	regmap_write(npu->regmap, REG_CR_BOOT_TRIGGER, 0x1);
492 	msleep(100);
493 
494 	platform_set_drvdata(pdev, npu);
495 
496 	return 0;
497 }
498 
499 static void airoha_npu_remove(struct platform_device *pdev)
500 {
501 	struct airoha_npu *npu = platform_get_drvdata(pdev);
502 	int i;
503 
504 	for (i = 0; i < ARRAY_SIZE(npu->cores); i++)
505 		cancel_work_sync(&npu->cores[i].wdt_work);
506 }
507 
508 static struct platform_driver airoha_npu_driver = {
509 	.probe = airoha_npu_probe,
510 	.remove = airoha_npu_remove,
511 	.driver = {
512 		.name = "airoha-npu",
513 		.of_match_table = of_airoha_npu_match,
514 	},
515 };
516 module_platform_driver(airoha_npu_driver);
517 
518 MODULE_LICENSE("GPL");
519 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
520 MODULE_DESCRIPTION("Airoha Network Processor Unit driver");
521