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