1be61c54cSBen Skeggs /*
2be61c54cSBen Skeggs  * Copyright 2012 Red Hat Inc.
3be61c54cSBen Skeggs  *
4be61c54cSBen Skeggs  * Permission is hereby granted, free of charge, to any person obtaining a
5be61c54cSBen Skeggs  * copy of this software and associated documentation files (the "Software"),
6be61c54cSBen Skeggs  * to deal in the Software without restriction, including without limitation
7be61c54cSBen Skeggs  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8be61c54cSBen Skeggs  * and/or sell copies of the Software, and to permit persons to whom the
9be61c54cSBen Skeggs  * Software is furnished to do so, subject to the following conditions:
10be61c54cSBen Skeggs  *
11be61c54cSBen Skeggs  * The above copyright notice and this permission notice shall be included in
12be61c54cSBen Skeggs  * all copies or substantial portions of the Software.
13be61c54cSBen Skeggs  *
14be61c54cSBen Skeggs  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15be61c54cSBen Skeggs  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16be61c54cSBen Skeggs  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17be61c54cSBen Skeggs  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18be61c54cSBen Skeggs  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19be61c54cSBen Skeggs  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20be61c54cSBen Skeggs  * OTHER DEALINGS IN THE SOFTWARE.
21be61c54cSBen Skeggs  *
22be61c54cSBen Skeggs  * Authors: Ben Skeggs
23be61c54cSBen Skeggs  */
24be61c54cSBen Skeggs #define gp100_mc(p) container_of((p), struct gp100_mc, base)
25be61c54cSBen Skeggs #include "priv.h"
26be61c54cSBen Skeggs 
27be61c54cSBen Skeggs struct gp100_mc {
28be61c54cSBen Skeggs 	struct nvkm_mc base;
29be61c54cSBen Skeggs 	spinlock_t lock;
30be61c54cSBen Skeggs 	bool intr;
31be61c54cSBen Skeggs 	u32 mask;
32be61c54cSBen Skeggs };
33be61c54cSBen Skeggs 
34be61c54cSBen Skeggs static void
35be61c54cSBen Skeggs gp100_mc_intr_update(struct gp100_mc *mc)
36be61c54cSBen Skeggs {
37be61c54cSBen Skeggs 	struct nvkm_device *device = mc->base.subdev.device;
38be61c54cSBen Skeggs 	u32 mask = mc->intr ? mc->mask : 0, i;
39be61c54cSBen Skeggs 	for (i = 0; i < 2; i++) {
40be61c54cSBen Skeggs 		nvkm_wr32(device, 0x000180 + (i * 0x04), ~mask);
41be61c54cSBen Skeggs 		nvkm_wr32(device, 0x000160 + (i * 0x04),  mask);
42be61c54cSBen Skeggs 	}
43be61c54cSBen Skeggs }
44be61c54cSBen Skeggs 
45be61c54cSBen Skeggs static void
46be61c54cSBen Skeggs gp100_mc_intr_unarm(struct nvkm_mc *base)
47be61c54cSBen Skeggs {
48be61c54cSBen Skeggs 	struct gp100_mc *mc = gp100_mc(base);
49be61c54cSBen Skeggs 	unsigned long flags;
50be61c54cSBen Skeggs 	spin_lock_irqsave(&mc->lock, flags);
51be61c54cSBen Skeggs 	mc->intr = false;
52be61c54cSBen Skeggs 	gp100_mc_intr_update(mc);
53be61c54cSBen Skeggs 	spin_unlock_irqrestore(&mc->lock, flags);
54be61c54cSBen Skeggs }
55be61c54cSBen Skeggs 
56be61c54cSBen Skeggs static void
57be61c54cSBen Skeggs gp100_mc_intr_rearm(struct nvkm_mc *base)
58be61c54cSBen Skeggs {
59be61c54cSBen Skeggs 	struct gp100_mc *mc = gp100_mc(base);
60be61c54cSBen Skeggs 	unsigned long flags;
61be61c54cSBen Skeggs 	spin_lock_irqsave(&mc->lock, flags);
62be61c54cSBen Skeggs 	mc->intr = true;
63be61c54cSBen Skeggs 	gp100_mc_intr_update(mc);
64be61c54cSBen Skeggs 	spin_unlock_irqrestore(&mc->lock, flags);
65be61c54cSBen Skeggs }
66be61c54cSBen Skeggs 
67be61c54cSBen Skeggs static void
68be61c54cSBen Skeggs gp100_mc_intr_mask(struct nvkm_mc *base, u32 mask, u32 intr)
69be61c54cSBen Skeggs {
70be61c54cSBen Skeggs 	struct gp100_mc *mc = gp100_mc(base);
71be61c54cSBen Skeggs 	unsigned long flags;
72be61c54cSBen Skeggs 	spin_lock_irqsave(&mc->lock, flags);
73be61c54cSBen Skeggs 	mc->mask = (mc->mask & ~mask) | intr;
74be61c54cSBen Skeggs 	gp100_mc_intr_update(mc);
75be61c54cSBen Skeggs 	spin_unlock_irqrestore(&mc->lock, flags);
76be61c54cSBen Skeggs }
77be61c54cSBen Skeggs 
78be61c54cSBen Skeggs static const struct nvkm_mc_func
79be61c54cSBen Skeggs gp100_mc = {
80be61c54cSBen Skeggs 	.init = nv50_mc_init,
81be61c54cSBen Skeggs 	.intr = gk104_mc_intr,
82be61c54cSBen Skeggs 	.intr_unarm = gp100_mc_intr_unarm,
83be61c54cSBen Skeggs 	.intr_rearm = gp100_mc_intr_rearm,
84be61c54cSBen Skeggs 	.intr_mask = gp100_mc_intr_mask,
85be61c54cSBen Skeggs 	.intr_stat = gf100_mc_intr_stat,
86be61c54cSBen Skeggs 	.reset = gk104_mc_reset,
87be61c54cSBen Skeggs };
88be61c54cSBen Skeggs 
89be61c54cSBen Skeggs int
90be61c54cSBen Skeggs gp100_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
91be61c54cSBen Skeggs {
92be61c54cSBen Skeggs 	struct gp100_mc *mc;
93be61c54cSBen Skeggs 
94be61c54cSBen Skeggs 	if (!(mc = kzalloc(sizeof(*mc), GFP_KERNEL)))
95be61c54cSBen Skeggs 		return -ENOMEM;
96be61c54cSBen Skeggs 	nvkm_mc_ctor(&gp100_mc, device, index, &mc->base);
97be61c54cSBen Skeggs 	*pmc = &mc->base;
98be61c54cSBen Skeggs 
99be61c54cSBen Skeggs 	spin_lock_init(&mc->lock);
100be61c54cSBen Skeggs 	mc->intr = false;
101be61c54cSBen Skeggs 	mc->mask = 0x7fffffff;
102be61c54cSBen Skeggs 	return 0;
103be61c54cSBen Skeggs }
104