1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
6 #include <linux/of_device.h>
7 #include <linux/platform_device.h>
8 #include <linux/reset-controller.h>
9 #include <linux/delay.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/regmap.h>
12 #include <soc/canaan/k210-sysctl.h>
14 #include <dt-bindings/reset/k210-rst.h>
16 #define K210_RST_MASK 0x27FFFFFF
20 struct reset_controller_dev rcdev
;
23 static inline struct k210_rst
*
24 to_k210_rst(struct reset_controller_dev
*rcdev
)
26 return container_of(rcdev
, struct k210_rst
, rcdev
);
29 static inline int k210_rst_assert(struct reset_controller_dev
*rcdev
,
32 struct k210_rst
*ksr
= to_k210_rst(rcdev
);
34 return regmap_update_bits(ksr
->map
, K210_SYSCTL_PERI_RESET
, BIT(id
), 1);
37 static inline int k210_rst_deassert(struct reset_controller_dev
*rcdev
,
40 struct k210_rst
*ksr
= to_k210_rst(rcdev
);
42 return regmap_update_bits(ksr
->map
, K210_SYSCTL_PERI_RESET
, BIT(id
), 0);
45 static int k210_rst_reset(struct reset_controller_dev
*rcdev
,
50 ret
= k210_rst_assert(rcdev
, id
);
53 ret
= k210_rst_deassert(rcdev
, id
);
59 static int k210_rst_status(struct reset_controller_dev
*rcdev
,
62 struct k210_rst
*ksr
= to_k210_rst(rcdev
);
63 u32 reg
, bit
= BIT(id
);
66 ret
= regmap_read(ksr
->map
, K210_SYSCTL_PERI_RESET
, ®
);
73 static int k210_rst_xlate(struct reset_controller_dev
*rcdev
,
74 const struct of_phandle_args
*reset_spec
)
76 unsigned long id
= reset_spec
->args
[0];
78 if (!(BIT(id
) & K210_RST_MASK
))
84 static const struct reset_control_ops k210_rst_ops
= {
85 .assert = k210_rst_assert
,
86 .deassert
= k210_rst_deassert
,
87 .reset
= k210_rst_reset
,
88 .status
= k210_rst_status
,
91 static int k210_rst_probe(struct platform_device
*pdev
)
93 struct device
*dev
= &pdev
->dev
;
94 struct device_node
*parent_np
= of_get_parent(dev
->of_node
);
97 dev_info(dev
, "K210 reset controller\n");
99 ksr
= devm_kzalloc(dev
, sizeof(*ksr
), GFP_KERNEL
);
103 ksr
->map
= syscon_node_to_regmap(parent_np
);
104 of_node_put(parent_np
);
105 if (IS_ERR(ksr
->map
))
106 return PTR_ERR(ksr
->map
);
108 ksr
->rcdev
.owner
= THIS_MODULE
;
109 ksr
->rcdev
.dev
= dev
;
110 ksr
->rcdev
.of_node
= dev
->of_node
;
111 ksr
->rcdev
.ops
= &k210_rst_ops
;
112 ksr
->rcdev
.nr_resets
= fls(K210_RST_MASK
);
113 ksr
->rcdev
.of_reset_n_cells
= 1;
114 ksr
->rcdev
.of_xlate
= k210_rst_xlate
;
116 return devm_reset_controller_register(dev
, &ksr
->rcdev
);
119 static const struct of_device_id k210_rst_dt_ids
[] = {
120 { .compatible
= "canaan,k210-rst" },
124 static struct platform_driver k210_rst_driver
= {
125 .probe
= k210_rst_probe
,
128 .of_match_table
= k210_rst_dt_ids
,
131 builtin_platform_driver(k210_rst_driver
);