hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/drivers/reset/hisilicon/hi6220_reset.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Hisilicon Hi6220 reset controller driver
34 *
....@@ -5,10 +6,6 @@
56 * Copyright (c) 2015-2016 Hisilicon Limited.
67 *
78 * Author: Feng Chen <puck.chen@hisilicon.com>
8
- *
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License version 2 as
11
- * published by the Free Software Foundation.
129 */
1310
1411 #include <linux/io.h>
....@@ -36,6 +33,7 @@
3633 enum hi6220_reset_ctrl_type {
3734 PERIPHERAL,
3835 MEDIA,
36
+ AO,
3937 };
4038
4139 struct hi6220_reset_data {
....@@ -95,6 +93,65 @@
9593 .deassert = hi6220_media_deassert,
9694 };
9795
96
+#define AO_SCTRL_SC_PW_CLKEN0 0x800
97
+#define AO_SCTRL_SC_PW_CLKDIS0 0x804
98
+
99
+#define AO_SCTRL_SC_PW_RSTEN0 0x810
100
+#define AO_SCTRL_SC_PW_RSTDIS0 0x814
101
+
102
+#define AO_SCTRL_SC_PW_ISOEN0 0x820
103
+#define AO_SCTRL_SC_PW_ISODIS0 0x824
104
+#define AO_MAX_INDEX 12
105
+
106
+static int hi6220_ao_assert(struct reset_controller_dev *rc_dev,
107
+ unsigned long idx)
108
+{
109
+ struct hi6220_reset_data *data = to_reset_data(rc_dev);
110
+ struct regmap *regmap = data->regmap;
111
+ int ret;
112
+
113
+ ret = regmap_write(regmap, AO_SCTRL_SC_PW_RSTEN0, BIT(idx));
114
+ if (ret)
115
+ return ret;
116
+
117
+ ret = regmap_write(regmap, AO_SCTRL_SC_PW_ISOEN0, BIT(idx));
118
+ if (ret)
119
+ return ret;
120
+
121
+ ret = regmap_write(regmap, AO_SCTRL_SC_PW_CLKDIS0, BIT(idx));
122
+ return ret;
123
+}
124
+
125
+static int hi6220_ao_deassert(struct reset_controller_dev *rc_dev,
126
+ unsigned long idx)
127
+{
128
+ struct hi6220_reset_data *data = to_reset_data(rc_dev);
129
+ struct regmap *regmap = data->regmap;
130
+ int ret;
131
+
132
+ /*
133
+ * It was suggested to disable isolation before enabling
134
+ * the clocks and deasserting reset, to avoid glitches.
135
+ * But this order is preserved to keep it matching the
136
+ * vendor code.
137
+ */
138
+ ret = regmap_write(regmap, AO_SCTRL_SC_PW_RSTDIS0, BIT(idx));
139
+ if (ret)
140
+ return ret;
141
+
142
+ ret = regmap_write(regmap, AO_SCTRL_SC_PW_ISODIS0, BIT(idx));
143
+ if (ret)
144
+ return ret;
145
+
146
+ ret = regmap_write(regmap, AO_SCTRL_SC_PW_CLKEN0, BIT(idx));
147
+ return ret;
148
+}
149
+
150
+static const struct reset_control_ops hi6220_ao_reset_ops = {
151
+ .assert = hi6220_ao_assert,
152
+ .deassert = hi6220_ao_deassert,
153
+};
154
+
98155 static int hi6220_reset_probe(struct platform_device *pdev)
99156 {
100157 struct device_node *np = pdev->dev.of_node;
....@@ -120,9 +177,12 @@
120177 if (type == MEDIA) {
121178 data->rc_dev.ops = &hi6220_media_reset_ops;
122179 data->rc_dev.nr_resets = MEDIA_MAX_INDEX;
123
- } else {
180
+ } else if (type == PERIPHERAL) {
124181 data->rc_dev.ops = &hi6220_peripheral_reset_ops;
125182 data->rc_dev.nr_resets = PERIPH_MAX_INDEX;
183
+ } else {
184
+ data->rc_dev.ops = &hi6220_ao_reset_ops;
185
+ data->rc_dev.nr_resets = AO_MAX_INDEX;
126186 }
127187
128188 return reset_controller_register(&data->rc_dev);
....@@ -137,6 +197,10 @@
137197 .compatible = "hisilicon,hi6220-mediactrl",
138198 .data = (void *)MEDIA,
139199 },
200
+ {
201
+ .compatible = "hisilicon,hi6220-aoctrl",
202
+ .data = (void *)AO,
203
+ },
140204 { /* sentinel */ },
141205 };
142206 MODULE_DEVICE_TABLE(of, hi6220_reset_match);