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/module.h>
16 #include <linux/of_address.h>
17 #include <linux/platform_device.h>
18 #include <linux/reset-controller.h>
19 #include <linux/slab.h>
20 #include <linux/types.h>
22 #define BERLIN_MAX_RESETS 32
24 #define to_berlin_reset_priv(p) \
25 container_of((p), struct berlin_reset_priv, rcdev)
27 struct berlin_reset_priv
{
30 struct reset_controller_dev rcdev
;
33 static int berlin_reset_reset(struct reset_controller_dev
*rcdev
,
36 struct berlin_reset_priv
*priv
= to_berlin_reset_priv(rcdev
);
38 int mask
= BIT(id
& 0x1f);
40 writel(mask
, priv
->base
+ offset
);
42 /* let the reset be effective */
48 static struct reset_control_ops berlin_reset_ops
= {
49 .reset
= berlin_reset_reset
,
52 static int berlin_reset_xlate(struct reset_controller_dev
*rcdev
,
53 const struct of_phandle_args
*reset_spec
)
55 struct berlin_reset_priv
*priv
= to_berlin_reset_priv(rcdev
);
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 (offset
>= priv
->size
)
67 if (bit
>= BERLIN_MAX_RESETS
)
70 return (offset
<< 8) | bit
;
73 static int __berlin_reset_init(struct device_node
*np
)
75 struct berlin_reset_priv
*priv
;
80 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
84 ret
= of_address_to_resource(np
, 0, &res
);
88 size
= resource_size(&res
);
89 priv
->base
= ioremap(res
.start
, size
);
96 priv
->rcdev
.owner
= THIS_MODULE
;
97 priv
->rcdev
.ops
= &berlin_reset_ops
;
98 priv
->rcdev
.of_node
= np
;
99 priv
->rcdev
.of_reset_n_cells
= 2;
100 priv
->rcdev
.of_xlate
= berlin_reset_xlate
;
102 reset_controller_register(&priv
->rcdev
);
111 static const struct of_device_id berlin_reset_of_match
[] __initconst
= {
112 { .compatible
= "marvell,berlin2-chip-ctrl" },
113 { .compatible
= "marvell,berlin2cd-chip-ctrl" },
114 { .compatible
= "marvell,berlin2q-chip-ctrl" },
118 static int __init
berlin_reset_init(void)
120 struct device_node
*np
;
123 for_each_matching_node(np
, berlin_reset_of_match
) {
124 ret
= __berlin_reset_init(np
);
131 arch_initcall(berlin_reset_init
);