xref: /OK3568_Linux_fs/kernel/drivers/rknpu/rknpu_reset.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) Rockchip Electronics Co.Ltd
4  * Author: Felix Zeng <felix.zeng@rock-chips.com>
5  */
6 
7 #include <linux/delay.h>
8 #include <linux/iommu.h>
9 
10 #include "rknpu_reset.h"
11 
12 #ifndef FPGA_PLATFORM
rknpu_reset_control_get(struct device * dev,const char * name)13 static inline struct reset_control *rknpu_reset_control_get(struct device *dev,
14 							    const char *name)
15 {
16 	struct reset_control *rst = NULL;
17 
18 	rst = devm_reset_control_get(dev, name);
19 	if (IS_ERR(rst))
20 		LOG_DEV_ERROR(dev,
21 			      "failed to get rknpu reset control: %s, %ld\n",
22 			      name, PTR_ERR(rst));
23 
24 	return rst;
25 }
26 #endif
27 
rknpu_reset_get(struct rknpu_device * rknpu_dev)28 int rknpu_reset_get(struct rknpu_device *rknpu_dev)
29 {
30 #ifndef FPGA_PLATFORM
31 	struct reset_control *srst_a = NULL;
32 	struct reset_control *srst_h = NULL;
33 	int i = 0;
34 
35 	for (i = 0; i < rknpu_dev->config->num_resets; i++) {
36 		srst_a = rknpu_reset_control_get(
37 			rknpu_dev->dev,
38 			rknpu_dev->config->resets[i].srst_a_name);
39 		if (IS_ERR(srst_a))
40 			return PTR_ERR(srst_a);
41 
42 		rknpu_dev->srst_a[i] = srst_a;
43 
44 		srst_h = rknpu_reset_control_get(
45 			rknpu_dev->dev,
46 			rknpu_dev->config->resets[i].srst_h_name);
47 		if (IS_ERR(srst_h))
48 			return PTR_ERR(srst_h);
49 
50 		rknpu_dev->srst_h[i] = srst_h;
51 	}
52 #endif
53 
54 	return 0;
55 }
56 
57 #ifndef FPGA_PLATFORM
rknpu_reset_assert(struct reset_control * rst)58 static int rknpu_reset_assert(struct reset_control *rst)
59 {
60 	int ret = -EINVAL;
61 
62 	if (!rst)
63 		return -EINVAL;
64 
65 	ret = reset_control_assert(rst);
66 	if (ret < 0) {
67 		LOG_ERROR("failed to assert rknpu reset: %d\n", ret);
68 		return ret;
69 	}
70 
71 	return 0;
72 }
73 
rknpu_reset_deassert(struct reset_control * rst)74 static int rknpu_reset_deassert(struct reset_control *rst)
75 {
76 	int ret = -EINVAL;
77 
78 	if (!rst)
79 		return -EINVAL;
80 
81 	ret = reset_control_deassert(rst);
82 	if (ret < 0) {
83 		LOG_ERROR("failed to deassert rknpu reset: %d\n", ret);
84 		return ret;
85 	}
86 
87 	return 0;
88 }
89 #endif
90 
rknpu_soft_reset(struct rknpu_device * rknpu_dev)91 int rknpu_soft_reset(struct rknpu_device *rknpu_dev)
92 {
93 #ifndef FPGA_PLATFORM
94 	struct iommu_domain *domain = NULL;
95 	struct rknpu_subcore_data *subcore_data = NULL;
96 	int ret = -EINVAL, i = 0;
97 
98 	if (rknpu_dev->bypass_soft_reset) {
99 		LOG_WARN("bypass soft reset\n");
100 		return 0;
101 	}
102 
103 	if (!mutex_trylock(&rknpu_dev->reset_lock))
104 		return 0;
105 
106 	rknpu_dev->soft_reseting = true;
107 
108 	msleep(100);
109 
110 	for (i = 0; i < rknpu_dev->config->num_irqs; ++i) {
111 		subcore_data = &rknpu_dev->subcore_datas[i];
112 		wake_up(&subcore_data->job_done_wq);
113 	}
114 
115 	LOG_INFO("soft reset\n");
116 
117 	for (i = 0; i < rknpu_dev->config->num_resets; i++) {
118 		ret = rknpu_reset_assert(rknpu_dev->srst_a[i]);
119 		ret |= rknpu_reset_assert(rknpu_dev->srst_h[i]);
120 
121 		udelay(10);
122 
123 		ret |= rknpu_reset_deassert(rknpu_dev->srst_a[i]);
124 		ret |= rknpu_reset_deassert(rknpu_dev->srst_h[i]);
125 	}
126 
127 	if (ret) {
128 		LOG_DEV_ERROR(rknpu_dev->dev,
129 			      "failed to soft reset for rknpu: %d\n", ret);
130 		mutex_unlock(&rknpu_dev->reset_lock);
131 		return ret;
132 	}
133 
134 	if (rknpu_dev->iommu_en)
135 		domain = iommu_get_domain_for_dev(rknpu_dev->dev);
136 
137 	if (domain) {
138 		iommu_detach_device(domain, rknpu_dev->dev);
139 		iommu_attach_device(domain, rknpu_dev->dev);
140 	}
141 
142 	rknpu_dev->soft_reseting = false;
143 
144 	mutex_unlock(&rknpu_dev->reset_lock);
145 #endif
146 
147 	return 0;
148 }
149