2 * Copyright (C) 2014 Marvell Technology Group Ltd.
4 * Antoine Tenart <antoine.tenart@free-electrons.com>
5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
12 #include <linux/delay.h>
14 #include <linux/mfd/syscon.h>
15 #include <linux/module.h>
17 #include <linux/of_address.h>
18 #include <linux/platform_device.h>
19 #include <linux/regmap.h>
20 #include <linux/reset-controller.h>
21 #include <linux/slab.h>
22 #include <linux/types.h>
24 #define BERLIN_MAX_RESETS 32
26 #define to_berlin_reset_priv(p) \
27 container_of((p), struct berlin_reset_priv, rcdev)
29 struct berlin_reset_priv
{
30 struct regmap
*regmap
;
31 struct reset_controller_dev rcdev
;
34 static int berlin_reset_reset(struct reset_controller_dev
*rcdev
,
37 struct berlin_reset_priv
*priv
= to_berlin_reset_priv(rcdev
);
39 int mask
= BIT(id
& 0x1f);
41 regmap_write(priv
->regmap
, offset
, mask
);
43 /* let the reset be effective */
49 static struct reset_control_ops berlin_reset_ops
= {
50 .reset
= berlin_reset_reset
,
53 static int berlin_reset_xlate(struct reset_controller_dev
*rcdev
,
54 const struct of_phandle_args
*reset_spec
)
58 if (WARN_ON(reset_spec
->args_count
!= rcdev
->of_reset_n_cells
))
61 offset
= reset_spec
->args
[0];
62 bit
= reset_spec
->args
[1];
64 if (bit
>= BERLIN_MAX_RESETS
)
67 return (offset
<< 8) | bit
;
70 static int berlin2_reset_probe(struct platform_device
*pdev
)
72 struct device_node
*parent_np
= of_get_parent(pdev
->dev
.of_node
);
73 struct berlin_reset_priv
*priv
;
75 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
79 priv
->regmap
= syscon_node_to_regmap(parent_np
);
80 of_node_put(parent_np
);
81 if (IS_ERR(priv
->regmap
))
82 return PTR_ERR(priv
->regmap
);
84 priv
->rcdev
.owner
= THIS_MODULE
;
85 priv
->rcdev
.ops
= &berlin_reset_ops
;
86 priv
->rcdev
.of_node
= pdev
->dev
.of_node
;
87 priv
->rcdev
.of_reset_n_cells
= 2;
88 priv
->rcdev
.of_xlate
= berlin_reset_xlate
;
90 reset_controller_register(&priv
->rcdev
);
95 static const struct of_device_id berlin_reset_dt_match
[] = {
96 { .compatible
= "marvell,berlin2-reset" },
99 MODULE_DEVICE_TABLE(of
, berlin_reset_dt_match
);
101 static struct platform_driver berlin_reset_driver
= {
102 .probe
= berlin2_reset_probe
,
104 .name
= "berlin2-reset",
105 .of_match_table
= berlin_reset_dt_match
,
108 module_platform_driver(berlin_reset_driver
);
110 MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
111 MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
112 MODULE_DESCRIPTION("Marvell Berlin reset driver");
113 MODULE_LICENSE("GPL");