imx8: disable node when the resource is not owned
[platform/kernel/u-boot.git] / arch / arm / mach-imx / imx8 / fdt.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 NXP
4  */
5
6 #include <common.h>
7 #include <asm/arch/sci/sci.h>
8 #include <dm/ofnode.h>
9 #include <fdt_support.h>
10
11 DECLARE_GLOBAL_DATA_PTR;
12
13 static bool check_owned_resource(sc_rsrc_t rsrc_id)
14 {
15         bool owned;
16
17         owned = sc_rm_is_resource_owned(-1, rsrc_id);
18
19         return owned;
20 }
21
22 static int disable_fdt_node(void *blob, int nodeoffset)
23 {
24         int rc, ret;
25         const char *status = "disabled";
26
27         do {
28                 rc = fdt_setprop(blob, nodeoffset, "status", status,
29                                  strlen(status) + 1);
30                 if (rc) {
31                         if (rc == -FDT_ERR_NOSPACE) {
32                                 ret = fdt_increase_size(blob, 512);
33                                 if (ret)
34                                         return ret;
35                         }
36                 }
37         } while (rc == -FDT_ERR_NOSPACE);
38
39         return rc;
40 }
41
42 static void update_fdt_with_owned_resources(void *blob)
43 {
44         /*
45          * Traverses the fdt nodes, check its power domain and use
46          * the resource id in the power domain for checking whether
47          * it is owned by current partition
48          */
49         struct fdtdec_phandle_args args;
50         int offset = 0, depth = 0;
51         u32 rsrc_id;
52         int rc, i;
53
54         for (offset = fdt_next_node(blob, offset, &depth); offset > 0;
55              offset = fdt_next_node(blob, offset, &depth)) {
56                 debug("Node name: %s, depth %d\n",
57                       fdt_get_name(blob, offset, NULL), depth);
58
59                 if (!fdt_get_property(blob, offset, "power-domains", NULL)) {
60                         debug("   - ignoring node %s\n",
61                               fdt_get_name(blob, offset, NULL));
62                         continue;
63                 }
64
65                 if (!fdtdec_get_is_enabled(blob, offset)) {
66                         debug("   - ignoring node %s\n",
67                               fdt_get_name(blob, offset, NULL));
68                         continue;
69                 }
70
71                 i = 0;
72                 while (true) {
73                         rc = fdtdec_parse_phandle_with_args(blob, offset,
74                                                             "power-domains",
75                                                             "#power-domain-cells",
76                                                             0, i++, &args);
77                         if (rc == -ENOENT) {
78                                 break;
79                         } else if (rc) {
80                                 printf("Parse power-domains of %s wrong: %d\n",
81                                        fdt_get_name(blob, offset, NULL), rc);
82                                 continue;
83                         }
84
85                         rsrc_id = args.args[0];
86
87                         if (!check_owned_resource(rsrc_id)) {
88                                 rc = disable_fdt_node(blob, offset);
89                                 if (!rc) {
90                                         printf("Disable %s rsrc %u not owned\n",
91                                                fdt_get_name(blob, offset, NULL),
92                                                rsrc_id);
93                                 } else {
94                                         printf("Unable to disable %s, err=%s\n",
95                                                fdt_get_name(blob, offset, NULL),
96                                                fdt_strerror(rc));
97                                 }
98                         }
99                 }
100         }
101 }
102
103 int ft_system_setup(void *blob, bd_t *bd)
104 {
105         update_fdt_with_owned_resources(blob);
106
107         return 0;
108 }