xref: /linux/drivers/clk/baikal-t1/ccu-rst.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2021 BAIKAL ELECTRONICS, JSC
4  *
5  * Authors:
6  *   Serge Semin <Sergey.Semin@baikalelectronics.ru>
7  *
8  * Baikal-T1 CCU Resets interface driver
9  */
10 
11 #define pr_fmt(fmt) "bt1-ccu-rst: " fmt
12 
13 #include <linux/bits.h>
14 #include <linux/delay.h>
15 #include <linux/kernel.h>
16 #include <linux/of.h>
17 #include <linux/printk.h>
18 #include <linux/regmap.h>
19 #include <linux/reset-controller.h>
20 #include <linux/slab.h>
21 
22 #include <dt-bindings/reset/bt1-ccu.h>
23 
24 #include "ccu-rst.h"
25 
26 #define CCU_AXI_MAIN_BASE		0x030
27 #define CCU_AXI_DDR_BASE		0x034
28 #define CCU_AXI_SATA_BASE		0x038
29 #define CCU_AXI_GMAC0_BASE		0x03C
30 #define CCU_AXI_GMAC1_BASE		0x040
31 #define CCU_AXI_XGMAC_BASE		0x044
32 #define CCU_AXI_PCIE_M_BASE		0x048
33 #define CCU_AXI_PCIE_S_BASE		0x04C
34 #define CCU_AXI_USB_BASE		0x050
35 #define CCU_AXI_HWA_BASE		0x054
36 #define CCU_AXI_SRAM_BASE		0x058
37 
38 #define CCU_SYS_DDR_BASE		0x02c
39 #define CCU_SYS_SATA_REF_BASE		0x060
40 #define CCU_SYS_APB_BASE		0x064
41 #define CCU_SYS_PCIE_BASE		0x144
42 
43 #define CCU_RST_DELAY_US		1
44 
45 #define CCU_RST_TRIG(_base, _ofs)		\
46 	{					\
47 		.type = CCU_RST_TRIG,		\
48 		.base = _base,			\
49 		.mask = BIT(_ofs),		\
50 	}
51 
52 #define CCU_RST_DIR(_base, _ofs)		\
53 	{					\
54 		.type = CCU_RST_DIR,		\
55 		.base = _base,			\
56 		.mask = BIT(_ofs),		\
57 	}
58 
59 struct ccu_rst_info {
60 	enum ccu_rst_type type;
61 	unsigned int base;
62 	unsigned int mask;
63 };
64 
65 /*
66  * Each AXI-bus clock divider is equipped with the corresponding clock-consumer
67  * domain reset (it's self-deasserted reset control).
68  */
69 static const struct ccu_rst_info axi_rst_info[] = {
70 	[CCU_AXI_MAIN_RST] = CCU_RST_TRIG(CCU_AXI_MAIN_BASE, 1),
71 	[CCU_AXI_DDR_RST] = CCU_RST_TRIG(CCU_AXI_DDR_BASE, 1),
72 	[CCU_AXI_SATA_RST] = CCU_RST_TRIG(CCU_AXI_SATA_BASE, 1),
73 	[CCU_AXI_GMAC0_RST] = CCU_RST_TRIG(CCU_AXI_GMAC0_BASE, 1),
74 	[CCU_AXI_GMAC1_RST] = CCU_RST_TRIG(CCU_AXI_GMAC1_BASE, 1),
75 	[CCU_AXI_XGMAC_RST] = CCU_RST_TRIG(CCU_AXI_XGMAC_BASE, 1),
76 	[CCU_AXI_PCIE_M_RST] = CCU_RST_TRIG(CCU_AXI_PCIE_M_BASE, 1),
77 	[CCU_AXI_PCIE_S_RST] = CCU_RST_TRIG(CCU_AXI_PCIE_S_BASE, 1),
78 	[CCU_AXI_USB_RST] = CCU_RST_TRIG(CCU_AXI_USB_BASE, 1),
79 	[CCU_AXI_HWA_RST] = CCU_RST_TRIG(CCU_AXI_HWA_BASE, 1),
80 	[CCU_AXI_SRAM_RST] = CCU_RST_TRIG(CCU_AXI_SRAM_BASE, 1),
81 };
82 
83 /*
84  * SATA reference clock domain and APB-bus domain are connected with the
85  * sefl-deasserted reset control, which can be activated via the corresponding
86  * clock divider register. DDR and PCIe sub-domains can be reset with directly
87  * controlled reset signals. Resetting the DDR controller though won't end up
88  * well while the Linux kernel is working.
89  */
90 static const struct ccu_rst_info sys_rst_info[] = {
91 	[CCU_SYS_SATA_REF_RST] = CCU_RST_TRIG(CCU_SYS_SATA_REF_BASE, 1),
92 	[CCU_SYS_APB_RST] = CCU_RST_TRIG(CCU_SYS_APB_BASE, 1),
93 	[CCU_SYS_DDR_FULL_RST] = CCU_RST_DIR(CCU_SYS_DDR_BASE, 1),
94 	[CCU_SYS_DDR_INIT_RST] = CCU_RST_DIR(CCU_SYS_DDR_BASE, 2),
95 	[CCU_SYS_PCIE_PCS_PHY_RST] = CCU_RST_DIR(CCU_SYS_PCIE_BASE, 0),
96 	[CCU_SYS_PCIE_PIPE0_RST] = CCU_RST_DIR(CCU_SYS_PCIE_BASE, 4),
97 	[CCU_SYS_PCIE_CORE_RST] = CCU_RST_DIR(CCU_SYS_PCIE_BASE, 8),
98 	[CCU_SYS_PCIE_PWR_RST] = CCU_RST_DIR(CCU_SYS_PCIE_BASE, 9),
99 	[CCU_SYS_PCIE_STICKY_RST] = CCU_RST_DIR(CCU_SYS_PCIE_BASE, 10),
100 	[CCU_SYS_PCIE_NSTICKY_RST] = CCU_RST_DIR(CCU_SYS_PCIE_BASE, 11),
101 	[CCU_SYS_PCIE_HOT_RST] = CCU_RST_DIR(CCU_SYS_PCIE_BASE, 12),
102 };
103 
ccu_rst_reset(struct reset_controller_dev * rcdev,unsigned long idx)104 static int ccu_rst_reset(struct reset_controller_dev *rcdev, unsigned long idx)
105 {
106 	struct ccu_rst *rst = to_ccu_rst(rcdev);
107 	const struct ccu_rst_info *info = &rst->rsts_info[idx];
108 
109 	if (info->type != CCU_RST_TRIG)
110 		return -EOPNOTSUPP;
111 
112 	regmap_update_bits(rst->sys_regs, info->base, info->mask, info->mask);
113 
114 	/* The next delay must be enough to cover all the resets. */
115 	udelay(CCU_RST_DELAY_US);
116 
117 	return 0;
118 }
119 
ccu_rst_set(struct reset_controller_dev * rcdev,unsigned long idx,bool high)120 static int ccu_rst_set(struct reset_controller_dev *rcdev,
121 		       unsigned long idx, bool high)
122 {
123 	struct ccu_rst *rst = to_ccu_rst(rcdev);
124 	const struct ccu_rst_info *info = &rst->rsts_info[idx];
125 
126 	if (info->type != CCU_RST_DIR)
127 		return high ? -EOPNOTSUPP : 0;
128 
129 	return regmap_update_bits(rst->sys_regs, info->base,
130 				  info->mask, high ? info->mask : 0);
131 }
132 
ccu_rst_assert(struct reset_controller_dev * rcdev,unsigned long idx)133 static int ccu_rst_assert(struct reset_controller_dev *rcdev,
134 			  unsigned long idx)
135 {
136 	return ccu_rst_set(rcdev, idx, true);
137 }
138 
ccu_rst_deassert(struct reset_controller_dev * rcdev,unsigned long idx)139 static int ccu_rst_deassert(struct reset_controller_dev *rcdev,
140 			    unsigned long idx)
141 {
142 	return ccu_rst_set(rcdev, idx, false);
143 }
144 
ccu_rst_status(struct reset_controller_dev * rcdev,unsigned long idx)145 static int ccu_rst_status(struct reset_controller_dev *rcdev,
146 			  unsigned long idx)
147 {
148 	struct ccu_rst *rst = to_ccu_rst(rcdev);
149 	const struct ccu_rst_info *info = &rst->rsts_info[idx];
150 	u32 val;
151 
152 	if (info->type != CCU_RST_DIR)
153 		return -EOPNOTSUPP;
154 
155 	regmap_read(rst->sys_regs, info->base, &val);
156 
157 	return !!(val & info->mask);
158 }
159 
160 static const struct reset_control_ops ccu_rst_ops = {
161 	.reset = ccu_rst_reset,
162 	.assert = ccu_rst_assert,
163 	.deassert = ccu_rst_deassert,
164 	.status = ccu_rst_status,
165 };
166 
ccu_rst_hw_register(const struct ccu_rst_init_data * rst_init)167 struct ccu_rst *ccu_rst_hw_register(const struct ccu_rst_init_data *rst_init)
168 {
169 	struct ccu_rst *rst;
170 	int ret;
171 
172 	if (!rst_init)
173 		return ERR_PTR(-EINVAL);
174 
175 	rst = kzalloc(sizeof(*rst), GFP_KERNEL);
176 	if (!rst)
177 		return ERR_PTR(-ENOMEM);
178 
179 	rst->sys_regs = rst_init->sys_regs;
180 	if (of_device_is_compatible(rst_init->np, "baikal,bt1-ccu-axi")) {
181 		rst->rcdev.nr_resets = ARRAY_SIZE(axi_rst_info);
182 		rst->rsts_info = axi_rst_info;
183 	} else if (of_device_is_compatible(rst_init->np, "baikal,bt1-ccu-sys")) {
184 		rst->rcdev.nr_resets = ARRAY_SIZE(sys_rst_info);
185 		rst->rsts_info = sys_rst_info;
186 	} else {
187 		pr_err("Incompatible DT node '%s' specified\n",
188 		       of_node_full_name(rst_init->np));
189 		ret = -EINVAL;
190 		goto err_kfree_rst;
191 	}
192 
193 	rst->rcdev.owner = THIS_MODULE;
194 	rst->rcdev.ops = &ccu_rst_ops;
195 	rst->rcdev.of_node = rst_init->np;
196 
197 	ret = reset_controller_register(&rst->rcdev);
198 	if (ret) {
199 		pr_err("Couldn't register '%s' reset controller\n",
200 		       of_node_full_name(rst_init->np));
201 		goto err_kfree_rst;
202 	}
203 
204 	return rst;
205 
206 err_kfree_rst:
207 	kfree(rst);
208 
209 	return ERR_PTR(ret);
210 }
211 
ccu_rst_hw_unregister(struct ccu_rst * rst)212 void ccu_rst_hw_unregister(struct ccu_rst *rst)
213 {
214 	reset_controller_unregister(&rst->rcdev);
215 
216 	kfree(rst);
217 }
218