xref: /aosp_15_r20/external/mesa3d/src/freedreno/perfcntrs/freedreno_dt.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2021 Google, Inc.
3*61046927SAndroid Build Coastguard Worker  * All Rights Reserved.
4*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker  */
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
8*61046927SAndroid Build Coastguard Worker #include <ftw.h>
9*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
10*61046927SAndroid Build Coastguard Worker #include <stdint.h>
11*61046927SAndroid Build Coastguard Worker #include <stdio.h>
12*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
13*61046927SAndroid Build Coastguard Worker #include <string.h>
14*61046927SAndroid Build Coastguard Worker #include <unistd.h>
15*61046927SAndroid Build Coastguard Worker #include <arpa/inet.h>
16*61046927SAndroid Build Coastguard Worker #include <sys/mman.h>
17*61046927SAndroid Build Coastguard Worker #include <sys/stat.h>
18*61046927SAndroid Build Coastguard Worker #include <sys/types.h>
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
21*61046927SAndroid Build Coastguard Worker #include "util/os_file.h"
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker #include "freedreno_dt.h"
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker static struct {
26*61046927SAndroid Build Coastguard Worker    char *dtnode;
27*61046927SAndroid Build Coastguard Worker    int address_cells, size_cells;
28*61046927SAndroid Build Coastguard Worker    uint64_t base;
29*61046927SAndroid Build Coastguard Worker    uint32_t size;
30*61046927SAndroid Build Coastguard Worker    uint32_t min_freq;
31*61046927SAndroid Build Coastguard Worker    uint32_t max_freq;
32*61046927SAndroid Build Coastguard Worker } dev;
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker /*
35*61046927SAndroid Build Coastguard Worker  * code to find stuff in /proc/device-tree:
36*61046927SAndroid Build Coastguard Worker  *
37*61046927SAndroid Build Coastguard Worker  * NOTE: if we sampled the counters from the cmdstream, we could avoid needing
38*61046927SAndroid Build Coastguard Worker  * /dev/mem and /proc/device-tree crawling.  OTOH when the GPU is heavily loaded
39*61046927SAndroid Build Coastguard Worker  * we would be competing with whatever else is using the GPU.
40*61046927SAndroid Build Coastguard Worker  */
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker static void *
readdt(const char * node)43*61046927SAndroid Build Coastguard Worker readdt(const char *node)
44*61046927SAndroid Build Coastguard Worker {
45*61046927SAndroid Build Coastguard Worker    char *path;
46*61046927SAndroid Build Coastguard Worker    void *buf;
47*61046927SAndroid Build Coastguard Worker    size_t sz;
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker    (void)asprintf(&path, "%s/%s", dev.dtnode, node);
50*61046927SAndroid Build Coastguard Worker    buf = os_read_file(path, &sz);
51*61046927SAndroid Build Coastguard Worker    free(path);
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker    return buf;
54*61046927SAndroid Build Coastguard Worker }
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker static int
find_freqs_fn(const char * fpath,const struct stat * sb,int typeflag,struct FTW * ftwbuf)57*61046927SAndroid Build Coastguard Worker find_freqs_fn(const char *fpath, const struct stat *sb, int typeflag,
58*61046927SAndroid Build Coastguard Worker               struct FTW *ftwbuf)
59*61046927SAndroid Build Coastguard Worker {
60*61046927SAndroid Build Coastguard Worker    const char *fname = fpath + ftwbuf->base;
61*61046927SAndroid Build Coastguard Worker    size_t sz;
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker    if (strcmp(fname, "qcom,gpu-freq") == 0) {
64*61046927SAndroid Build Coastguard Worker       uint32_t *buf = (uint32_t *)os_read_file(fpath, &sz);
65*61046927SAndroid Build Coastguard Worker       uint32_t freq = ntohl(buf[0]);
66*61046927SAndroid Build Coastguard Worker       free(buf);
67*61046927SAndroid Build Coastguard Worker       dev.max_freq = MAX2(dev.max_freq, freq);
68*61046927SAndroid Build Coastguard Worker       dev.min_freq = MIN2(dev.min_freq, freq);
69*61046927SAndroid Build Coastguard Worker    }
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker    return 0;
72*61046927SAndroid Build Coastguard Worker }
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker static void
find_freqs(void)75*61046927SAndroid Build Coastguard Worker find_freqs(void)
76*61046927SAndroid Build Coastguard Worker {
77*61046927SAndroid Build Coastguard Worker    char *path;
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    dev.min_freq = ~0;
80*61046927SAndroid Build Coastguard Worker    dev.max_freq = 0;
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker    (void)asprintf(&path, "%s/%s", dev.dtnode, "qcom,gpu-pwrlevels");
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    nftw(path, find_freqs_fn, 64, 0);
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker    free(path);
87*61046927SAndroid Build Coastguard Worker }
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker static const char *compatibles[] = {
90*61046927SAndroid Build Coastguard Worker    "qcom,adreno-3xx",
91*61046927SAndroid Build Coastguard Worker    "qcom,kgsl-3d0",
92*61046927SAndroid Build Coastguard Worker    "amd,imageon",
93*61046927SAndroid Build Coastguard Worker    "qcom,adreno",
94*61046927SAndroid Build Coastguard Worker };
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker /**
97*61046927SAndroid Build Coastguard Worker  * compatstrs is a list of compatible strings separated by null, ie.
98*61046927SAndroid Build Coastguard Worker  *
99*61046927SAndroid Build Coastguard Worker  *       compatible = "qcom,adreno-630.2", "qcom,adreno";
100*61046927SAndroid Build Coastguard Worker  *
101*61046927SAndroid Build Coastguard Worker  * would result in "qcom,adreno-630.2\0qcom,adreno\0"
102*61046927SAndroid Build Coastguard Worker  */
103*61046927SAndroid Build Coastguard Worker static bool
match_compatible(char * compatstrs,int sz)104*61046927SAndroid Build Coastguard Worker match_compatible(char *compatstrs, int sz)
105*61046927SAndroid Build Coastguard Worker {
106*61046927SAndroid Build Coastguard Worker    while (sz > 0) {
107*61046927SAndroid Build Coastguard Worker       char *compatible = compatstrs;
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < ARRAY_SIZE(compatibles); i++) {
110*61046927SAndroid Build Coastguard Worker          if (strcmp(compatible, compatibles[i]) == 0) {
111*61046927SAndroid Build Coastguard Worker             return true;
112*61046927SAndroid Build Coastguard Worker          }
113*61046927SAndroid Build Coastguard Worker       }
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker       compatstrs += strlen(compatible) + 1;
116*61046927SAndroid Build Coastguard Worker       sz -= strlen(compatible) + 1;
117*61046927SAndroid Build Coastguard Worker    }
118*61046927SAndroid Build Coastguard Worker    return false;
119*61046927SAndroid Build Coastguard Worker }
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker static int
find_device_fn(const char * fpath,const struct stat * sb,int typeflag,struct FTW * ftwbuf)122*61046927SAndroid Build Coastguard Worker find_device_fn(const char *fpath, const struct stat *sb, int typeflag,
123*61046927SAndroid Build Coastguard Worker                struct FTW *ftwbuf)
124*61046927SAndroid Build Coastguard Worker {
125*61046927SAndroid Build Coastguard Worker    const char *fname = fpath + ftwbuf->base;
126*61046927SAndroid Build Coastguard Worker    size_t sz;
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    if (strcmp(fname, "compatible") == 0) {
129*61046927SAndroid Build Coastguard Worker       char *str = os_read_file(fpath, &sz);
130*61046927SAndroid Build Coastguard Worker       if (match_compatible(str, sz)) {
131*61046927SAndroid Build Coastguard Worker          int dlen = strlen(fpath) - strlen("/compatible");
132*61046927SAndroid Build Coastguard Worker          dev.dtnode = malloc(dlen + 1);
133*61046927SAndroid Build Coastguard Worker          memcpy(dev.dtnode, fpath, dlen);
134*61046927SAndroid Build Coastguard Worker          dev.dtnode[dlen] = '\0';
135*61046927SAndroid Build Coastguard Worker          printf("found dt node: %s\n", dev.dtnode);
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker          char buf[dlen + sizeof("/../#address-cells") + 1];
138*61046927SAndroid Build Coastguard Worker          size_t sz;
139*61046927SAndroid Build Coastguard Worker          int *val;
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker          sprintf(buf, "%s/../#address-cells", dev.dtnode);
142*61046927SAndroid Build Coastguard Worker          val = (int *)os_read_file(buf, &sz);
143*61046927SAndroid Build Coastguard Worker          dev.address_cells = ntohl(*val);
144*61046927SAndroid Build Coastguard Worker          free(val);
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker          sprintf(buf, "%s/../#size-cells", dev.dtnode);
147*61046927SAndroid Build Coastguard Worker          val = (int *)os_read_file(buf, &sz);
148*61046927SAndroid Build Coastguard Worker          dev.size_cells = ntohl(*val);
149*61046927SAndroid Build Coastguard Worker          free(val);
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker          printf("#address-cells=%d, #size-cells=%d\n", dev.address_cells,
152*61046927SAndroid Build Coastguard Worker                 dev.size_cells);
153*61046927SAndroid Build Coastguard Worker       }
154*61046927SAndroid Build Coastguard Worker       free(str);
155*61046927SAndroid Build Coastguard Worker    }
156*61046927SAndroid Build Coastguard Worker    if (dev.dtnode) {
157*61046927SAndroid Build Coastguard Worker       /* we found it! */
158*61046927SAndroid Build Coastguard Worker       return 1;
159*61046927SAndroid Build Coastguard Worker    }
160*61046927SAndroid Build Coastguard Worker    return 0;
161*61046927SAndroid Build Coastguard Worker }
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker static bool
find_device(void)164*61046927SAndroid Build Coastguard Worker find_device(void)
165*61046927SAndroid Build Coastguard Worker {
166*61046927SAndroid Build Coastguard Worker    int ret;
167*61046927SAndroid Build Coastguard Worker    uint32_t *buf, *b;
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    if (dev.dtnode)
170*61046927SAndroid Build Coastguard Worker       return true;
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker    ret = nftw("/proc/device-tree/", find_device_fn, 64, 0);
173*61046927SAndroid Build Coastguard Worker    if (ret < 0)
174*61046927SAndroid Build Coastguard Worker       return false;
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker    if (!dev.dtnode)
177*61046927SAndroid Build Coastguard Worker       return false;
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker    b = buf = readdt("reg");
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    if (dev.address_cells == 2) {
182*61046927SAndroid Build Coastguard Worker       uint32_t u[2] = {ntohl(buf[0]), ntohl(buf[1])};
183*61046927SAndroid Build Coastguard Worker       dev.base = (((uint64_t)u[0]) << 32) | u[1];
184*61046927SAndroid Build Coastguard Worker       buf += 2;
185*61046927SAndroid Build Coastguard Worker    } else {
186*61046927SAndroid Build Coastguard Worker       dev.base = ntohl(buf[0]);
187*61046927SAndroid Build Coastguard Worker       buf += 1;
188*61046927SAndroid Build Coastguard Worker    }
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker    if (dev.size_cells == 2) {
191*61046927SAndroid Build Coastguard Worker       uint32_t u[2] = {ntohl(buf[0]), ntohl(buf[1])};
192*61046927SAndroid Build Coastguard Worker       dev.size = (((uint64_t)u[0]) << 32) | u[1];
193*61046927SAndroid Build Coastguard Worker       buf += 2;
194*61046927SAndroid Build Coastguard Worker    } else {
195*61046927SAndroid Build Coastguard Worker       dev.size = ntohl(buf[0]);
196*61046927SAndroid Build Coastguard Worker       buf += 1;
197*61046927SAndroid Build Coastguard Worker    }
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker    free(b);
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker    printf("i/o region at %08" PRIx64 " (size: %x)\n", dev.base, dev.size);
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    find_freqs();
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker    printf("min_freq=%u, max_freq=%u\n", dev.min_freq, dev.max_freq);
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker    return true;
208*61046927SAndroid Build Coastguard Worker }
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker bool
fd_dt_find_freqs(uint32_t * min_freq,uint32_t * max_freq)211*61046927SAndroid Build Coastguard Worker fd_dt_find_freqs(uint32_t *min_freq, uint32_t *max_freq)
212*61046927SAndroid Build Coastguard Worker {
213*61046927SAndroid Build Coastguard Worker    if (!find_device())
214*61046927SAndroid Build Coastguard Worker       return false;
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    *min_freq = dev.min_freq;
217*61046927SAndroid Build Coastguard Worker    *max_freq = dev.max_freq;
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    return true;
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker void *
fd_dt_find_io(void)223*61046927SAndroid Build Coastguard Worker fd_dt_find_io(void)
224*61046927SAndroid Build Coastguard Worker {
225*61046927SAndroid Build Coastguard Worker    if (!find_device())
226*61046927SAndroid Build Coastguard Worker       return NULL;
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    int fd = open("/dev/mem", O_RDWR | O_SYNC);
229*61046927SAndroid Build Coastguard Worker    if (fd < 0)
230*61046927SAndroid Build Coastguard Worker       return NULL;
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker    void *io =
233*61046927SAndroid Build Coastguard Worker       mmap(0, dev.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, dev.base);
234*61046927SAndroid Build Coastguard Worker    close(fd);
235*61046927SAndroid Build Coastguard Worker    if (io == MAP_FAILED)
236*61046927SAndroid Build Coastguard Worker       return NULL;
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker    return io;
239*61046927SAndroid Build Coastguard Worker }
240