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/platform_device.h>
23 #include <linux/reset-controller.h>
24 #include <linux/slab.h>
25 #include <linux/spinlock.h>
28 #define HISI_RESET_BIT_MASK 0x1f
29 #define HISI_RESET_OFFSET_SHIFT 8
30 #define HISI_RESET_OFFSET_MASK 0xffff00
32 struct hisi_reset_controller
{
34 void __iomem
*membase
;
35 struct reset_controller_dev rcdev
;
39 #define to_hisi_reset_controller(rcdev) \
40 container_of(rcdev, struct hisi_reset_controller, rcdev)
42 static int hisi_reset_of_xlate(struct reset_controller_dev
*rcdev
,
43 const struct of_phandle_args
*reset_spec
)
48 offset
= (reset_spec
->args
[0] << HISI_RESET_OFFSET_SHIFT
)
49 & HISI_RESET_OFFSET_MASK
;
50 bit
= reset_spec
->args
[1] & HISI_RESET_BIT_MASK
;
52 return (offset
| bit
);
55 static int hisi_reset_assert(struct reset_controller_dev
*rcdev
,
58 struct hisi_reset_controller
*rstc
= to_hisi_reset_controller(rcdev
);
63 offset
= (id
& HISI_RESET_OFFSET_MASK
) >> HISI_RESET_OFFSET_SHIFT
;
64 bit
= id
& HISI_RESET_BIT_MASK
;
66 spin_lock_irqsave(&rstc
->lock
, flags
);
68 reg
= readl(rstc
->membase
+ offset
);
69 writel(reg
| BIT(bit
), rstc
->membase
+ offset
);
71 spin_unlock_irqrestore(&rstc
->lock
, flags
);
76 static int hisi_reset_deassert(struct reset_controller_dev
*rcdev
,
79 struct hisi_reset_controller
*rstc
= to_hisi_reset_controller(rcdev
);
84 offset
= (id
& HISI_RESET_OFFSET_MASK
) >> HISI_RESET_OFFSET_SHIFT
;
85 bit
= id
& HISI_RESET_BIT_MASK
;
87 spin_lock_irqsave(&rstc
->lock
, flags
);
89 reg
= readl(rstc
->membase
+ offset
);
90 writel(reg
& ~BIT(bit
), rstc
->membase
+ offset
);
92 spin_unlock_irqrestore(&rstc
->lock
, flags
);
97 static const struct reset_control_ops hisi_reset_ops
= {
98 .assert = hisi_reset_assert
,
99 .deassert
= hisi_reset_deassert
,
102 struct hisi_reset_controller
*hisi_reset_init(struct platform_device
*pdev
)
104 struct hisi_reset_controller
*rstc
;
105 struct resource
*res
;
107 rstc
= devm_kmalloc(&pdev
->dev
, sizeof(*rstc
), GFP_KERNEL
);
111 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
112 rstc
->membase
= devm_ioremap(&pdev
->dev
,
113 res
->start
, resource_size(res
));
117 spin_lock_init(&rstc
->lock
);
118 rstc
->rcdev
.owner
= THIS_MODULE
;
119 rstc
->rcdev
.ops
= &hisi_reset_ops
;
120 rstc
->rcdev
.of_node
= pdev
->dev
.of_node
;
121 rstc
->rcdev
.of_reset_n_cells
= 2;
122 rstc
->rcdev
.of_xlate
= hisi_reset_of_xlate
;
123 reset_controller_register(&rstc
->rcdev
);
127 EXPORT_SYMBOL_GPL(hisi_reset_init
);
129 void hisi_reset_exit(struct hisi_reset_controller
*rstc
)
131 reset_controller_unregister(&rstc
->rcdev
);
133 EXPORT_SYMBOL_GPL(hisi_reset_exit
);