| .. | .. |
|---|
| 22 | 22 | #include "priv.h" |
|---|
| 23 | 23 | |
|---|
| 24 | 24 | #include <subdev/mc.h> |
|---|
| 25 | +#include <subdev/top.h> |
|---|
| 25 | 26 | |
|---|
| 26 | 27 | void |
|---|
| 27 | 28 | nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, |
|---|
| .. | .. |
|---|
| 118 | 119 | int |
|---|
| 119 | 120 | nvkm_falcon_reset(struct nvkm_falcon *falcon) |
|---|
| 120 | 121 | { |
|---|
| 121 | | - nvkm_falcon_disable(falcon); |
|---|
| 122 | | - return nvkm_falcon_enable(falcon); |
|---|
| 122 | + if (!falcon->func->reset) { |
|---|
| 123 | + nvkm_falcon_disable(falcon); |
|---|
| 124 | + return nvkm_falcon_enable(falcon); |
|---|
| 125 | + } |
|---|
| 126 | + |
|---|
| 127 | + return falcon->func->reset(falcon); |
|---|
| 123 | 128 | } |
|---|
| 124 | 129 | |
|---|
| 125 | 130 | int |
|---|
| .. | .. |
|---|
| 132 | 137 | nvkm_falcon_clear_interrupt(struct nvkm_falcon *falcon, u32 mask) |
|---|
| 133 | 138 | { |
|---|
| 134 | 139 | return falcon->func->clear_interrupt(falcon, mask); |
|---|
| 140 | +} |
|---|
| 141 | + |
|---|
| 142 | +static int |
|---|
| 143 | +nvkm_falcon_oneinit(struct nvkm_falcon *falcon) |
|---|
| 144 | +{ |
|---|
| 145 | + const struct nvkm_falcon_func *func = falcon->func; |
|---|
| 146 | + const struct nvkm_subdev *subdev = falcon->owner; |
|---|
| 147 | + u32 reg; |
|---|
| 148 | + |
|---|
| 149 | + if (!falcon->addr) { |
|---|
| 150 | + falcon->addr = nvkm_top_addr(subdev->device, subdev->index); |
|---|
| 151 | + if (WARN_ON(!falcon->addr)) |
|---|
| 152 | + return -ENODEV; |
|---|
| 153 | + } |
|---|
| 154 | + |
|---|
| 155 | + reg = nvkm_falcon_rd32(falcon, 0x12c); |
|---|
| 156 | + falcon->version = reg & 0xf; |
|---|
| 157 | + falcon->secret = (reg >> 4) & 0x3; |
|---|
| 158 | + falcon->code.ports = (reg >> 8) & 0xf; |
|---|
| 159 | + falcon->data.ports = (reg >> 12) & 0xf; |
|---|
| 160 | + |
|---|
| 161 | + reg = nvkm_falcon_rd32(falcon, 0x108); |
|---|
| 162 | + falcon->code.limit = (reg & 0x1ff) << 8; |
|---|
| 163 | + falcon->data.limit = (reg & 0x3fe00) >> 1; |
|---|
| 164 | + |
|---|
| 165 | + if (func->debug) { |
|---|
| 166 | + u32 val = nvkm_falcon_rd32(falcon, func->debug); |
|---|
| 167 | + falcon->debug = (val >> 20) & 0x1; |
|---|
| 168 | + } |
|---|
| 169 | + |
|---|
| 170 | + return 0; |
|---|
| 135 | 171 | } |
|---|
| 136 | 172 | |
|---|
| 137 | 173 | void |
|---|
| .. | .. |
|---|
| 151 | 187 | int |
|---|
| 152 | 188 | nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) |
|---|
| 153 | 189 | { |
|---|
| 190 | + int ret = 0; |
|---|
| 191 | + |
|---|
| 154 | 192 | mutex_lock(&falcon->mutex); |
|---|
| 155 | 193 | if (falcon->user) { |
|---|
| 156 | 194 | nvkm_error(user, "%s falcon already acquired by %s!\n", |
|---|
| .. | .. |
|---|
| 160 | 198 | } |
|---|
| 161 | 199 | |
|---|
| 162 | 200 | nvkm_debug(user, "acquired %s falcon\n", falcon->name); |
|---|
| 201 | + if (!falcon->oneinit) |
|---|
| 202 | + ret = nvkm_falcon_oneinit(falcon); |
|---|
| 163 | 203 | falcon->user = user; |
|---|
| 164 | 204 | mutex_unlock(&falcon->mutex); |
|---|
| 165 | | - return 0; |
|---|
| 205 | + return ret; |
|---|
| 166 | 206 | } |
|---|
| 167 | 207 | |
|---|
| 168 | 208 | void |
|---|
| 209 | +nvkm_falcon_dtor(struct nvkm_falcon *falcon) |
|---|
| 210 | +{ |
|---|
| 211 | +} |
|---|
| 212 | + |
|---|
| 213 | +int |
|---|
| 169 | 214 | nvkm_falcon_ctor(const struct nvkm_falcon_func *func, |
|---|
| 170 | 215 | struct nvkm_subdev *subdev, const char *name, u32 addr, |
|---|
| 171 | 216 | struct nvkm_falcon *falcon) |
|---|
| 172 | 217 | { |
|---|
| 173 | | - u32 debug_reg; |
|---|
| 174 | | - u32 reg; |
|---|
| 175 | | - |
|---|
| 176 | 218 | falcon->func = func; |
|---|
| 177 | 219 | falcon->owner = subdev; |
|---|
| 178 | 220 | falcon->name = name; |
|---|
| 179 | 221 | falcon->addr = addr; |
|---|
| 180 | 222 | mutex_init(&falcon->mutex); |
|---|
| 181 | 223 | mutex_init(&falcon->dmem_mutex); |
|---|
| 182 | | - |
|---|
| 183 | | - reg = nvkm_falcon_rd32(falcon, 0x12c); |
|---|
| 184 | | - falcon->version = reg & 0xf; |
|---|
| 185 | | - falcon->secret = (reg >> 4) & 0x3; |
|---|
| 186 | | - falcon->code.ports = (reg >> 8) & 0xf; |
|---|
| 187 | | - falcon->data.ports = (reg >> 12) & 0xf; |
|---|
| 188 | | - |
|---|
| 189 | | - reg = nvkm_falcon_rd32(falcon, 0x108); |
|---|
| 190 | | - falcon->code.limit = (reg & 0x1ff) << 8; |
|---|
| 191 | | - falcon->data.limit = (reg & 0x3fe00) >> 1; |
|---|
| 192 | | - |
|---|
| 193 | | - switch (subdev->index) { |
|---|
| 194 | | - case NVKM_ENGINE_GR: |
|---|
| 195 | | - debug_reg = 0x0; |
|---|
| 196 | | - break; |
|---|
| 197 | | - case NVKM_SUBDEV_PMU: |
|---|
| 198 | | - debug_reg = 0xc08; |
|---|
| 199 | | - break; |
|---|
| 200 | | - case NVKM_ENGINE_NVDEC: |
|---|
| 201 | | - debug_reg = 0xd00; |
|---|
| 202 | | - break; |
|---|
| 203 | | - case NVKM_ENGINE_SEC2: |
|---|
| 204 | | - debug_reg = 0x408; |
|---|
| 205 | | - falcon->has_emem = true; |
|---|
| 206 | | - break; |
|---|
| 207 | | - default: |
|---|
| 208 | | - nvkm_warn(subdev, "unsupported falcon %s!\n", |
|---|
| 209 | | - nvkm_subdev_name[subdev->index]); |
|---|
| 210 | | - debug_reg = 0; |
|---|
| 211 | | - break; |
|---|
| 212 | | - } |
|---|
| 213 | | - |
|---|
| 214 | | - if (debug_reg) { |
|---|
| 215 | | - u32 val = nvkm_falcon_rd32(falcon, debug_reg); |
|---|
| 216 | | - falcon->debug = (val >> 20) & 0x1; |
|---|
| 217 | | - } |
|---|
| 224 | + return 0; |
|---|
| 218 | 225 | } |
|---|
| 219 | 226 | |
|---|
| 220 | 227 | void |
|---|
| 221 | 228 | nvkm_falcon_del(struct nvkm_falcon **pfalcon) |
|---|
| 222 | 229 | { |
|---|
| 223 | 230 | if (*pfalcon) { |
|---|
| 231 | + nvkm_falcon_dtor(*pfalcon); |
|---|
| 224 | 232 | kfree(*pfalcon); |
|---|
| 225 | 233 | *pfalcon = NULL; |
|---|
| 226 | 234 | } |
|---|