1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <subdev/mc.h>
26
27static irqreturn_t
28nouveau_mc_intr(int irq, void *arg)
29{
30 struct nouveau_mc *pmc = arg;
31 const struct nouveau_mc_intr *map = pmc->intr_map;
32 struct nouveau_subdev *unit;
33 u32 stat, intr;
34
35 intr = stat = nv_rd32(pmc, 0x000100);
36 while (stat && map->stat) {
37 if (stat & map->stat) {
38 unit = nouveau_subdev(pmc, map->unit);
39 if (unit && unit->intr)
40 unit->intr(unit);
41 intr &= ~map->stat;
42 }
43 map++;
44 }
45
46 if (intr) {
47 nv_error(pmc, "unknown intr 0x%08x\n", stat);
48 }
49
50 return stat ? IRQ_HANDLED : IRQ_NONE;
51}
52
53int
54_nouveau_mc_fini(struct nouveau_object *object, bool suspend)
55{
56 struct nouveau_mc *pmc = (void *)object;
57 nv_wr32(pmc, 0x000140, 0x00000000);
58 return nouveau_subdev_fini(&pmc->base, suspend);
59}
60
61int
62_nouveau_mc_init(struct nouveau_object *object)
63{
64 struct nouveau_mc *pmc = (void *)object;
65 int ret = nouveau_subdev_init(&pmc->base);
66 if (ret)
67 return ret;
68 nv_wr32(pmc, 0x000140, 0x00000001);
69 return 0;
70}
71
72void
73_nouveau_mc_dtor(struct nouveau_object *object)
74{
75 struct nouveau_device *device = nv_device(object);
76 struct nouveau_mc *pmc = (void *)object;
77 free_irq(device->pdev->irq, pmc);
78 nouveau_subdev_destroy(&pmc->base);
79}
80
81int
82nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
83 struct nouveau_oclass *oclass, int length, void **pobject)
84{
85 struct nouveau_device *device = nv_device(parent);
86 struct nouveau_mc *pmc;
87 int ret;
88
89 ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PMC",
90 "master", length, pobject);
91 pmc = *pobject;
92 if (ret)
93 return ret;
94
95 ret = request_irq(device->pdev->irq, nouveau_mc_intr,
96 IRQF_SHARED, "nouveau", pmc);
97 if (ret < 0)
98 return ret;
99
100 return 0;
101}
102