2 * Cortina Gemini Reset controller driver
3 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #include <linux/err.h>
11 #include <linux/init.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/regmap.h>
15 #include <linux/platform_device.h>
16 #include <linux/reset-controller.h>
17 #include <dt-bindings/reset/cortina,gemini-reset.h>
20 * struct gemini_reset - gemini reset controller
21 * @map: regmap to access the containing system controller
22 * @rcdev: reset controller device
26 struct reset_controller_dev rcdev
;
29 #define GEMINI_GLOBAL_SOFT_RESET 0x0c
31 #define to_gemini_reset(p) \
32 container_of((p), struct gemini_reset, rcdev)
35 * This is a self-deasserting reset controller.
37 static int gemini_reset(struct reset_controller_dev
*rcdev
,
40 struct gemini_reset
*gr
= to_gemini_reset(rcdev
);
42 /* Manual says to always set BIT 30 (CPU1) to 1 */
43 return regmap_write(gr
->map
,
44 GEMINI_GLOBAL_SOFT_RESET
,
45 BIT(GEMINI_RESET_CPU1
) | BIT(id
));
48 static int gemini_reset_status(struct reset_controller_dev
*rcdev
,
51 struct gemini_reset
*gr
= to_gemini_reset(rcdev
);
55 ret
= regmap_read(gr
->map
, GEMINI_GLOBAL_SOFT_RESET
, &val
);
59 return !!(val
& BIT(id
));
62 static const struct reset_control_ops gemini_reset_ops
= {
63 .reset
= gemini_reset
,
64 .status
= gemini_reset_status
,
67 static int gemini_reset_probe(struct platform_device
*pdev
)
69 struct gemini_reset
*gr
;
70 struct device
*dev
= &pdev
->dev
;
71 struct device_node
*np
= dev
->of_node
;
74 gr
= devm_kzalloc(dev
, sizeof(*gr
), GFP_KERNEL
);
78 gr
->map
= syscon_node_to_regmap(np
);
79 if (IS_ERR(gr
->map
)) {
80 ret
= PTR_ERR(gr
->map
);
81 dev_err(dev
, "unable to get regmap (%d)", ret
);
84 gr
->rcdev
.owner
= THIS_MODULE
;
85 gr
->rcdev
.nr_resets
= 32;
86 gr
->rcdev
.ops
= &gemini_reset_ops
;
87 gr
->rcdev
.of_node
= pdev
->dev
.of_node
;
89 ret
= devm_reset_controller_register(&pdev
->dev
, &gr
->rcdev
);
93 dev_info(dev
, "registered Gemini reset controller\n");
97 static const struct of_device_id gemini_reset_dt_ids
[] = {
98 { .compatible
= "cortina,gemini-syscon", },
102 static struct platform_driver gemini_reset_driver
= {
103 .probe
= gemini_reset_probe
,
105 .name
= "gemini-reset",
106 .of_match_table
= gemini_reset_dt_ids
,
107 .suppress_bind_attrs
= true,
110 builtin_platform_driver(gemini_reset_driver
);