1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
6 #include <linux/platform_device.h>
7 #include <linux/reset-controller.h>
8 #include <linux/delay.h>
9 #include <linux/mfd/syscon.h>
10 #include <linux/regmap.h>
11 #include <soc/canaan/k210-sysctl.h>
13 #include <dt-bindings/reset/k210-rst.h>
15 #define K210_RST_MASK 0x27FFFFFF
19 struct reset_controller_dev rcdev
;
22 static inline struct k210_rst
*
23 to_k210_rst(struct reset_controller_dev
*rcdev
)
25 return container_of(rcdev
, struct k210_rst
, rcdev
);
28 static inline int k210_rst_assert(struct reset_controller_dev
*rcdev
,
31 struct k210_rst
*ksr
= to_k210_rst(rcdev
);
33 return regmap_update_bits(ksr
->map
, K210_SYSCTL_PERI_RESET
, BIT(id
), 1);
36 static inline int k210_rst_deassert(struct reset_controller_dev
*rcdev
,
39 struct k210_rst
*ksr
= to_k210_rst(rcdev
);
41 return regmap_update_bits(ksr
->map
, K210_SYSCTL_PERI_RESET
, BIT(id
), 0);
44 static int k210_rst_reset(struct reset_controller_dev
*rcdev
,
49 ret
= k210_rst_assert(rcdev
, id
);
52 ret
= k210_rst_deassert(rcdev
, id
);
58 static int k210_rst_status(struct reset_controller_dev
*rcdev
,
61 struct k210_rst
*ksr
= to_k210_rst(rcdev
);
62 u32 reg
, bit
= BIT(id
);
65 ret
= regmap_read(ksr
->map
, K210_SYSCTL_PERI_RESET
, ®
);
72 static int k210_rst_xlate(struct reset_controller_dev
*rcdev
,
73 const struct of_phandle_args
*reset_spec
)
75 unsigned long id
= reset_spec
->args
[0];
77 if (!(BIT(id
) & K210_RST_MASK
))
83 static const struct reset_control_ops k210_rst_ops
= {
84 .assert = k210_rst_assert
,
85 .deassert
= k210_rst_deassert
,
86 .reset
= k210_rst_reset
,
87 .status
= k210_rst_status
,
90 static int k210_rst_probe(struct platform_device
*pdev
)
92 struct device
*dev
= &pdev
->dev
;
93 struct device_node
*parent_np
;
96 dev_info(dev
, "K210 reset controller\n");
98 ksr
= devm_kzalloc(dev
, sizeof(*ksr
), GFP_KERNEL
);
102 parent_np
= of_get_parent(dev
->of_node
);
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
);