e7f6bb6e267cf6141a52349c13d5157aac386ba0
[linux-2.6-microblaze.git] / drivers / gpu / drm / nouveau / core / engine / crypt / nv98.c
1 /*
2  * Copyright 2012 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  */
24
25 #include <core/os.h>
26 #include <core/enum.h>
27 #include <core/class.h>
28 #include <core/engctx.h>
29 #include <core/falcon.h>
30
31 #include <subdev/timer.h>
32 #include <subdev/fb.h>
33
34 #include <engine/fifo.h>
35 #include <engine/crypt.h>
36
37 #include "fuc/nv98.fuc.h"
38
39 struct nv98_crypt_priv {
40         struct nouveau_falcon base;
41 };
42
43 struct nv98_crypt_chan {
44         struct nouveau_falcon_chan base;
45 };
46
47 /*******************************************************************************
48  * Crypt object classes
49  ******************************************************************************/
50
51 static struct nouveau_oclass
52 nv98_crypt_sclass[] = {
53         { 0x88b4, &nouveau_object_ofuncs },
54         {},
55 };
56
57 /*******************************************************************************
58  * PCRYPT context
59  ******************************************************************************/
60
61 static int
62 nv98_crypt_context_ctor(struct nouveau_object *parent,
63                         struct nouveau_object *engine,
64                         struct nouveau_oclass *oclass, void *data, u32 size,
65                         struct nouveau_object **pobject)
66 {
67         struct nv98_crypt_chan *priv;
68         int ret;
69
70         ret = nouveau_falcon_context_create(parent, engine, oclass, NULL, 256,
71                                             256, NVOBJ_FLAG_ZERO_ALLOC, &priv);
72         *pobject = nv_object(priv);
73         if (ret)
74                 return ret;
75
76         return 0;
77 }
78
79 static struct nouveau_oclass
80 nv98_crypt_cclass = {
81         .handle = NV_ENGCTX(CRYPT, 0x98),
82         .ofuncs = &(struct nouveau_ofuncs) {
83                 .ctor = nv98_crypt_context_ctor,
84                 .dtor = _nouveau_falcon_context_dtor,
85                 .init = _nouveau_falcon_context_init,
86                 .fini = _nouveau_falcon_context_fini,
87                 .rd32 = _nouveau_falcon_context_rd32,
88                 .wr32 = _nouveau_falcon_context_wr32,
89         },
90 };
91
92 /*******************************************************************************
93  * PCRYPT engine/subdev functions
94  ******************************************************************************/
95
96 static const struct nouveau_enum nv98_crypt_isr_error_name[] = {
97         { 0x0000, "ILLEGAL_MTHD" },
98         { 0x0001, "INVALID_BITFIELD" },
99         { 0x0002, "INVALID_ENUM" },
100         { 0x0003, "QUERY" },
101         {}
102 };
103
104 static void
105 nv98_crypt_intr(struct nouveau_subdev *subdev)
106 {
107         struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
108         struct nouveau_engine *engine = nv_engine(subdev);
109         struct nouveau_object *engctx;
110         struct nv98_crypt_priv *priv = (void *)subdev;
111         u32 disp = nv_rd32(priv, 0x08701c);
112         u32 stat = nv_rd32(priv, 0x087008) & disp & ~(disp >> 16);
113         u32 inst = nv_rd32(priv, 0x087050) & 0x3fffffff;
114         u32 ssta = nv_rd32(priv, 0x087040) & 0x0000ffff;
115         u32 addr = nv_rd32(priv, 0x087040) >> 16;
116         u32 mthd = (addr & 0x07ff) << 2;
117         u32 subc = (addr & 0x3800) >> 11;
118         u32 data = nv_rd32(priv, 0x087044);
119         int chid;
120
121         engctx = nouveau_engctx_get(engine, inst);
122         chid   = pfifo->chid(pfifo, engctx);
123
124         if (stat & 0x00000040) {
125                 nv_error(priv, "DISPATCH_ERROR [");
126                 nouveau_enum_print(nv98_crypt_isr_error_name, ssta);
127                 printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n",
128                        chid, (u64)inst << 12, subc, mthd, data);
129                 nv_wr32(priv, 0x087004, 0x00000040);
130                 stat &= ~0x00000040;
131         }
132
133         if (stat) {
134                 nv_error(priv, "unhandled intr 0x%08x\n", stat);
135                 nv_wr32(priv, 0x087004, stat);
136         }
137
138         nouveau_engctx_put(engctx);
139 }
140
141 static int
142 nv98_crypt_tlb_flush(struct nouveau_engine *engine)
143 {
144         nv50_vm_flush_engine(&engine->base, 0x0a);
145         return 0;
146 }
147
148 static int
149 nv98_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
150                struct nouveau_oclass *oclass, void *data, u32 size,
151                struct nouveau_object **pobject)
152 {
153         struct nv98_crypt_priv *priv;
154         int ret;
155
156         ret = nouveau_falcon_create(parent, engine, oclass, 0x087000, true,
157                                     "PCRYPT", "crypt", &priv);
158         *pobject = nv_object(priv);
159         if (ret)
160                 return ret;
161
162         nv_subdev(priv)->unit = 0x00004000;
163         nv_subdev(priv)->intr = nv98_crypt_intr;
164         nv_engine(priv)->cclass = &nv98_crypt_cclass;
165         nv_engine(priv)->sclass = nv98_crypt_sclass;
166         nv_engine(priv)->tlb_flush = nv98_crypt_tlb_flush;
167         nv_falcon(priv)->code.data = nv98_pcrypt_code;
168         nv_falcon(priv)->code.size = sizeof(nv98_pcrypt_code);
169         nv_falcon(priv)->data.data = nv98_pcrypt_data;
170         nv_falcon(priv)->data.size = sizeof(nv98_pcrypt_data);
171         return 0;
172 }
173
174 struct nouveau_oclass
175 nv98_crypt_oclass = {
176         .handle = NV_ENGINE(CRYPT, 0x98),
177         .ofuncs = &(struct nouveau_ofuncs) {
178                 .ctor = nv98_crypt_ctor,
179                 .dtor = _nouveau_falcon_dtor,
180                 .init = _nouveau_falcon_init,
181                 .fini = _nouveau_falcon_fini,
182                 .rd32 = _nouveau_falcon_rd32,
183                 .wr32 = _nouveau_falcon_wr32,
184         },
185 };