Skip to content

Commit 7d1e3bd

Browse files
jk-ozlabslag-linaro
authored andcommitted
mfd: syscon: Allow reset control for syscon devices
Simple syscon devices may require deassertion of a reset signal in order to access their register set. Rather than requiring a custom driver to implement this, we can use the generic "resets" specifiers to link a reset line to the syscon. This change adds an optional reset line to the syscon device description, and deasserts the reset if detected. Signed-off-by: Jeremy Kerr <[email protected]> Reviewed-by: Arnd Bergmann <[email protected]> Signed-off-by: Lee Jones <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 0f4d261 commit 7d1e3bd

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

drivers/mfd/syscon.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/platform_data/syscon.h>
2121
#include <linux/platform_device.h>
2222
#include <linux/regmap.h>
23+
#include <linux/reset.h>
2324
#include <linux/mfd/syscon.h>
2425
#include <linux/slab.h>
2526

@@ -31,6 +32,7 @@ static LIST_HEAD(syscon_list);
3132
struct syscon {
3233
struct device_node *np;
3334
struct regmap *regmap;
35+
struct reset_control *reset;
3436
struct list_head list;
3537
};
3638

@@ -40,7 +42,7 @@ static const struct regmap_config syscon_regmap_config = {
4042
.reg_stride = 4,
4143
};
4244

43-
static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
45+
static struct syscon *of_syscon_register(struct device_node *np, bool check_res)
4446
{
4547
struct clk *clk;
4648
struct syscon *syscon;
@@ -50,6 +52,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
5052
int ret;
5153
struct regmap_config syscon_config = syscon_regmap_config;
5254
struct resource res;
55+
struct reset_control *reset;
5356

5457
syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
5558
if (!syscon)
@@ -114,7 +117,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
114117
goto err_regmap;
115118
}
116119

117-
if (check_clk) {
120+
if (check_res) {
118121
clk = of_clk_get(np, 0);
119122
if (IS_ERR(clk)) {
120123
ret = PTR_ERR(clk);
@@ -124,8 +127,18 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
124127
} else {
125128
ret = regmap_mmio_attach_clk(regmap, clk);
126129
if (ret)
127-
goto err_attach;
130+
goto err_attach_clk;
128131
}
132+
133+
reset = of_reset_control_get_optional_exclusive(np, NULL);
134+
if (IS_ERR(reset)) {
135+
ret = PTR_ERR(reset);
136+
goto err_attach_clk;
137+
}
138+
139+
ret = reset_control_deassert(reset);
140+
if (ret)
141+
goto err_reset;
129142
}
130143

131144
syscon->regmap = regmap;
@@ -137,7 +150,9 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
137150

138151
return syscon;
139152

140-
err_attach:
153+
err_reset:
154+
reset_control_put(reset);
155+
err_attach_clk:
141156
if (!IS_ERR(clk))
142157
clk_put(clk);
143158
err_clk:
@@ -150,7 +165,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
150165
}
151166

152167
static struct regmap *device_node_get_regmap(struct device_node *np,
153-
bool check_clk)
168+
bool check_res)
154169
{
155170
struct syscon *entry, *syscon = NULL;
156171

@@ -165,7 +180,7 @@ static struct regmap *device_node_get_regmap(struct device_node *np,
165180
spin_unlock(&syscon_list_slock);
166181

167182
if (!syscon)
168-
syscon = of_syscon_register(np, check_clk);
183+
syscon = of_syscon_register(np, check_res);
169184

170185
if (IS_ERR(syscon))
171186
return ERR_CAST(syscon);

0 commit comments

Comments
 (0)