1 | /* $NetBSD: nouveau_engine_perfmon_nv40.c,v 1.1.1.1 2014/08/06 12:36:27 riastradh Exp $ */ |
2 | |
3 | /* |
4 | * Copyright 2013 Red Hat Inc. |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), |
8 | * to deal in the Software without restriction, including without limitation |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
10 | * and/or sell copies of the Software, and to permit persons to whom the |
11 | * Software is furnished to do so, subject to the following conditions: |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in |
14 | * all copies or substantial portions of the Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
23 | * |
24 | * Authors: Ben Skeggs |
25 | */ |
26 | |
27 | #include <sys/cdefs.h> |
28 | __KERNEL_RCSID(0, "$NetBSD: nouveau_engine_perfmon_nv40.c,v 1.1.1.1 2014/08/06 12:36:27 riastradh Exp $" ); |
29 | |
30 | #include "nv40.h" |
31 | |
32 | /******************************************************************************* |
33 | * Perfmon object classes |
34 | ******************************************************************************/ |
35 | |
36 | /******************************************************************************* |
37 | * PPM context |
38 | ******************************************************************************/ |
39 | |
40 | /******************************************************************************* |
41 | * PPM engine/subdev functions |
42 | ******************************************************************************/ |
43 | |
44 | static void |
45 | nv40_perfctr_init(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom, |
46 | struct nouveau_perfctr *ctr) |
47 | { |
48 | struct nv40_perfmon_priv *priv = (void *)ppm; |
49 | struct nv40_perfmon_cntr *cntr = (void *)ctr; |
50 | u32 log = ctr->logic_op; |
51 | u32 src = 0x00000000; |
52 | int i; |
53 | |
54 | for (i = 0; i < 4 && ctr->signal[i]; i++) |
55 | src |= (ctr->signal[i] - dom->signal) << (i * 8); |
56 | |
57 | nv_wr32(priv, 0x00a7c0 + dom->addr, 0x00000001); |
58 | nv_wr32(priv, 0x00a400 + dom->addr + (cntr->base.slot * 0x40), src); |
59 | nv_wr32(priv, 0x00a420 + dom->addr + (cntr->base.slot * 0x40), log); |
60 | } |
61 | |
62 | static void |
63 | nv40_perfctr_read(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom, |
64 | struct nouveau_perfctr *ctr) |
65 | { |
66 | struct nv40_perfmon_priv *priv = (void *)ppm; |
67 | struct nv40_perfmon_cntr *cntr = (void *)ctr; |
68 | |
69 | switch (cntr->base.slot) { |
70 | case 0: cntr->base.ctr = nv_rd32(priv, 0x00a700 + dom->addr); break; |
71 | case 1: cntr->base.ctr = nv_rd32(priv, 0x00a6c0 + dom->addr); break; |
72 | case 2: cntr->base.ctr = nv_rd32(priv, 0x00a680 + dom->addr); break; |
73 | case 3: cntr->base.ctr = nv_rd32(priv, 0x00a740 + dom->addr); break; |
74 | } |
75 | cntr->base.clk = nv_rd32(priv, 0x00a600 + dom->addr); |
76 | } |
77 | |
78 | static void |
79 | nv40_perfctr_next(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom) |
80 | { |
81 | struct nv40_perfmon_priv *priv = (void *)ppm; |
82 | if (priv->sequence != ppm->sequence) { |
83 | nv_wr32(priv, 0x400084, 0x00000020); |
84 | priv->sequence = ppm->sequence; |
85 | } |
86 | } |
87 | |
88 | const struct nouveau_funcdom |
89 | nv40_perfctr_func = { |
90 | .init = nv40_perfctr_init, |
91 | .read = nv40_perfctr_read, |
92 | .next = nv40_perfctr_next, |
93 | }; |
94 | |
95 | static const struct nouveau_specdom |
96 | nv40_perfmon[] = { |
97 | { 0x20, (const struct nouveau_specsig[]) { |
98 | {} |
99 | }, &nv40_perfctr_func }, |
100 | { 0x20, (const struct nouveau_specsig[]) { |
101 | {} |
102 | }, &nv40_perfctr_func }, |
103 | { 0x20, (const struct nouveau_specsig[]) { |
104 | {} |
105 | }, &nv40_perfctr_func }, |
106 | { 0x20, (const struct nouveau_specsig[]) { |
107 | {} |
108 | }, &nv40_perfctr_func }, |
109 | { 0x20, (const struct nouveau_specsig[]) { |
110 | {} |
111 | }, &nv40_perfctr_func }, |
112 | {} |
113 | }; |
114 | |
115 | int |
116 | nv40_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
117 | struct nouveau_oclass *oclass, void *data, u32 size, |
118 | struct nouveau_object **pobject) |
119 | { |
120 | struct nv40_perfmon_oclass *mclass = (void *)oclass; |
121 | struct nv40_perfmon_priv *priv; |
122 | int ret; |
123 | |
124 | ret = nouveau_perfmon_create(parent, engine, oclass, &priv); |
125 | *pobject = nv_object(priv); |
126 | if (ret) |
127 | return ret; |
128 | |
129 | ret = nouveau_perfdom_new(&priv->base, "pm" , 0, 0, 0, 4, mclass->doms); |
130 | if (ret) |
131 | return ret; |
132 | |
133 | nv_engine(priv)->cclass = &nouveau_perfmon_cclass; |
134 | nv_engine(priv)->sclass = nouveau_perfmon_sclass; |
135 | return 0; |
136 | } |
137 | |
138 | struct nouveau_oclass * |
139 | nv40_perfmon_oclass = &(struct nv40_perfmon_oclass) { |
140 | .base.handle = NV_ENGINE(PERFMON, 0x40), |
141 | .base.ofuncs = &(struct nouveau_ofuncs) { |
142 | .ctor = nv40_perfmon_ctor, |
143 | .dtor = _nouveau_perfmon_dtor, |
144 | .init = _nouveau_perfmon_init, |
145 | .fini = _nouveau_perfmon_fini, |
146 | }, |
147 | .doms = nv40_perfmon, |
148 | }.base; |
149 | |