2 * Hisilicon Reset Controller Driver
4 * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/of_address.h>
22 #include <linux/reset-controller.h>
23 #include <linux/slab.h>
24 #include <linux/spinlock.h>
27 #define HISI_RESET_BIT_MASK 0x1f
28 #define HISI_RESET_OFFSET_SHIFT 8
29 #define HISI_RESET_OFFSET_MASK 0xffff00
31 struct hisi_reset_controller
{
33 void __iomem
*membase
;
34 struct reset_controller_dev rcdev
;
38 #define to_hisi_reset_controller(rcdev) \
39 container_of(rcdev, struct hisi_reset_controller, rcdev)
41 static int hisi_reset_of_xlate(struct reset_controller_dev
*rcdev
,
42 const struct of_phandle_args
*reset_spec
)
47 offset
= (reset_spec
->args
[0] << HISI_RESET_OFFSET_SHIFT
)
48 & HISI_RESET_OFFSET_MASK
;
49 bit
= reset_spec
->args
[1] & HISI_RESET_BIT_MASK
;
51 return (offset
| bit
);
54 static int hisi_reset_assert(struct reset_controller_dev
*rcdev
,
57 struct hisi_reset_controller
*rstc
= to_hisi_reset_controller(rcdev
);
62 offset
= (id
& HISI_RESET_OFFSET_MASK
) >> HISI_RESET_OFFSET_SHIFT
;
63 bit
= id
& HISI_RESET_BIT_MASK
;
65 spin_lock_irqsave(&rstc
->lock
, flags
);
67 reg
= readl(rstc
->membase
+ offset
);
68 writel(reg
| BIT(bit
), rstc
->membase
+ offset
);
70 spin_unlock_irqrestore(&rstc
->lock
, flags
);
75 static int hisi_reset_deassert(struct reset_controller_dev
*rcdev
,
78 struct hisi_reset_controller
*rstc
= to_hisi_reset_controller(rcdev
);
83 offset
= (id
& HISI_RESET_OFFSET_MASK
) >> HISI_RESET_OFFSET_SHIFT
;
84 bit
= id
& HISI_RESET_BIT_MASK
;
86 spin_lock_irqsave(&rstc
->lock
, flags
);
88 reg
= readl(rstc
->membase
+ offset
);
89 writel(reg
& ~BIT(bit
), rstc
->membase
+ offset
);
91 spin_unlock_irqrestore(&rstc
->lock
, flags
);
96 static const struct reset_control_ops hisi_reset_ops
= {
97 .assert = hisi_reset_assert
,
98 .deassert
= hisi_reset_deassert
,
101 struct hisi_reset_controller
*hisi_reset_init(struct device_node
*np
)
103 struct hisi_reset_controller
*rstc
;
105 rstc
= kzalloc(sizeof(*rstc
), GFP_KERNEL
);
109 rstc
->membase
= of_iomap(np
, 0);
110 if (!rstc
->membase
) {
115 spin_lock_init(&rstc
->lock
);
117 rstc
->rcdev
.owner
= THIS_MODULE
;
118 rstc
->rcdev
.ops
= &hisi_reset_ops
;
119 rstc
->rcdev
.of_node
= np
;
120 rstc
->rcdev
.of_reset_n_cells
= 2;
121 rstc
->rcdev
.of_xlate
= hisi_reset_of_xlate
;
122 reset_controller_register(&rstc
->rcdev
);
126 EXPORT_SYMBOL_GPL(hisi_reset_init
);
128 void hisi_reset_exit(struct hisi_reset_controller
*rstc
)
130 reset_controller_unregister(&rstc
->rcdev
);
131 iounmap(rstc
->membase
);
134 EXPORT_SYMBOL_GPL(hisi_reset_exit
);