33 * Reset driver for the StarFive JH7100 SoC
44 *
55 * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
6+ * Copyright (C) 2021 Walker Chen <walker.chen@starfivetech.com>
67 */
78
89#include <linux/bitmap.h>
910#include <linux/io.h>
10- #include <linux/iopoll.h>
11- #include <linux/mod_devicetable.h>
11+ #include <linux/of_device.h>
12+ #include <linux/regmap.h>
13+ #include <linux/mfd/syscon.h>
1214#include <linux/platform_device.h>
1315#include <linux/reset-controller.h>
1416#include <linux/spinlock.h>
2527#define JH7100_RESET_STATUS2 0x18
2628#define JH7100_RESET_STATUS3 0x1c
2729
28- #if BITS_PER_LONG == 64
29- #define jh7100_reset_read readq
30- #define jh7100_reset_write writeq
31- #else
32- #define jh7100_reset_read readl
33- #define jh7100_reset_write writel
34- #endif
30+ #define JH7100_AUDIO_RESET_STATUS0 0x4
3531
36- /*
37- * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
38- * line 32m + n, and writing a 0 deasserts the same line.
39- * Most reset lines have their status inverted so a 0 bit in the STATUS
40- * register means the line is asserted and a 1 means it's deasserted. A few
41- * lines don't though, so store the expected value of the status registers when
42- * all lines are asserted.
43- */
44- static const DECLARE_BITMAP ( jh7100_reset_asserted , 4 * 32 ) = {
45- BITMAP_FROM_U64 ( BIT_ULL_MASK ( JH7100_RST_U74 ) |
46- BIT_ULL_MASK ( JH7100_RST_VP6_DRESET ) |
47- BIT_ULL_MASK ( JH7100_RST_VP6_BRESET ) |
48- BIT_ULL_MASK ( JH7100_RST_HIFI4_DRESET ) |
49- BIT_ULL_MASK ( JH7100_RST_HIFI4_BRESET )),
50- BITMAP_FROM_U64 ( BIT_ULL_MASK ( JH7100_RST_E24 )),
32+ enum jh7100_reset_ctrl_type {
33+ PERIPHERAL = 0 ,
34+ AUDIO ,
35+ ISP ,
36+ };
37+
38+ static const u32 jh7100_reset_asserted [ 4 ] = {
39+ BIT ( JH7100_RST_U74 % 32 ) |
40+ BIT ( JH7100_RST_VP6_DRESET % 32 ) |
41+ BIT ( JH7100_RST_VP6_BRESET % 32 ),
42+
43+ BIT ( JH7100_RST_HIFI4_DRESET % 32 ) |
44+ BIT ( JH7100_RST_HIFI4_BRESET % 32 ),
45+
46+ BIT_MASK ( JH7100_RST_E24 % 32 )
5147};
5248
5349struct jh7100_reset {
5450 struct reset_controller_dev rcdev ;
5551 /* protect registers against concurrent read-modify-write */
5652 spinlock_t lock ;
57- void __iomem * base ;
53+ struct regmap * regmap ;
5854};
5955
6056static inline struct jh7100_reset *
@@ -63,106 +59,178 @@ jh7100_reset_from(struct reset_controller_dev *rcdev)
6359 return container_of (rcdev , struct jh7100_reset , rcdev );
6460}
6561
66- static int jh7100_reset_update (struct reset_controller_dev * rcdev ,
67- unsigned long id , bool assert )
62+ static int jh7100_reset_update (struct reset_controller_dev * rcdev , unsigned long id ,
63+ unsigned int reg_status , bool assert )
6864{
6965 struct jh7100_reset * data = jh7100_reset_from (rcdev );
70- unsigned long offset = id / BITS_PER_LONG ;
71- void __iomem * reg_assert = data -> base + JH7100_RESET_ASSERT0 + offset * sizeof (long );
72- void __iomem * reg_status = data -> base + JH7100_RESET_STATUS0 + offset * sizeof (long );
73- unsigned long mask = BIT_MASK (id );
74- unsigned long done = jh7100_reset_asserted [offset ] & mask ;
75- unsigned long value ;
66+ unsigned long bank = id / 32 ;
67+ u32 offset = JH7100_RESET_ASSERT0 + 4 * bank ;
68+ u32 status = reg_status + 4 * bank ;
69+ u32 mask = BIT (id % 32 );
70+ u32 done = jh7100_reset_asserted [bank ] & mask ;
7671 unsigned long flags ;
77- int ret ;
72+ unsigned long timeout ;
73+ u32 value = 0 ;
74+ int ret = 0 ;
7875
7976 if (!assert )
8077 done ^= mask ;
8178
8279 spin_lock_irqsave (& data -> lock , flags );
8380
84- value = jh7100_reset_read ( reg_assert );
81+ regmap_read ( data -> regmap , offset , & value );
8582 if (assert )
8683 value |= mask ;
8784 else
8885 value &= ~mask ;
89- jh7100_reset_write ( value , reg_assert );
86+ regmap_write ( data -> regmap , offset , value );
9087
91- /* if the associated clock is gated, deasserting might otherwise hang forever */
92- ret = readx_poll_timeout_atomic (jh7100_reset_read , reg_status , value ,
93- (value & mask ) == done , 0 , 1000 );
88+ timeout = jiffies + msecs_to_jiffies (10 );
89+ do {
90+ regmap_read (data -> regmap , status , & value );
91+ if (time_after (jiffies , timeout )) {
92+ ret = - ETIMEDOUT ;
93+ break ;
94+ }
95+ } while ((value & mask ) != done );
9496
9597 spin_unlock_irqrestore (& data -> lock , flags );
9698 return ret ;
9799}
98100
99- static int jh7100_reset_assert (struct reset_controller_dev * rcdev ,
101+ static int jh7100_periph_reset_assert (struct reset_controller_dev * rcdev ,
100102 unsigned long id )
101103{
102- return jh7100_reset_update (rcdev , id , true);
104+ return jh7100_reset_update (rcdev , id , JH7100_RESET_STATUS0 , true);
103105}
104106
105- static int jh7100_reset_deassert (struct reset_controller_dev * rcdev ,
107+ static int jh7100_periph_reset_deassert (struct reset_controller_dev * rcdev ,
106108 unsigned long id )
107109{
108- return jh7100_reset_update (rcdev , id , false);
110+ return jh7100_reset_update (rcdev , id , JH7100_RESET_STATUS0 , false);
109111}
110112
111- static int jh7100_reset_reset (struct reset_controller_dev * rcdev ,
113+ static int jh7100_periph_reset_reset (struct reset_controller_dev * rcdev ,
112114 unsigned long id )
113115{
114- int ret ;
115-
116- ret = jh7100_reset_assert (rcdev , id );
116+ int ret = jh7100_periph_reset_assert (rcdev , id );
117117 if (ret )
118118 return ret ;
119119
120- return jh7100_reset_deassert (rcdev , id );
120+ return jh7100_periph_reset_deassert (rcdev , id );
121121}
122122
123- static int jh7100_reset_status (struct reset_controller_dev * rcdev ,
124- unsigned long id )
123+ static int jh7100_get_reset_status (struct reset_controller_dev * rcdev ,
124+ unsigned int reg_status ,
125+ unsigned long id )
125126{
126127 struct jh7100_reset * data = jh7100_reset_from (rcdev );
127- unsigned long offset = id / BITS_PER_LONG ;
128- void __iomem * reg_status = data -> base + JH7100_RESET_STATUS0 + offset * sizeof (long );
129- unsigned long value = jh7100_reset_read (reg_status );
130- unsigned long mask = BIT_MASK (id );
128+ unsigned long bank = id / 32 ;
129+ unsigned long mask = BIT (id % 32 );
130+ u32 value = 0 ;
131+
132+ reg_status = reg_status + 4 * bank ;
133+ regmap_read (data -> regmap , reg_status , & value );
131134
132- return !((value ^ jh7100_reset_asserted [offset ]) & mask );
135+ return !((value ^ jh7100_reset_asserted [bank ]) & mask );
133136}
134137
135- static const struct reset_control_ops jh7100_reset_ops = {
136- .assert = jh7100_reset_assert ,
137- .deassert = jh7100_reset_deassert ,
138- .reset = jh7100_reset_reset ,
139- .status = jh7100_reset_status ,
138+ static int jh7100_periph_reset_status (struct reset_controller_dev * rcdev ,
139+ unsigned long id )
140+ {
141+ return jh7100_get_reset_status (rcdev , JH7100_RESET_STATUS0 , id );
142+ }
143+
144+ static const struct reset_control_ops jh7100_periph_reset_ops = {
145+ .assert = jh7100_periph_reset_assert ,
146+ .deassert = jh7100_periph_reset_deassert ,
147+ .reset = jh7100_periph_reset_reset ,
148+ .status = jh7100_periph_reset_status ,
149+ };
150+
151+ static int jh7100_audio_reset_assert (struct reset_controller_dev * rcdev ,
152+ unsigned long id )
153+ {
154+ return jh7100_reset_update (rcdev , id , JH7100_AUDIO_RESET_STATUS0 , true);
155+ }
156+
157+ static int jh7100_audio_reset_deassert (struct reset_controller_dev * rcdev ,
158+ unsigned long id )
159+ {
160+ return jh7100_reset_update (rcdev , id , JH7100_AUDIO_RESET_STATUS0 , false);
161+ }
162+
163+ static int jh7100_audio_reset_reset (struct reset_controller_dev * rcdev ,
164+ unsigned long id )
165+ {
166+ int ret = jh7100_audio_reset_assert (rcdev , id );
167+ if (ret )
168+ return ret ;
169+
170+ return jh7100_audio_reset_deassert (rcdev , id );
171+ }
172+
173+ static int jh7100_audio_reset_status (struct reset_controller_dev * rcdev ,
174+ unsigned long id )
175+ {
176+ return jh7100_get_reset_status (rcdev , JH7100_AUDIO_RESET_STATUS0 , id );
177+ }
178+
179+ static const struct reset_control_ops jh7100_audio_reset_ops = {
180+ .assert = jh7100_audio_reset_assert ,
181+ .deassert = jh7100_audio_reset_deassert ,
182+ .reset = jh7100_audio_reset_reset ,
183+ .status = jh7100_audio_reset_status ,
140184};
141185
142186static int __init jh7100_reset_probe (struct platform_device * pdev )
143187{
188+ enum jh7100_reset_ctrl_type type ;
189+ struct regmap * regmap ;
190+ struct device_node * np = pdev -> dev .of_node ;
191+ struct device * dev = & pdev -> dev ;
144192 struct jh7100_reset * data ;
145193
146194 data = devm_kzalloc (& pdev -> dev , sizeof (* data ), GFP_KERNEL );
147195 if (!data )
148196 return - ENOMEM ;
149197
150- data -> base = devm_platform_ioremap_resource (pdev , 0 );
151- if (IS_ERR (data -> base ))
152- return PTR_ERR (data -> base );
198+ type = (enum jh7100_reset_ctrl_type )of_device_get_match_data (dev );
153199
154- data -> rcdev .ops = & jh7100_reset_ops ;
200+ regmap = syscon_node_to_regmap (np );
201+ if (IS_ERR (regmap )) {
202+ dev_err (dev , "failed to get reset controller regmap\n" );
203+ return PTR_ERR (regmap );
204+ }
205+
206+ data -> regmap = regmap ;
207+ data -> rcdev .of_node = np ;
208+ data -> rcdev .dev = dev ;
155209 data -> rcdev .owner = THIS_MODULE ;
156- data -> rcdev .nr_resets = JH7100_RSTN_END ;
157- data -> rcdev .dev = & pdev -> dev ;
158- data -> rcdev .of_node = pdev -> dev .of_node ;
210+ if (type == PERIPHERAL ) {
211+ data -> rcdev .ops = & jh7100_periph_reset_ops ;
212+ data -> rcdev .nr_resets = JH7100_RSTN_END ;
213+ } else if (type == AUDIO ) {
214+ data -> rcdev .ops = & jh7100_audio_reset_ops ;
215+ data -> rcdev .nr_resets = JH7100_AUDIO_RSTN_END ;
216+ } else {
217+ ;
218+ }
219+
159220 spin_lock_init (& data -> lock );
160221
161222 return devm_reset_controller_register (& pdev -> dev , & data -> rcdev );
162223}
163224
164225static const struct of_device_id jh7100_reset_dt_ids [] = {
165- { .compatible = "starfive,jh7100-reset" },
226+ {
227+ .compatible = "starfive,jh7100-reset" ,
228+ .data = (void * )PERIPHERAL ,
229+ },
230+ {
231+ .compatible = "starfive,jh7100-reset-audio" ,
232+ .data = (void * )AUDIO ,
233+ },
166234 { /* sentinel */ }
167235};
168236
0 commit comments