0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "priv.h"
0025
0026 #include <core/option.h>
0027 #include <subdev/top.h>
0028
0029 void
0030 nvkm_mc_unk260(struct nvkm_device *device, u32 data)
0031 {
0032 struct nvkm_mc *mc = device->mc;
0033 if (likely(mc) && mc->func->unk260)
0034 mc->func->unk260(mc, data);
0035 }
0036
0037 void
0038 nvkm_mc_intr_mask(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, bool en)
0039 {
0040 struct nvkm_mc *mc = device->mc;
0041 const struct nvkm_mc_map *map;
0042 if (likely(mc) && mc->func->intr_mask) {
0043 u32 mask = nvkm_top_intr_mask(device, type, inst);
0044 for (map = mc->func->intr; !mask && map->stat; map++) {
0045 if (map->type == type && map->inst == inst)
0046 mask = map->stat;
0047 }
0048 mc->func->intr_mask(mc, mask, en ? mask : 0);
0049 }
0050 }
0051
0052 void
0053 nvkm_mc_intr_unarm(struct nvkm_device *device)
0054 {
0055 struct nvkm_mc *mc = device->mc;
0056 if (likely(mc))
0057 mc->func->intr_unarm(mc);
0058 }
0059
0060 void
0061 nvkm_mc_intr_rearm(struct nvkm_device *device)
0062 {
0063 struct nvkm_mc *mc = device->mc;
0064 if (likely(mc))
0065 mc->func->intr_rearm(mc);
0066 }
0067
0068 static u32
0069 nvkm_mc_intr_stat(struct nvkm_mc *mc)
0070 {
0071 u32 intr = mc->func->intr_stat(mc);
0072 if (WARN_ON_ONCE(intr == 0xffffffff))
0073 intr = 0;
0074 return intr;
0075 }
0076
0077 void
0078 nvkm_mc_intr(struct nvkm_device *device, bool *handled)
0079 {
0080 struct nvkm_mc *mc = device->mc;
0081 struct nvkm_top *top = device->top;
0082 struct nvkm_top_device *tdev;
0083 struct nvkm_subdev *subdev;
0084 const struct nvkm_mc_map *map;
0085 u32 stat, intr;
0086
0087 if (unlikely(!mc))
0088 return;
0089
0090 stat = intr = nvkm_mc_intr_stat(mc);
0091
0092 if (top) {
0093 list_for_each_entry(tdev, &top->device, head) {
0094 if (tdev->intr >= 0 && (stat & BIT(tdev->intr))) {
0095 subdev = nvkm_device_subdev(device, tdev->type, tdev->inst);
0096 if (subdev) {
0097 nvkm_subdev_intr(subdev);
0098 stat &= ~BIT(tdev->intr);
0099 if (!stat)
0100 break;
0101 }
0102 }
0103 }
0104 }
0105
0106 for (map = mc->func->intr; map->stat; map++) {
0107 if (intr & map->stat) {
0108 subdev = nvkm_device_subdev(device, map->type, map->inst);
0109 if (subdev)
0110 nvkm_subdev_intr(subdev);
0111 stat &= ~map->stat;
0112 }
0113 }
0114
0115 if (stat)
0116 nvkm_error(&mc->subdev, "intr %08x\n", stat);
0117 *handled = intr != 0;
0118 }
0119
0120 static u32
0121 nvkm_mc_reset_mask(struct nvkm_device *device, bool isauto, enum nvkm_subdev_type type, int inst)
0122 {
0123 struct nvkm_mc *mc = device->mc;
0124 const struct nvkm_mc_map *map;
0125 u64 pmc_enable = 0;
0126 if (likely(mc)) {
0127 if (!(pmc_enable = nvkm_top_reset(device, type, inst))) {
0128 for (map = mc->func->reset; map && map->stat; map++) {
0129 if (!isauto || !map->noauto) {
0130 if (map->type == type && map->inst == inst) {
0131 pmc_enable = map->stat;
0132 break;
0133 }
0134 }
0135 }
0136 }
0137 }
0138 return pmc_enable;
0139 }
0140
0141 void
0142 nvkm_mc_reset(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
0143 {
0144 u64 pmc_enable = nvkm_mc_reset_mask(device, true, type, inst);
0145 if (pmc_enable) {
0146 nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
0147 nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
0148 nvkm_rd32(device, 0x000200);
0149 }
0150 }
0151
0152 void
0153 nvkm_mc_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
0154 {
0155 u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
0156 if (pmc_enable)
0157 nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
0158 }
0159
0160 void
0161 nvkm_mc_enable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
0162 {
0163 u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
0164 if (pmc_enable) {
0165 nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
0166 nvkm_rd32(device, 0x000200);
0167 }
0168 }
0169
0170 bool
0171 nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
0172 {
0173 u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
0174
0175 return (pmc_enable != 0) &&
0176 ((nvkm_rd32(device, 0x000200) & pmc_enable) == pmc_enable);
0177 }
0178
0179
0180 static int
0181 nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
0182 {
0183 nvkm_mc_intr_unarm(subdev->device);
0184 return 0;
0185 }
0186
0187 static int
0188 nvkm_mc_init(struct nvkm_subdev *subdev)
0189 {
0190 struct nvkm_mc *mc = nvkm_mc(subdev);
0191 if (mc->func->init)
0192 mc->func->init(mc);
0193 nvkm_mc_intr_rearm(subdev->device);
0194 return 0;
0195 }
0196
0197 static void *
0198 nvkm_mc_dtor(struct nvkm_subdev *subdev)
0199 {
0200 return nvkm_mc(subdev);
0201 }
0202
0203 static const struct nvkm_subdev_func
0204 nvkm_mc = {
0205 .dtor = nvkm_mc_dtor,
0206 .init = nvkm_mc_init,
0207 .fini = nvkm_mc_fini,
0208 };
0209
0210 void
0211 nvkm_mc_ctor(const struct nvkm_mc_func *func, struct nvkm_device *device,
0212 enum nvkm_subdev_type type, int inst, struct nvkm_mc *mc)
0213 {
0214 nvkm_subdev_ctor(&nvkm_mc, device, type, inst, &mc->subdev);
0215 mc->func = func;
0216 }
0217
0218 int
0219 nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
0220 enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
0221 {
0222 struct nvkm_mc *mc;
0223 if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL)))
0224 return -ENOMEM;
0225 nvkm_mc_ctor(func, device, type, inst, *pmc);
0226 return 0;
0227 }