1/* $NetBSD: nouveau_engine_copy_nva3.c,v 1.2 2014/08/23 08:03:33 riastradh Exp $ */
2
3/*
4 * Copyright 2012 Red Hat Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Ben Skeggs
25 */
26
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: nouveau_engine_copy_nva3.c,v 1.2 2014/08/23 08:03:33 riastradh Exp $");
29
30#include <engine/falcon.h>
31#include <engine/fifo.h>
32#include <engine/copy.h>
33
34#include <subdev/fb.h>
35#include <subdev/vm.h>
36
37#include <core/client.h>
38#include <core/class.h>
39#include <core/enum.h>
40
41
42#include "fuc/nva3.fuc.h"
43
44struct nva3_copy_priv {
45 struct nouveau_falcon base;
46};
47
48/*******************************************************************************
49 * Copy object classes
50 ******************************************************************************/
51
52static struct nouveau_oclass
53nva3_copy_sclass[] = {
54 { 0x85b5, &nouveau_object_ofuncs },
55 {}
56};
57
58/*******************************************************************************
59 * PCOPY context
60 ******************************************************************************/
61
62static struct nouveau_oclass
63nva3_copy_cclass = {
64 .handle = NV_ENGCTX(COPY0, 0xa3),
65 .ofuncs = &(struct nouveau_ofuncs) {
66 .ctor = _nouveau_falcon_context_ctor,
67 .dtor = _nouveau_falcon_context_dtor,
68 .init = _nouveau_falcon_context_init,
69 .fini = _nouveau_falcon_context_fini,
70 .rd32 = _nouveau_falcon_context_rd32,
71 .wr32 = _nouveau_falcon_context_wr32,
72
73 },
74};
75
76/*******************************************************************************
77 * PCOPY engine/subdev functions
78 ******************************************************************************/
79
80static const struct nouveau_enum nva3_copy_isr_error_name[] = {
81 { 0x0001, "ILLEGAL_MTHD" },
82 { 0x0002, "INVALID_ENUM" },
83 { 0x0003, "INVALID_BITFIELD" },
84 {}
85};
86
87void
88nva3_copy_intr(struct nouveau_subdev *subdev)
89{
90 struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
91 struct nouveau_engine *engine = nv_engine(subdev);
92 struct nouveau_falcon *falcon = (void *)subdev;
93 struct nouveau_object *engctx;
94 u32 dispatch = nv_ro32(falcon, 0x01c);
95 u32 stat = nv_ro32(falcon, 0x008) & dispatch & ~(dispatch >> 16);
96 u64 inst = nv_ro32(falcon, 0x050) & 0x3fffffff;
97 u32 ssta = nv_ro32(falcon, 0x040) & 0x0000ffff;
98 u32 addr = nv_ro32(falcon, 0x040) >> 16;
99 u32 mthd = (addr & 0x07ff) << 2;
100 u32 subc = (addr & 0x3800) >> 11;
101 u32 data = nv_ro32(falcon, 0x044);
102 int chid;
103
104 engctx = nouveau_engctx_get(engine, inst);
105 chid = pfifo->chid(pfifo, engctx);
106
107 if (stat & 0x00000040) {
108 nv_error(falcon, "DISPATCH_ERROR [");
109 nouveau_enum_print(nva3_copy_isr_error_name, ssta);
110 pr_cont("] ch %d [0x%010"PRIx64" %s] subc %d mthd 0x%04x data 0x%08x\n",
111 chid, inst << 12, nouveau_client_name(engctx), subc,
112 mthd, data);
113 nv_wo32(falcon, 0x004, 0x00000040);
114 stat &= ~0x00000040;
115 }
116
117 if (stat) {
118 nv_error(falcon, "unhandled intr 0x%08x\n", stat);
119 nv_wo32(falcon, 0x004, stat);
120 }
121
122 nouveau_engctx_put(engctx);
123}
124
125static int
126nva3_copy_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
127 struct nouveau_oclass *oclass, void *data, u32 size,
128 struct nouveau_object **pobject)
129{
130 bool enable = (nv_device(parent)->chipset != 0xaf);
131 struct nva3_copy_priv *priv;
132 int ret;
133
134 ret = nouveau_falcon_create(parent, engine, oclass, 0x104000, enable,
135 "PCE0", "copy0", &priv);
136 *pobject = nv_object(priv);
137 if (ret)
138 return ret;
139
140 nv_subdev(priv)->unit = 0x00802000;
141 nv_subdev(priv)->intr = nva3_copy_intr;
142 nv_engine(priv)->cclass = &nva3_copy_cclass;
143 nv_engine(priv)->sclass = nva3_copy_sclass;
144 nv_falcon(priv)->code.data = nva3_pcopy_code;
145 nv_falcon(priv)->code.size = sizeof(nva3_pcopy_code);
146 nv_falcon(priv)->data.data = nva3_pcopy_data;
147 nv_falcon(priv)->data.size = sizeof(nva3_pcopy_data);
148 return 0;
149}
150
151struct nouveau_oclass
152nva3_copy_oclass = {
153 .handle = NV_ENGINE(COPY0, 0xa3),
154 .ofuncs = &(struct nouveau_ofuncs) {
155 .ctor = nva3_copy_ctor,
156 .dtor = _nouveau_falcon_dtor,
157 .init = _nouveau_falcon_init,
158 .fini = _nouveau_falcon_fini,
159 .rd32 = _nouveau_falcon_rd32,
160 .wr32 = _nouveau_falcon_wr32,
161 },
162};
163