1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "priv.h"
25
26#include <core/option.h>
27#include <subdev/top.h>
28
29void
30nvkm_mc_unk260(struct nvkm_device *device, u32 data)
31{
32 struct nvkm_mc *mc = device->mc;
33 if (likely(mc) && mc->func->unk260)
34 mc->func->unk260(mc, data);
35}
36
37void
38nvkm_mc_intr_mask(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, bool en)
39{
40 struct nvkm_mc *mc = device->mc;
41 const struct nvkm_mc_map *map;
42 if (likely(mc) && mc->func->intr_mask) {
43 u32 mask = nvkm_top_intr_mask(device, type, inst);
44 for (map = mc->func->intr; !mask && map->stat; map++) {
45 if (map->type == type && map->inst == inst)
46 mask = map->stat;
47 }
48 mc->func->intr_mask(mc, mask, en ? mask : 0);
49 }
50}
51
52void
53nvkm_mc_intr_unarm(struct nvkm_device *device)
54{
55 struct nvkm_mc *mc = device->mc;
56 if (likely(mc))
57 mc->func->intr_unarm(mc);
58}
59
60void
61nvkm_mc_intr_rearm(struct nvkm_device *device)
62{
63 struct nvkm_mc *mc = device->mc;
64 if (likely(mc))
65 mc->func->intr_rearm(mc);
66}
67
68static u32
69nvkm_mc_intr_stat(struct nvkm_mc *mc)
70{
71 u32 intr = mc->func->intr_stat(mc);
72 if (WARN_ON_ONCE(intr == 0xffffffff))
73 intr = 0;
74 return intr;
75}
76
77void
78nvkm_mc_intr(struct nvkm_device *device, bool *handled)
79{
80 struct nvkm_mc *mc = device->mc;
81 struct nvkm_top *top = device->top;
82 struct nvkm_top_device *tdev;
83 struct nvkm_subdev *subdev;
84 const struct nvkm_mc_map *map;
85 u32 stat, intr;
86
87 if (unlikely(!mc))
88 return;
89
90 stat = intr = nvkm_mc_intr_stat(mc);
91
92 if (top) {
93 list_for_each_entry(tdev, &top->device, head) {
94 if (tdev->intr >= 0 && (stat & BIT(tdev->intr))) {
95 subdev = nvkm_device_subdev(device, tdev->type, tdev->inst);
96 if (subdev) {
97 nvkm_subdev_intr(subdev);
98 stat &= ~BIT(tdev->intr);
99 if (!stat)
100 break;
101 }
102 }
103 }
104 }
105
106 for (map = mc->func->intr; map->stat; map++) {
107 if (intr & map->stat) {
108 subdev = nvkm_device_subdev(device, map->type, map->inst);
109 if (subdev)
110 nvkm_subdev_intr(subdev);
111 stat &= ~map->stat;
112 }
113 }
114
115 if (stat)
116 nvkm_error(&mc->subdev, "intr %08x\n", stat);
117 *handled = intr != 0;
118}
119
120static u32
121nvkm_mc_reset_mask(struct nvkm_device *device, bool isauto, enum nvkm_subdev_type type, int inst)
122{
123 struct nvkm_mc *mc = device->mc;
124 const struct nvkm_mc_map *map;
125 u64 pmc_enable = 0;
126 if (likely(mc)) {
127 if (!(pmc_enable = nvkm_top_reset(device, type, inst))) {
128 for (map = mc->func->reset; map && map->stat; map++) {
129 if (!isauto || !map->noauto) {
130 if (map->type == type && map->inst == inst) {
131 pmc_enable = map->stat;
132 break;
133 }
134 }
135 }
136 }
137 }
138 return pmc_enable;
139}
140
141void
142nvkm_mc_reset(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
143{
144 u64 pmc_enable = nvkm_mc_reset_mask(device, true, type, inst);
145 if (pmc_enable) {
146 nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
147 nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
148 nvkm_rd32(device, 0x000200);
149 }
150}
151
152void
153nvkm_mc_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
154{
155 u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
156 if (pmc_enable)
157 nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
158}
159
160void
161nvkm_mc_enable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
162{
163 u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
164 if (pmc_enable) {
165 nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
166 nvkm_rd32(device, 0x000200);
167 }
168}
169
170bool
171nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
172{
173 u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
174
175 return (pmc_enable != 0) &&
176 ((nvkm_rd32(device, 0x000200) & pmc_enable) == pmc_enable);
177}
178
179
180static int
181nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
182{
183 nvkm_mc_intr_unarm(subdev->device);
184 return 0;
185}
186
187static int
188nvkm_mc_init(struct nvkm_subdev *subdev)
189{
190 struct nvkm_mc *mc = nvkm_mc(subdev);
191 if (mc->func->init)
192 mc->func->init(mc);
193 nvkm_mc_intr_rearm(subdev->device);
194 return 0;
195}
196
197static void *
198nvkm_mc_dtor(struct nvkm_subdev *subdev)
199{
200 return nvkm_mc(subdev);
201}
202
203static const struct nvkm_subdev_func
204nvkm_mc = {
205 .dtor = nvkm_mc_dtor,
206 .init = nvkm_mc_init,
207 .fini = nvkm_mc_fini,
208};
209
210void
211nvkm_mc_ctor(const struct nvkm_mc_func *func, struct nvkm_device *device,
212 enum nvkm_subdev_type type, int inst, struct nvkm_mc *mc)
213{
214 nvkm_subdev_ctor(&nvkm_mc, device, type, inst, &mc->subdev);
215 mc->func = func;
216}
217
218int
219nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
220 enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
221{
222 struct nvkm_mc *mc;
223 if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL)))
224 return -ENOMEM;
225 nvkm_mc_ctor(func, device, type, inst, *pmc);
226 return 0;
227}
228