1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2021 BAIKAL ELECTRONICS, JSC
6 * Serge Semin <Sergey.Semin@baikalelectronics.ru>
8 * Baikal-T1 CCU Resets interface driver
11 #define pr_fmt(fmt) "bt1-ccu-rst: " fmt
13 #include <linux/bits.h>
14 #include <linux/delay.h>
15 #include <linux/kernel.h>
17 #include <linux/printk.h>
18 #include <linux/regmap.h>
19 #include <linux/reset-controller.h>
20 #include <linux/slab.h>
22 #include <dt-bindings/reset/bt1-ccu.h>
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
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
43 #define CCU_RST_DELAY_US 1
45 #define CCU_RST_TRIG(_base, _ofs) \
47 .type = CCU_RST_TRIG, \
52 #define CCU_RST_DIR(_base, _ofs) \
54 .type = CCU_RST_DIR, \
60 enum ccu_rst_type type
;
66 * Each AXI-bus clock divider is equipped with the corresponding clock-consumer
67 * domain reset (it's self-deasserted reset control).
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),
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.
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),
104 static int ccu_rst_reset(struct reset_controller_dev
*rcdev
, unsigned long idx
)
106 struct ccu_rst
*rst
= to_ccu_rst(rcdev
);
107 const struct ccu_rst_info
*info
= &rst
->rsts_info
[idx
];
109 if (info
->type
!= CCU_RST_TRIG
)
112 regmap_update_bits(rst
->sys_regs
, info
->base
, info
->mask
, info
->mask
);
114 /* The next delay must be enough to cover all the resets. */
115 udelay(CCU_RST_DELAY_US
);
120 static int ccu_rst_set(struct reset_controller_dev
*rcdev
,
121 unsigned long idx
, bool high
)
123 struct ccu_rst
*rst
= to_ccu_rst(rcdev
);
124 const struct ccu_rst_info
*info
= &rst
->rsts_info
[idx
];
126 if (info
->type
!= CCU_RST_DIR
)
127 return high
? -EOPNOTSUPP
: 0;
129 return regmap_update_bits(rst
->sys_regs
, info
->base
,
130 info
->mask
, high
? info
->mask
: 0);
133 static int ccu_rst_assert(struct reset_controller_dev
*rcdev
,
136 return ccu_rst_set(rcdev
, idx
, true);
139 static int ccu_rst_deassert(struct reset_controller_dev
*rcdev
,
142 return ccu_rst_set(rcdev
, idx
, false);
145 static int ccu_rst_status(struct reset_controller_dev
*rcdev
,
148 struct ccu_rst
*rst
= to_ccu_rst(rcdev
);
149 const struct ccu_rst_info
*info
= &rst
->rsts_info
[idx
];
152 if (info
->type
!= CCU_RST_DIR
)
155 regmap_read(rst
->sys_regs
, info
->base
, &val
);
157 return !!(val
& info
->mask
);
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
,
167 struct ccu_rst
*ccu_rst_hw_register(const struct ccu_rst_init_data
*rst_init
)
173 return ERR_PTR(-EINVAL
);
175 rst
= kzalloc(sizeof(*rst
), GFP_KERNEL
);
177 return ERR_PTR(-ENOMEM
);
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
;
187 pr_err("Incompatible DT node '%s' specified\n",
188 of_node_full_name(rst_init
->np
));
193 rst
->rcdev
.owner
= THIS_MODULE
;
194 rst
->rcdev
.ops
= &ccu_rst_ops
;
195 rst
->rcdev
.of_node
= rst_init
->np
;
197 ret
= reset_controller_register(&rst
->rcdev
);
199 pr_err("Couldn't register '%s' reset controller\n",
200 of_node_full_name(rst_init
->np
));
212 void ccu_rst_hw_unregister(struct ccu_rst
*rst
)
214 reset_controller_unregister(&rst
->rcdev
);