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