2 * Copyright (C) 2014 Marvell Technology Group Ltd.
4 * Marvell Berlin reset driver
6 * Antoine Tenart <antoine.tenart@free-electrons.com>
7 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
14 #include <linux/delay.h>
16 #include <linux/mfd/syscon.h>
17 #include <linux/init.h>
19 #include <linux/of_address.h>
20 #include <linux/platform_device.h>
21 #include <linux/regmap.h>
22 #include <linux/reset-controller.h>
23 #include <linux/slab.h>
24 #include <linux/types.h>
26 #define BERLIN_MAX_RESETS 32
28 #define to_berlin_reset_priv(p) \
29 container_of((p), struct berlin_reset_priv, rcdev)
31 struct berlin_reset_priv
{
32 struct regmap
*regmap
;
33 struct reset_controller_dev rcdev
;
36 static int berlin_reset_reset(struct reset_controller_dev
*rcdev
,
39 struct berlin_reset_priv
*priv
= to_berlin_reset_priv(rcdev
);
41 int mask
= BIT(id
& 0x1f);
43 regmap_write(priv
->regmap
, offset
, mask
);
45 /* let the reset be effective */
51 static const struct reset_control_ops berlin_reset_ops
= {
52 .reset
= berlin_reset_reset
,
55 static int berlin_reset_xlate(struct reset_controller_dev
*rcdev
,
56 const struct of_phandle_args
*reset_spec
)
60 offset
= reset_spec
->args
[0];
61 bit
= reset_spec
->args
[1];
63 if (bit
>= BERLIN_MAX_RESETS
)
66 return (offset
<< 8) | bit
;
69 static int berlin2_reset_probe(struct platform_device
*pdev
)
71 struct device_node
*parent_np
= of_get_parent(pdev
->dev
.of_node
);
72 struct berlin_reset_priv
*priv
;
74 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
78 priv
->regmap
= syscon_node_to_regmap(parent_np
);
79 of_node_put(parent_np
);
80 if (IS_ERR(priv
->regmap
))
81 return PTR_ERR(priv
->regmap
);
83 priv
->rcdev
.owner
= THIS_MODULE
;
84 priv
->rcdev
.ops
= &berlin_reset_ops
;
85 priv
->rcdev
.of_node
= pdev
->dev
.of_node
;
86 priv
->rcdev
.of_reset_n_cells
= 2;
87 priv
->rcdev
.of_xlate
= berlin_reset_xlate
;
89 return reset_controller_register(&priv
->rcdev
);
92 static const struct of_device_id berlin_reset_dt_match
[] = {
93 { .compatible
= "marvell,berlin2-reset" },
97 static struct platform_driver berlin_reset_driver
= {
98 .probe
= berlin2_reset_probe
,
100 .name
= "berlin2-reset",
101 .of_match_table
= berlin_reset_dt_match
,
104 builtin_platform_driver(berlin_reset_driver
);