8
8
*/
9
9
#include <linux/auxiliary_bus.h>
10
10
#include <linux/delay.h>
11
+ #include <linux/io.h>
11
12
#include <linux/module.h>
12
13
#include <linux/of.h>
13
14
#include <linux/platform_device.h>
15
+ #include <linux/slab.h>
14
16
#include <linux/reset-controller.h>
15
17
#include <dt-bindings/clock/microchip,mpfs-clock.h>
16
18
#include <soc/microchip/mpfs.h>
28
30
/* block concurrent access to the soft reset register */
29
31
static DEFINE_SPINLOCK (mpfs_reset_lock );
30
32
33
+ struct mpfs_reset {
34
+ void __iomem * base ;
35
+ struct reset_controller_dev rcdev ;
36
+ };
37
+
38
+ static inline struct mpfs_reset * to_mpfs_reset (struct reset_controller_dev * rcdev )
39
+ {
40
+ return container_of (rcdev , struct mpfs_reset , rcdev );
41
+ }
42
+
31
43
/*
32
44
* Peripheral clock resets
33
45
*/
34
-
35
46
static int mpfs_assert (struct reset_controller_dev * rcdev , unsigned long id )
36
47
{
48
+ struct mpfs_reset * rst = to_mpfs_reset (rcdev );
37
49
unsigned long flags ;
38
50
u32 reg ;
39
51
40
52
spin_lock_irqsave (& mpfs_reset_lock , flags );
41
53
42
- reg = mpfs_reset_read ( rcdev -> dev );
54
+ reg = readl ( rst -> base );
43
55
reg |= BIT (id );
44
- mpfs_reset_write ( rcdev -> dev , reg );
56
+ writel ( reg , rst -> base );
45
57
46
58
spin_unlock_irqrestore (& mpfs_reset_lock , flags );
47
59
@@ -50,14 +62,15 @@ static int mpfs_assert(struct reset_controller_dev *rcdev, unsigned long id)
50
62
51
63
static int mpfs_deassert (struct reset_controller_dev * rcdev , unsigned long id )
52
64
{
65
+ struct mpfs_reset * rst = to_mpfs_reset (rcdev );
53
66
unsigned long flags ;
54
67
u32 reg ;
55
68
56
69
spin_lock_irqsave (& mpfs_reset_lock , flags );
57
70
58
- reg = mpfs_reset_read ( rcdev -> dev );
71
+ reg = readl ( rst -> base );
59
72
reg &= ~BIT (id );
60
- mpfs_reset_write ( rcdev -> dev , reg );
73
+ writel ( reg , rst -> base );
61
74
62
75
spin_unlock_irqrestore (& mpfs_reset_lock , flags );
63
76
@@ -66,7 +79,8 @@ static int mpfs_deassert(struct reset_controller_dev *rcdev, unsigned long id)
66
79
67
80
static int mpfs_status (struct reset_controller_dev * rcdev , unsigned long id )
68
81
{
69
- u32 reg = mpfs_reset_read (rcdev -> dev );
82
+ struct mpfs_reset * rst = to_mpfs_reset (rcdev );
83
+ u32 reg = readl (rst -> base );
70
84
71
85
/*
72
86
* It is safe to return here as MPFS_NUM_RESETS makes sure the sign bit
@@ -121,11 +135,15 @@ static int mpfs_reset_probe(struct auxiliary_device *adev,
121
135
{
122
136
struct device * dev = & adev -> dev ;
123
137
struct reset_controller_dev * rcdev ;
138
+ struct mpfs_reset * rst ;
124
139
125
- rcdev = devm_kzalloc (dev , sizeof (* rcdev ), GFP_KERNEL );
126
- if (!rcdev )
140
+ rst = devm_kzalloc (dev , sizeof (* rst ), GFP_KERNEL );
141
+ if (!rst )
127
142
return - ENOMEM ;
128
143
144
+ rst -> base = (void __iomem * )adev -> dev .platform_data ;
145
+
146
+ rcdev = & rst -> rcdev ;
129
147
rcdev -> dev = dev ;
130
148
rcdev -> dev -> parent = dev -> parent ;
131
149
rcdev -> ops = & mpfs_reset_ops ;
@@ -137,9 +155,68 @@ static int mpfs_reset_probe(struct auxiliary_device *adev,
137
155
return devm_reset_controller_register (dev , rcdev );
138
156
}
139
157
158
+ static void mpfs_reset_unregister_adev (void * _adev )
159
+ {
160
+ struct auxiliary_device * adev = _adev ;
161
+
162
+ auxiliary_device_delete (adev );
163
+ auxiliary_device_uninit (adev );
164
+ }
165
+
166
+ static void mpfs_reset_adev_release (struct device * dev )
167
+ {
168
+ struct auxiliary_device * adev = to_auxiliary_dev (dev );
169
+
170
+ kfree (adev );
171
+ }
172
+
173
+ static struct auxiliary_device * mpfs_reset_adev_alloc (struct device * clk_dev )
174
+ {
175
+ struct auxiliary_device * adev ;
176
+ int ret ;
177
+
178
+ adev = kzalloc (sizeof (* adev ), GFP_KERNEL );
179
+ if (!adev )
180
+ return ERR_PTR (- ENOMEM );
181
+
182
+ adev -> name = "reset-mpfs" ;
183
+ adev -> dev .parent = clk_dev ;
184
+ adev -> dev .release = mpfs_reset_adev_release ;
185
+ adev -> id = 666u ;
186
+
187
+ ret = auxiliary_device_init (adev );
188
+ if (ret ) {
189
+ kfree (adev );
190
+ return ERR_PTR (ret );
191
+ }
192
+
193
+ return adev ;
194
+ }
195
+
196
+ int mpfs_reset_controller_register (struct device * clk_dev , void __iomem * base )
197
+ {
198
+ struct auxiliary_device * adev ;
199
+ int ret ;
200
+
201
+ adev = mpfs_reset_adev_alloc (clk_dev );
202
+ if (IS_ERR (adev ))
203
+ return PTR_ERR (adev );
204
+
205
+ ret = auxiliary_device_add (adev );
206
+ if (ret ) {
207
+ auxiliary_device_uninit (adev );
208
+ return ret ;
209
+ }
210
+
211
+ adev -> dev .platform_data = (__force void * )base ;
212
+
213
+ return devm_add_action_or_reset (clk_dev , mpfs_reset_unregister_adev , adev );
214
+ }
215
+ EXPORT_SYMBOL_NS_GPL (mpfs_reset_controller_register , MCHP_CLK_MPFS );
216
+
140
217
static const struct auxiliary_device_id mpfs_reset_ids [] = {
141
218
{
142
- .name = "clk_mpfs .reset-mpfs" ,
219
+ .name = "reset_mpfs .reset-mpfs" ,
143
220
},
144
221
{ }
145
222
};
0 commit comments