xref: /linux/drivers/accel/rocket/rocket_core.c (revision 58809f614e0e3f4e12b489bddf680bfeb31c0a20)
1ed98261bSTomeu Vizoso // SPDX-License-Identifier: GPL-2.0-only
2ed98261bSTomeu Vizoso /* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */
3ed98261bSTomeu Vizoso 
4ed98261bSTomeu Vizoso #include <linux/clk.h>
5ed98261bSTomeu Vizoso #include <linux/delay.h>
6ed98261bSTomeu Vizoso #include <linux/dev_printk.h>
7ed98261bSTomeu Vizoso #include <linux/dma-mapping.h>
8ed98261bSTomeu Vizoso #include <linux/err.h>
9ed98261bSTomeu Vizoso #include <linux/iommu.h>
10ed98261bSTomeu Vizoso #include <linux/platform_device.h>
11ed98261bSTomeu Vizoso #include <linux/pm_runtime.h>
12ed98261bSTomeu Vizoso #include <linux/reset.h>
13ed98261bSTomeu Vizoso 
14ed98261bSTomeu Vizoso #include "rocket_core.h"
150810d5adSTomeu Vizoso #include "rocket_job.h"
16ed98261bSTomeu Vizoso 
17ed98261bSTomeu Vizoso int rocket_core_init(struct rocket_core *core)
18ed98261bSTomeu Vizoso {
19ed98261bSTomeu Vizoso 	struct device *dev = core->dev;
20ed98261bSTomeu Vizoso 	struct platform_device *pdev = to_platform_device(dev);
21ed98261bSTomeu Vizoso 	u32 version;
22ed98261bSTomeu Vizoso 	int err = 0;
23ed98261bSTomeu Vizoso 
24ed98261bSTomeu Vizoso 	core->resets[0].id = "srst_a";
25ed98261bSTomeu Vizoso 	core->resets[1].id = "srst_h";
26ed98261bSTomeu Vizoso 	err = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(core->resets),
27ed98261bSTomeu Vizoso 						    core->resets);
28ed98261bSTomeu Vizoso 	if (err)
29ed98261bSTomeu Vizoso 		return dev_err_probe(dev, err, "failed to get resets for core %d\n", core->index);
30ed98261bSTomeu Vizoso 
31ed98261bSTomeu Vizoso 	err = devm_clk_bulk_get(dev, ARRAY_SIZE(core->clks), core->clks);
32ed98261bSTomeu Vizoso 	if (err)
33ed98261bSTomeu Vizoso 		return dev_err_probe(dev, err, "failed to get clocks for core %d\n", core->index);
34ed98261bSTomeu Vizoso 
35ed98261bSTomeu Vizoso 	core->pc_iomem = devm_platform_ioremap_resource_byname(pdev, "pc");
36ed98261bSTomeu Vizoso 	if (IS_ERR(core->pc_iomem)) {
37ed98261bSTomeu Vizoso 		dev_err(dev, "couldn't find PC registers %ld\n", PTR_ERR(core->pc_iomem));
38ed98261bSTomeu Vizoso 		return PTR_ERR(core->pc_iomem);
39ed98261bSTomeu Vizoso 	}
40ed98261bSTomeu Vizoso 
41ed98261bSTomeu Vizoso 	core->cna_iomem = devm_platform_ioremap_resource_byname(pdev, "cna");
42ed98261bSTomeu Vizoso 	if (IS_ERR(core->cna_iomem)) {
43ed98261bSTomeu Vizoso 		dev_err(dev, "couldn't find CNA registers %ld\n", PTR_ERR(core->cna_iomem));
44ed98261bSTomeu Vizoso 		return PTR_ERR(core->cna_iomem);
45ed98261bSTomeu Vizoso 	}
46ed98261bSTomeu Vizoso 
47ed98261bSTomeu Vizoso 	core->core_iomem = devm_platform_ioremap_resource_byname(pdev, "core");
48ed98261bSTomeu Vizoso 	if (IS_ERR(core->core_iomem)) {
49ed98261bSTomeu Vizoso 		dev_err(dev, "couldn't find CORE registers %ld\n", PTR_ERR(core->core_iomem));
50ed98261bSTomeu Vizoso 		return PTR_ERR(core->core_iomem);
51ed98261bSTomeu Vizoso 	}
52ed98261bSTomeu Vizoso 
53ed98261bSTomeu Vizoso 	dma_set_max_seg_size(dev, UINT_MAX);
54ed98261bSTomeu Vizoso 
55ed98261bSTomeu Vizoso 	err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
56ed98261bSTomeu Vizoso 	if (err)
57ed98261bSTomeu Vizoso 		return err;
58ed98261bSTomeu Vizoso 
59ed98261bSTomeu Vizoso 	core->iommu_group = iommu_group_get(dev);
60ed98261bSTomeu Vizoso 
610810d5adSTomeu Vizoso 	err = rocket_job_init(core);
620810d5adSTomeu Vizoso 	if (err)
630810d5adSTomeu Vizoso 		return err;
640810d5adSTomeu Vizoso 
65ed98261bSTomeu Vizoso 	pm_runtime_use_autosuspend(dev);
66ed98261bSTomeu Vizoso 
67ed98261bSTomeu Vizoso 	/*
68ed98261bSTomeu Vizoso 	 * As this NPU will be most often used as part of a media pipeline that
69ed98261bSTomeu Vizoso 	 * ends presenting in a display, choose 50 ms (~3 frames at 60Hz) as an
70ed98261bSTomeu Vizoso 	 * autosuspend delay as that will keep the device powered up while the
71ed98261bSTomeu Vizoso 	 * pipeline is running.
72ed98261bSTomeu Vizoso 	 */
73ed98261bSTomeu Vizoso 	pm_runtime_set_autosuspend_delay(dev, 50);
74ed98261bSTomeu Vizoso 
75ed98261bSTomeu Vizoso 	pm_runtime_enable(dev);
76ed98261bSTomeu Vizoso 
77*09e6d39cSDan Carpenter 	err = pm_runtime_resume_and_get(dev);
780810d5adSTomeu Vizoso 	if (err) {
790810d5adSTomeu Vizoso 		rocket_job_fini(core);
800810d5adSTomeu Vizoso 		return err;
810810d5adSTomeu Vizoso 	}
82ed98261bSTomeu Vizoso 
83ed98261bSTomeu Vizoso 	version = rocket_pc_readl(core, VERSION);
84ed98261bSTomeu Vizoso 	version += rocket_pc_readl(core, VERSION_NUM) & 0xffff;
85ed98261bSTomeu Vizoso 
86ed98261bSTomeu Vizoso 	pm_runtime_mark_last_busy(dev);
87ed98261bSTomeu Vizoso 	pm_runtime_put_autosuspend(dev);
88ed98261bSTomeu Vizoso 
89ed98261bSTomeu Vizoso 	dev_info(dev, "Rockchip NPU core %d version: %d\n", core->index, version);
90ed98261bSTomeu Vizoso 
91ed98261bSTomeu Vizoso 	return 0;
92ed98261bSTomeu Vizoso }
93ed98261bSTomeu Vizoso 
94ed98261bSTomeu Vizoso void rocket_core_fini(struct rocket_core *core)
95ed98261bSTomeu Vizoso {
96ed98261bSTomeu Vizoso 	pm_runtime_dont_use_autosuspend(core->dev);
97ed98261bSTomeu Vizoso 	pm_runtime_disable(core->dev);
98ed98261bSTomeu Vizoso 	iommu_group_put(core->iommu_group);
99ed98261bSTomeu Vizoso 	core->iommu_group = NULL;
1000810d5adSTomeu Vizoso 	rocket_job_fini(core);
101ed98261bSTomeu Vizoso }
102ed98261bSTomeu Vizoso 
103ed98261bSTomeu Vizoso void rocket_core_reset(struct rocket_core *core)
104ed98261bSTomeu Vizoso {
105ed98261bSTomeu Vizoso 	reset_control_bulk_assert(ARRAY_SIZE(core->resets), core->resets);
106ed98261bSTomeu Vizoso 
107ed98261bSTomeu Vizoso 	udelay(10);
108ed98261bSTomeu Vizoso 
109ed98261bSTomeu Vizoso 	reset_control_bulk_deassert(ARRAY_SIZE(core->resets), core->resets);
110ed98261bSTomeu Vizoso }
111