hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/soc/rockchip/rockchip_pm_config.c
....@@ -27,6 +27,10 @@
2727 #define MAX_ON_OFF_REG_PROP_NAME_LEN 60
2828 #define MAX_CONFIG_PROP_NAME_LEN 60
2929
30
+#define RK_ATAG_MCU_SLP_CORE 0x526b0001
31
+#define RK_ATAG_MCU_SLP_MAX 0x526b00ff
32
+#define RK_ATAG_NONE 0x00000000
33
+
3034 enum rk_pm_state {
3135 RK_PM_MEM = 0,
3236 RK_PM_MEM_LITE,
....@@ -52,6 +56,31 @@
5256 u32 wakeup_config;
5357 } sleep_config[RK_PM_STATE_MAX];
5458
59
+/* rk_tag related defines */
60
+#define sleep_tag_next(t) \
61
+ ((struct rk_sleep_tag *)((__u32 *)(t) + (t)->hdr.size))
62
+
63
+struct rk_tag_header {
64
+ u32 size;
65
+ u32 tag;
66
+};
67
+
68
+struct rk_sleep_tag {
69
+ struct rk_tag_header hdr;
70
+ u32 params[];
71
+};
72
+
73
+struct rk_mcu_sleep_core_tag {
74
+ struct rk_tag_header hdr;
75
+ u32 total_size;
76
+ u32 reserve[13];
77
+};
78
+
79
+struct rk_mcu_sleep_tags {
80
+ struct rk_mcu_sleep_core_tag core;
81
+ struct rk_sleep_tag slp_tags;
82
+};
83
+
5584 static const struct of_device_id pm_match_table[] = {
5685 { .compatible = "rockchip,pm-px30",},
5786 { .compatible = "rockchip,pm-rk1808",},
....@@ -70,9 +99,19 @@
7099 };
71100
72101 #ifndef MODULE
102
+enum {
103
+ RK_PM_VIRT_PWROFF_EN = 0,
104
+ RK_PM_VIRT_PWROFF_IRQ_CFG = 1,
105
+ RK_PM_VIRT_PWROFF_MAX,
106
+};
107
+
108
+static u32 *virtual_pwroff_irqs;
109
+
73110 static void rockchip_pm_virt_pwroff_prepare(void)
74111 {
75
- int error;
112
+ int error, i;
113
+
114
+ pm_wakeup_clear(0);
76115
77116 regulator_suspend_prepare(PM_SUSPEND_MEM);
78117
....@@ -82,8 +121,58 @@
82121 return;
83122 }
84123
85
- sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, 0, 1);
124
+ sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, RK_PM_VIRT_PWROFF_EN, 1);
125
+
126
+ if (virtual_pwroff_irqs) {
127
+ for (i = 0; virtual_pwroff_irqs[i]; i++) {
128
+ error = sip_smc_set_suspend_mode(VIRTUAL_POWEROFF,
129
+ RK_PM_VIRT_PWROFF_IRQ_CFG,
130
+ virtual_pwroff_irqs[i]);
131
+ if (error) {
132
+ pr_err("%s: config virtual_pwroff_irqs[%d] error, overflow or update trust!\n",
133
+ __func__, i);
134
+ break;
135
+ }
136
+ }
137
+ }
138
+
86139 sip_smc_virtual_poweroff();
140
+}
141
+
142
+static int parse_virtual_pwroff_config(struct device_node *node)
143
+{
144
+ int ret = 0, cnt;
145
+ u32 virtual_poweroff_en = 0;
146
+
147
+ if (!of_property_read_u32_array(node,
148
+ "rockchip,virtual-poweroff",
149
+ &virtual_poweroff_en, 1) &&
150
+ virtual_poweroff_en)
151
+ pm_power_off_prepare = rockchip_pm_virt_pwroff_prepare;
152
+
153
+ if (!virtual_poweroff_en)
154
+ return 0;
155
+
156
+ cnt = of_property_count_u32_elems(node, "rockchip,virtual-poweroff-irqs");
157
+ if (cnt > 0) {
158
+ /* 0 as the last element of virtual_pwroff_irqs */
159
+ virtual_pwroff_irqs = kzalloc((cnt + 1) * sizeof(u32), GFP_KERNEL);
160
+ if (!virtual_pwroff_irqs) {
161
+ ret = -ENOMEM;
162
+ goto out;
163
+ }
164
+
165
+ ret = of_property_read_u32_array(node, "rockchip,virtual-poweroff-irqs",
166
+ virtual_pwroff_irqs, cnt);
167
+ if (ret) {
168
+ pr_err("%s: get rockchip,virtual-poweroff-irqs error\n",
169
+ __func__);
170
+ goto out;
171
+ }
172
+ }
173
+
174
+out:
175
+ return ret;
87176 }
88177
89178 static int parse_sleep_config(struct device_node *node, enum rk_pm_state state)
....@@ -166,6 +255,115 @@
166255 }
167256 #endif
168257
258
+static int parse_mcu_sleep_config(struct device_node *node)
259
+{
260
+ int ret, cnt;
261
+ struct arm_smccc_res res;
262
+ struct device_node *mcu_sleep_node;
263
+ struct device_node *child;
264
+ struct rk_mcu_sleep_tags *config;
265
+ struct rk_sleep_tag *slp_tag;
266
+ char *end;
267
+
268
+ mcu_sleep_node = of_find_node_by_name(node, "rockchip-mcu-sleep-cfg");
269
+ if (IS_ERR_OR_NULL(mcu_sleep_node)) {
270
+ ret = -ENODEV;
271
+ goto out;
272
+ }
273
+
274
+ cnt = of_get_child_count(mcu_sleep_node);
275
+ if (!cnt) {
276
+ ret = -EINVAL;
277
+ goto free_mcu_mode;
278
+ }
279
+
280
+ /*
281
+ * 4kb for sleep parameters
282
+ */
283
+ res = sip_smc_request_share_mem(1, SHARE_PAGE_TYPE_SLEEP);
284
+ if (res.a0 != 0) {
285
+ pr_err("%s: no trust memory for mcu_sleep\n", __func__);
286
+ ret = -ENOMEM;
287
+ goto free_mcu_mode;
288
+ }
289
+
290
+ /* Initialize core tag */
291
+ memset((void *)res.a1, 0, sizeof(struct rk_mcu_sleep_tags));
292
+ config = (struct rk_mcu_sleep_tags *)res.a1;
293
+ config->core.hdr.tag = RK_ATAG_MCU_SLP_CORE;
294
+ config->core.hdr.size = sizeof(struct rk_mcu_sleep_core_tag) / sizeof(u32);
295
+ config->core.total_size = sizeof(struct rk_mcu_sleep_tags) -
296
+ sizeof(struct rk_sleep_tag);
297
+
298
+ slp_tag = &config->slp_tags;
299
+
300
+ /* End point of sleep data */
301
+ end = (char *)config + PAGE_SIZE - sizeof(struct rk_sleep_tag);
302
+
303
+ for_each_available_child_of_node(mcu_sleep_node, child) {
304
+ /* Is overflow? */
305
+ if ((char *)slp_tag->params >= end)
306
+ break;
307
+
308
+ ret = of_property_read_u32_array(child, "rockchip,tag",
309
+ &slp_tag->hdr.tag, 1);
310
+ if (ret ||
311
+ slp_tag->hdr.tag <= RK_ATAG_MCU_SLP_CORE ||
312
+ slp_tag->hdr.tag >= RK_ATAG_MCU_SLP_MAX) {
313
+ pr_info("%s: no or invalid rockchip,tag in %s\n",
314
+ __func__, child->name);
315
+
316
+ continue;
317
+ }
318
+
319
+ cnt = of_property_count_u32_elems(child, "rockchip,params");
320
+ if (cnt > 0) {
321
+ /* Is overflow? */
322
+ if ((char *)(slp_tag->params + cnt) >= end) {
323
+ pr_warn("%s: no more space for rockchip,tag in %s\n",
324
+ __func__, child->name);
325
+ break;
326
+ }
327
+
328
+ ret = of_property_read_u32_array(child, "rockchip,params",
329
+ slp_tag->params, cnt);
330
+ if (ret) {
331
+ pr_err("%s: rockchip,params error in %s\n",
332
+ __func__, child->name);
333
+ break;
334
+ }
335
+
336
+ slp_tag->hdr.size =
337
+ cnt + sizeof(struct rk_tag_header) / sizeof(u32);
338
+ } else if (cnt == 0) {
339
+ slp_tag->hdr.size = 0;
340
+ } else {
341
+ continue;
342
+ }
343
+
344
+ config->core.total_size += slp_tag->hdr.size * sizeof(u32);
345
+
346
+ slp_tag = sleep_tag_next(slp_tag);
347
+ }
348
+
349
+ /* Add none tag.
350
+ * Compiler will combine the follow code as "str xzr, [x28]", but
351
+ * "slp->hdr" may not be 8-byte alignment. So we use memset_io instead:
352
+ * slp_tag->hdr.size = 0;
353
+ * slp_tag->hdr.tag = RK_ATAG_NONE;
354
+ */
355
+ memset_io(&slp_tag->hdr, 0, sizeof(slp_tag->hdr));
356
+
357
+ config->core.total_size += sizeof(struct rk_sleep_tag);
358
+
359
+ ret = 0;
360
+
361
+free_mcu_mode:
362
+ of_node_put(mcu_sleep_node);
363
+out:
364
+ return ret;
365
+}
366
+
169367 static int pm_config_probe(struct platform_device *pdev)
170368 {
171369 const struct of_device_id *match_id;
....@@ -177,9 +375,7 @@
177375 u32 apios_suspend = 0;
178376 u32 io_ret_config = 0;
179377 u32 sleep_pin_config[2] = {0};
180
-#ifndef MODULE
181
- u32 virtual_poweroff_en = 0;
182
-#endif
378
+
183379 enum of_gpio_flags flags;
184380 int i = 0;
185381 int length;
....@@ -270,12 +466,10 @@
270466 ret);
271467 }
272468
469
+ parse_mcu_sleep_config(node);
470
+
273471 #ifndef MODULE
274
- if (!of_property_read_u32_array(node,
275
- "rockchip,virtual-poweroff",
276
- &virtual_poweroff_en, 1) &&
277
- virtual_poweroff_en)
278
- pm_power_off_prepare = rockchip_pm_virt_pwroff_prepare;
472
+ parse_virtual_pwroff_config(node);
279473
280474 for (i = RK_PM_MEM; i < RK_PM_STATE_MAX; i++) {
281475 parse_sleep_config(node, i);