xref: /linux/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
15f76f294SBen Skeggs /*
25f76f294SBen Skeggs  * Copyright 2016 Red Hat Inc.
35f76f294SBen Skeggs  *
45f76f294SBen Skeggs  * Permission is hereby granted, free of charge, to any person obtaining a
55f76f294SBen Skeggs  * copy of this software and associated documentation files (the "Software"),
65f76f294SBen Skeggs  * to deal in the Software without restriction, including without limitation
75f76f294SBen Skeggs  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85f76f294SBen Skeggs  * and/or sell copies of the Software, and to permit persons to whom the
95f76f294SBen Skeggs  * Software is furnished to do so, subject to the following conditions:
105f76f294SBen Skeggs  *
115f76f294SBen Skeggs  * The above copyright notice and this permission notice shall be included in
125f76f294SBen Skeggs  * all copies or substantial portions of the Software.
135f76f294SBen Skeggs  *
145f76f294SBen Skeggs  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155f76f294SBen Skeggs  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165f76f294SBen Skeggs  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175f76f294SBen Skeggs  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
185f76f294SBen Skeggs  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
195f76f294SBen Skeggs  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
205f76f294SBen Skeggs  * OTHER DEALINGS IN THE SOFTWARE.
215f76f294SBen Skeggs  *
225f76f294SBen Skeggs  * Authors: Ben Skeggs <bskeggs@redhat.com>
235f76f294SBen Skeggs  */
245f76f294SBen Skeggs #include "priv.h"
255f76f294SBen Skeggs 
265f76f294SBen Skeggs struct nvkm_top_device *
nvkm_top_device_new(struct nvkm_top * top)275f76f294SBen Skeggs nvkm_top_device_new(struct nvkm_top *top)
285f76f294SBen Skeggs {
295f76f294SBen Skeggs 	struct nvkm_top_device *info = kmalloc(sizeof(*info), GFP_KERNEL);
305f76f294SBen Skeggs 	if (info) {
315e0d3dbcSBen Skeggs 		info->type = NVKM_SUBDEV_NR;
325e0d3dbcSBen Skeggs 		info->inst = -1;
335f76f294SBen Skeggs 		info->addr = 0;
345f76f294SBen Skeggs 		info->fault = -1;
355f76f294SBen Skeggs 		info->engine = -1;
365f76f294SBen Skeggs 		info->runlist = -1;
375f76f294SBen Skeggs 		info->reset = -1;
385f76f294SBen Skeggs 		info->intr = -1;
395f76f294SBen Skeggs 		list_add_tail(&info->head, &top->device);
405f76f294SBen Skeggs 	}
415f76f294SBen Skeggs 	return info;
425f76f294SBen Skeggs }
435f76f294SBen Skeggs 
445f76f294SBen Skeggs u32
nvkm_top_addr(struct nvkm_device * device,enum nvkm_subdev_type type,int inst)45b7da823aSBen Skeggs nvkm_top_addr(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
46eec9ffe4SBen Skeggs {
47eec9ffe4SBen Skeggs 	struct nvkm_top *top = device->top;
48eec9ffe4SBen Skeggs 	struct nvkm_top_device *info;
49eec9ffe4SBen Skeggs 
50eec9ffe4SBen Skeggs 	if (top) {
51eec9ffe4SBen Skeggs 		list_for_each_entry(info, &top->device, head) {
52b7da823aSBen Skeggs 			if (info->type == type && info->inst == inst)
53eec9ffe4SBen Skeggs 				return info->addr;
54eec9ffe4SBen Skeggs 		}
55eec9ffe4SBen Skeggs 	}
56eec9ffe4SBen Skeggs 
57eec9ffe4SBen Skeggs 	return 0;
58eec9ffe4SBen Skeggs }
59eec9ffe4SBen Skeggs 
60eec9ffe4SBen Skeggs u32
nvkm_top_reset(struct nvkm_device * device,enum nvkm_subdev_type type,int inst)616997ea13SBen Skeggs nvkm_top_reset(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
625f76f294SBen Skeggs {
63952eb819SBen Skeggs 	struct nvkm_top *top = device->top;
645f76f294SBen Skeggs 	struct nvkm_top_device *info;
655f76f294SBen Skeggs 
665f76f294SBen Skeggs 	if (top) {
675f76f294SBen Skeggs 		list_for_each_entry(info, &top->device, head) {
686997ea13SBen Skeggs 			if (info->type == type && info->inst == inst && info->reset >= 0)
695f76f294SBen Skeggs 				return BIT(info->reset);
705f76f294SBen Skeggs 		}
715f76f294SBen Skeggs 	}
725f76f294SBen Skeggs 
735f76f294SBen Skeggs 	return 0;
745f76f294SBen Skeggs }
755f76f294SBen Skeggs 
765f76f294SBen Skeggs u32
nvkm_top_intr_mask(struct nvkm_device * device,enum nvkm_subdev_type type,int inst)77a35047baSBen Skeggs nvkm_top_intr_mask(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
783560e170SBen Skeggs {
793560e170SBen Skeggs 	struct nvkm_top *top = device->top;
803560e170SBen Skeggs 	struct nvkm_top_device *info;
813560e170SBen Skeggs 
823560e170SBen Skeggs 	if (top) {
833560e170SBen Skeggs 		list_for_each_entry(info, &top->device, head) {
84a35047baSBen Skeggs 			if (info->type == type && info->inst == inst && info->intr >= 0)
853560e170SBen Skeggs 				return BIT(info->intr);
863560e170SBen Skeggs 		}
873560e170SBen Skeggs 	}
883560e170SBen Skeggs 
893560e170SBen Skeggs 	return 0;
903560e170SBen Skeggs }
913560e170SBen Skeggs 
9213416077SBen Skeggs int
nvkm_top_fault_id(struct nvkm_device * device,enum nvkm_subdev_type type,int inst)93088bfe43SBen Skeggs nvkm_top_fault_id(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
9413416077SBen Skeggs {
9513416077SBen Skeggs 	struct nvkm_top *top = device->top;
9613416077SBen Skeggs 	struct nvkm_top_device *info;
9713416077SBen Skeggs 
9813416077SBen Skeggs 	list_for_each_entry(info, &top->device, head) {
99088bfe43SBen Skeggs 		if (info->type == type && info->inst == inst && info->fault >= 0)
10013416077SBen Skeggs 			return info->fault;
10113416077SBen Skeggs 	}
10213416077SBen Skeggs 
10313416077SBen Skeggs 	return -ENOENT;
10413416077SBen Skeggs }
10513416077SBen Skeggs 
106ba083ec7SBen Skeggs struct nvkm_subdev *
nvkm_top_fault(struct nvkm_device * device,int fault)107952eb819SBen Skeggs nvkm_top_fault(struct nvkm_device *device, int fault)
1085f76f294SBen Skeggs {
109952eb819SBen Skeggs 	struct nvkm_top *top = device->top;
1105f76f294SBen Skeggs 	struct nvkm_top_device *info;
1115f76f294SBen Skeggs 
1125f76f294SBen Skeggs 	list_for_each_entry(info, &top->device, head) {
1135f76f294SBen Skeggs 		if (info->fault == fault)
114ba083ec7SBen Skeggs 			return nvkm_device_subdev(device, info->type, info->inst);
1155f76f294SBen Skeggs 	}
1165f76f294SBen Skeggs 
117ba083ec7SBen Skeggs 	return NULL;
1185f76f294SBen Skeggs }
1195f76f294SBen Skeggs 
120*eec3f6dfSBen Skeggs int
nvkm_top_parse(struct nvkm_device * device)121*eec3f6dfSBen Skeggs nvkm_top_parse(struct nvkm_device *device)
1225f76f294SBen Skeggs {
123*eec3f6dfSBen Skeggs 	struct nvkm_top *top = device->top;
124*eec3f6dfSBen Skeggs 
125*eec3f6dfSBen Skeggs 	if (!top || !list_empty(&top->device))
126*eec3f6dfSBen Skeggs 		return 0;
127*eec3f6dfSBen Skeggs 
128*eec3f6dfSBen Skeggs 	return top->func->parse(top);
1295f76f294SBen Skeggs }
1305f76f294SBen Skeggs 
1315f76f294SBen Skeggs static void *
nvkm_top_dtor(struct nvkm_subdev * subdev)1325f76f294SBen Skeggs nvkm_top_dtor(struct nvkm_subdev *subdev)
1335f76f294SBen Skeggs {
1345f76f294SBen Skeggs 	struct nvkm_top *top = nvkm_top(subdev);
1355f76f294SBen Skeggs 	struct nvkm_top_device *info, *temp;
1365f76f294SBen Skeggs 
1375f76f294SBen Skeggs 	list_for_each_entry_safe(info, temp, &top->device, head) {
1385f76f294SBen Skeggs 		list_del(&info->head);
1395f76f294SBen Skeggs 		kfree(info);
1405f76f294SBen Skeggs 	}
1415f76f294SBen Skeggs 
1425f76f294SBen Skeggs 	return top;
1435f76f294SBen Skeggs }
1445f76f294SBen Skeggs 
1455f76f294SBen Skeggs static const struct nvkm_subdev_func
1465f76f294SBen Skeggs nvkm_top = {
1475f76f294SBen Skeggs 	.dtor = nvkm_top_dtor,
1485f76f294SBen Skeggs };
1495f76f294SBen Skeggs 
1505f76f294SBen Skeggs int
nvkm_top_new_(const struct nvkm_top_func * func,struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_top ** ptop)1515f76f294SBen Skeggs nvkm_top_new_(const struct nvkm_top_func *func, struct nvkm_device *device,
152601c2a06SBen Skeggs 	      enum nvkm_subdev_type type, int inst, struct nvkm_top **ptop)
1535f76f294SBen Skeggs {
1545f76f294SBen Skeggs 	struct nvkm_top *top;
1555f76f294SBen Skeggs 	if (!(top = *ptop = kzalloc(sizeof(*top), GFP_KERNEL)))
1565f76f294SBen Skeggs 		return -ENOMEM;
157601c2a06SBen Skeggs 	nvkm_subdev_ctor(&nvkm_top, device, type, inst, &top->subdev);
1585f76f294SBen Skeggs 	top->func = func;
1595f76f294SBen Skeggs 	INIT_LIST_HEAD(&top->device);
1605f76f294SBen Skeggs 	return 0;
1615f76f294SBen Skeggs }
162