Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2018 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  */
0022 #define tu102_mc(p) container_of((p), struct tu102_mc, base)
0023 #include "priv.h"
0024 
0025 struct tu102_mc {
0026     struct nvkm_mc base;
0027     spinlock_t lock;
0028     bool intr;
0029     u32 mask;
0030 };
0031 
0032 static void
0033 tu102_mc_intr_update(struct tu102_mc *mc)
0034 {
0035     struct nvkm_device *device = mc->base.subdev.device;
0036     u32 mask = mc->intr ? mc->mask : 0, i;
0037 
0038     for (i = 0; i < 2; i++) {
0039         nvkm_wr32(device, 0x000180 + (i * 0x04), ~mask);
0040         nvkm_wr32(device, 0x000160 + (i * 0x04),  mask);
0041     }
0042 
0043     if (mask & 0x00000200)
0044         nvkm_wr32(device, 0xb81608, 0x6);
0045     else
0046         nvkm_wr32(device, 0xb81610, 0x6);
0047 }
0048 
0049 static void
0050 tu102_mc_intr_unarm(struct nvkm_mc *base)
0051 {
0052     struct tu102_mc *mc = tu102_mc(base);
0053     unsigned long flags;
0054 
0055     spin_lock_irqsave(&mc->lock, flags);
0056     mc->intr = false;
0057     tu102_mc_intr_update(mc);
0058     spin_unlock_irqrestore(&mc->lock, flags);
0059 }
0060 
0061 static void
0062 tu102_mc_intr_rearm(struct nvkm_mc *base)
0063 {
0064     struct tu102_mc *mc = tu102_mc(base);
0065     unsigned long flags;
0066 
0067     spin_lock_irqsave(&mc->lock, flags);
0068     mc->intr = true;
0069     tu102_mc_intr_update(mc);
0070     spin_unlock_irqrestore(&mc->lock, flags);
0071 }
0072 
0073 static void
0074 tu102_mc_intr_mask(struct nvkm_mc *base, u32 mask, u32 intr)
0075 {
0076     struct tu102_mc *mc = tu102_mc(base);
0077     unsigned long flags;
0078 
0079     spin_lock_irqsave(&mc->lock, flags);
0080     mc->mask = (mc->mask & ~mask) | intr;
0081     tu102_mc_intr_update(mc);
0082     spin_unlock_irqrestore(&mc->lock, flags);
0083 }
0084 
0085 static u32
0086 tu102_mc_intr_stat(struct nvkm_mc *mc)
0087 {
0088     struct nvkm_device *device = mc->subdev.device;
0089     u32 intr0 = nvkm_rd32(device, 0x000100);
0090     u32 intr1 = nvkm_rd32(device, 0x000104);
0091     u32 intr_top = nvkm_rd32(device, 0xb81600);
0092 
0093     /* Turing and above route the MMU fault interrupts via a different
0094      * interrupt tree with different control registers. For the moment remap
0095      * them back to the old PMC vector.
0096      */
0097     if (intr_top & 0x00000006)
0098         intr0 |= 0x00000200;
0099 
0100     return intr0 | intr1;
0101 }
0102 
0103 
0104 static const struct nvkm_mc_func
0105 tu102_mc = {
0106     .init = nv50_mc_init,
0107     .intr = gp100_mc_intr,
0108     .intr_unarm = tu102_mc_intr_unarm,
0109     .intr_rearm = tu102_mc_intr_rearm,
0110     .intr_mask = tu102_mc_intr_mask,
0111     .intr_stat = tu102_mc_intr_stat,
0112     .reset = gk104_mc_reset,
0113 };
0114 
0115 static int
0116 tu102_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
0117           enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
0118 {
0119     struct tu102_mc *mc;
0120 
0121     if (!(mc = kzalloc(sizeof(*mc), GFP_KERNEL)))
0122         return -ENOMEM;
0123     nvkm_mc_ctor(func, device, type, inst, &mc->base);
0124     *pmc = &mc->base;
0125 
0126     spin_lock_init(&mc->lock);
0127     mc->intr = false;
0128     mc->mask = 0x7fffffff;
0129     return 0;
0130 }
0131 
0132 int
0133 tu102_mc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
0134 {
0135     return tu102_mc_new_(&tu102_mc, device, type, inst, pmc);
0136 }