0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "priv.h"
0023
0024 #include <subdev/mc.h>
0025 #include <subdev/top.h>
0026
0027 void
0028 nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start,
0029 u32 size, u16 tag, u8 port, bool secure)
0030 {
0031 if (secure && !falcon->secret) {
0032 nvkm_warn(falcon->user,
0033 "writing with secure tag on a non-secure falcon!\n");
0034 return;
0035 }
0036
0037 falcon->func->load_imem(falcon, data, start, size, tag, port,
0038 secure);
0039 }
0040
0041 void
0042 nvkm_falcon_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start,
0043 u32 size, u8 port)
0044 {
0045 mutex_lock(&falcon->dmem_mutex);
0046
0047 falcon->func->load_dmem(falcon, data, start, size, port);
0048
0049 mutex_unlock(&falcon->dmem_mutex);
0050 }
0051
0052 void
0053 nvkm_falcon_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port,
0054 void *data)
0055 {
0056 mutex_lock(&falcon->dmem_mutex);
0057
0058 falcon->func->read_dmem(falcon, start, size, port, data);
0059
0060 mutex_unlock(&falcon->dmem_mutex);
0061 }
0062
0063 void
0064 nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *inst)
0065 {
0066 if (!falcon->func->bind_context) {
0067 nvkm_error(falcon->user,
0068 "Context binding not supported on this falcon!\n");
0069 return;
0070 }
0071
0072 falcon->func->bind_context(falcon, inst);
0073 }
0074
0075 void
0076 nvkm_falcon_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr)
0077 {
0078 falcon->func->set_start_addr(falcon, start_addr);
0079 }
0080
0081 void
0082 nvkm_falcon_start(struct nvkm_falcon *falcon)
0083 {
0084 falcon->func->start(falcon);
0085 }
0086
0087 int
0088 nvkm_falcon_enable(struct nvkm_falcon *falcon)
0089 {
0090 struct nvkm_device *device = falcon->owner->device;
0091 int ret;
0092
0093 nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst);
0094 ret = falcon->func->enable(falcon);
0095 if (ret) {
0096 nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
0097 return ret;
0098 }
0099
0100 return 0;
0101 }
0102
0103 void
0104 nvkm_falcon_disable(struct nvkm_falcon *falcon)
0105 {
0106 struct nvkm_device *device = falcon->owner->device;
0107
0108
0109 if (!nvkm_mc_enabled(device, falcon->owner->type, falcon->owner->inst))
0110 return;
0111
0112 falcon->func->disable(falcon);
0113
0114 nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
0115 }
0116
0117 int
0118 nvkm_falcon_reset(struct nvkm_falcon *falcon)
0119 {
0120 if (!falcon->func->reset) {
0121 nvkm_falcon_disable(falcon);
0122 return nvkm_falcon_enable(falcon);
0123 }
0124
0125 return falcon->func->reset(falcon);
0126 }
0127
0128 int
0129 nvkm_falcon_wait_for_halt(struct nvkm_falcon *falcon, u32 ms)
0130 {
0131 return falcon->func->wait_for_halt(falcon, ms);
0132 }
0133
0134 int
0135 nvkm_falcon_clear_interrupt(struct nvkm_falcon *falcon, u32 mask)
0136 {
0137 return falcon->func->clear_interrupt(falcon, mask);
0138 }
0139
0140 static int
0141 nvkm_falcon_oneinit(struct nvkm_falcon *falcon)
0142 {
0143 const struct nvkm_falcon_func *func = falcon->func;
0144 const struct nvkm_subdev *subdev = falcon->owner;
0145 u32 reg;
0146
0147 if (!falcon->addr) {
0148 falcon->addr = nvkm_top_addr(subdev->device, subdev->type, subdev->inst);
0149 if (WARN_ON(!falcon->addr))
0150 return -ENODEV;
0151 }
0152
0153 reg = nvkm_falcon_rd32(falcon, 0x12c);
0154 falcon->version = reg & 0xf;
0155 falcon->secret = (reg >> 4) & 0x3;
0156 falcon->code.ports = (reg >> 8) & 0xf;
0157 falcon->data.ports = (reg >> 12) & 0xf;
0158
0159 reg = nvkm_falcon_rd32(falcon, 0x108);
0160 falcon->code.limit = (reg & 0x1ff) << 8;
0161 falcon->data.limit = (reg & 0x3fe00) >> 1;
0162
0163 if (func->debug) {
0164 u32 val = nvkm_falcon_rd32(falcon, func->debug);
0165 falcon->debug = (val >> 20) & 0x1;
0166 }
0167
0168 return 0;
0169 }
0170
0171 void
0172 nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
0173 {
0174 if (unlikely(!falcon))
0175 return;
0176
0177 mutex_lock(&falcon->mutex);
0178 if (falcon->user == user) {
0179 nvkm_debug(falcon->user, "released %s falcon\n", falcon->name);
0180 falcon->user = NULL;
0181 }
0182 mutex_unlock(&falcon->mutex);
0183 }
0184
0185 int
0186 nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
0187 {
0188 int ret = 0;
0189
0190 mutex_lock(&falcon->mutex);
0191 if (falcon->user) {
0192 nvkm_error(user, "%s falcon already acquired by %s!\n",
0193 falcon->name, falcon->user->name);
0194 mutex_unlock(&falcon->mutex);
0195 return -EBUSY;
0196 }
0197
0198 nvkm_debug(user, "acquired %s falcon\n", falcon->name);
0199 if (!falcon->oneinit)
0200 ret = nvkm_falcon_oneinit(falcon);
0201 falcon->user = user;
0202 mutex_unlock(&falcon->mutex);
0203 return ret;
0204 }
0205
0206 void
0207 nvkm_falcon_dtor(struct nvkm_falcon *falcon)
0208 {
0209 }
0210
0211 int
0212 nvkm_falcon_ctor(const struct nvkm_falcon_func *func,
0213 struct nvkm_subdev *subdev, const char *name, u32 addr,
0214 struct nvkm_falcon *falcon)
0215 {
0216 falcon->func = func;
0217 falcon->owner = subdev;
0218 falcon->name = name;
0219 falcon->addr = addr;
0220 mutex_init(&falcon->mutex);
0221 mutex_init(&falcon->dmem_mutex);
0222 return 0;
0223 }