1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Hisilicon Reset Controller Driver
5 * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
9 #include <linux/of_address.h>
10 #include <linux/platform_device.h>
11 #include <linux/reset-controller.h>
12 #include <linux/slab.h>
13 #include <linux/spinlock.h>
16 #define HISI_RESET_BIT_MASK 0x1f
17 #define HISI_RESET_OFFSET_SHIFT 8
18 #define HISI_RESET_OFFSET_MASK 0xffff00
20 struct hisi_reset_controller
{
22 void __iomem
*membase
;
23 struct reset_controller_dev rcdev
;
27 #define to_hisi_reset_controller(rcdev) \
28 container_of(rcdev, struct hisi_reset_controller, rcdev)
30 static int hisi_reset_of_xlate(struct reset_controller_dev
*rcdev
,
31 const struct of_phandle_args
*reset_spec
)
36 offset
= (reset_spec
->args
[0] << HISI_RESET_OFFSET_SHIFT
)
37 & HISI_RESET_OFFSET_MASK
;
38 bit
= reset_spec
->args
[1] & HISI_RESET_BIT_MASK
;
40 return (offset
| bit
);
43 static int hisi_reset_assert(struct reset_controller_dev
*rcdev
,
46 struct hisi_reset_controller
*rstc
= to_hisi_reset_controller(rcdev
);
51 offset
= (id
& HISI_RESET_OFFSET_MASK
) >> HISI_RESET_OFFSET_SHIFT
;
52 bit
= id
& HISI_RESET_BIT_MASK
;
54 spin_lock_irqsave(&rstc
->lock
, flags
);
56 reg
= readl(rstc
->membase
+ offset
);
57 writel(reg
| BIT(bit
), rstc
->membase
+ offset
);
59 spin_unlock_irqrestore(&rstc
->lock
, flags
);
64 static int hisi_reset_deassert(struct reset_controller_dev
*rcdev
,
67 struct hisi_reset_controller
*rstc
= to_hisi_reset_controller(rcdev
);
72 offset
= (id
& HISI_RESET_OFFSET_MASK
) >> HISI_RESET_OFFSET_SHIFT
;
73 bit
= id
& HISI_RESET_BIT_MASK
;
75 spin_lock_irqsave(&rstc
->lock
, flags
);
77 reg
= readl(rstc
->membase
+ offset
);
78 writel(reg
& ~BIT(bit
), rstc
->membase
+ offset
);
80 spin_unlock_irqrestore(&rstc
->lock
, flags
);
85 static const struct reset_control_ops hisi_reset_ops
= {
86 .assert = hisi_reset_assert
,
87 .deassert
= hisi_reset_deassert
,
90 struct hisi_reset_controller
*hisi_reset_init(struct platform_device
*pdev
)
92 struct hisi_reset_controller
*rstc
;
94 rstc
= devm_kmalloc(&pdev
->dev
, sizeof(*rstc
), GFP_KERNEL
);
98 rstc
->membase
= devm_platform_ioremap_resource(pdev
, 0);
99 if (IS_ERR(rstc
->membase
))
102 spin_lock_init(&rstc
->lock
);
103 rstc
->rcdev
.owner
= THIS_MODULE
;
104 rstc
->rcdev
.ops
= &hisi_reset_ops
;
105 rstc
->rcdev
.of_node
= pdev
->dev
.of_node
;
106 rstc
->rcdev
.of_reset_n_cells
= 2;
107 rstc
->rcdev
.of_xlate
= hisi_reset_of_xlate
;
108 reset_controller_register(&rstc
->rcdev
);
112 EXPORT_SYMBOL_GPL(hisi_reset_init
);
114 void hisi_reset_exit(struct hisi_reset_controller
*rstc
)
116 reset_controller_unregister(&rstc
->rcdev
);
118 EXPORT_SYMBOL_GPL(hisi_reset_exit
);