2 * Copyright 2011 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
27 #include "nouveau_drv.h"
28 #include "nouveau_util.h"
29 #include "nouveau_vm.h"
30 #include "nouveau_ramht.h"
32 #include "nv98_crypt.fuc.h"
34 struct nv98_crypt_priv
{
35 struct nouveau_exec_engine base
;
38 struct nv98_crypt_chan
{
39 struct nouveau_gpuobj
*mem
;
43 nv98_crypt_context_new(struct nouveau_channel
*chan
, int engine
)
45 struct drm_device
*dev
= chan
->dev
;
46 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
47 struct nv98_crypt_priv
*priv
= nv_engine(dev
, engine
);
48 struct nv98_crypt_chan
*cctx
;
51 cctx
= chan
->engctx
[engine
] = kzalloc(sizeof(*cctx
), GFP_KERNEL
);
55 atomic_inc(&chan
->vm
->engref
[engine
]);
57 ret
= nouveau_gpuobj_new(dev
, chan
, 256, 0, NVOBJ_FLAG_ZERO_ALLOC
|
58 NVOBJ_FLAG_ZERO_FREE
, &cctx
->mem
);
62 nv_wo32(chan
->ramin
, 0xa0, 0x00190000);
63 nv_wo32(chan
->ramin
, 0xa4, cctx
->mem
->vinst
+ cctx
->mem
->size
- 1);
64 nv_wo32(chan
->ramin
, 0xa8, cctx
->mem
->vinst
);
65 nv_wo32(chan
->ramin
, 0xac, 0x00000000);
66 nv_wo32(chan
->ramin
, 0xb0, 0x00000000);
67 nv_wo32(chan
->ramin
, 0xb4, 0x00000000);
68 dev_priv
->engine
.instmem
.flush(dev
);
72 priv
->base
.context_del(chan
, engine
);
77 nv98_crypt_context_del(struct nouveau_channel
*chan
, int engine
)
79 struct nv98_crypt_chan
*cctx
= chan
->engctx
[engine
];
82 for (i
= 0xa0; i
< 0xb4; i
+= 4)
83 nv_wo32(chan
->ramin
, i
, 0x00000000);
85 nouveau_gpuobj_ref(NULL
, &cctx
->mem
);
87 atomic_dec(&chan
->vm
->engref
[engine
]);
88 chan
->engctx
[engine
] = NULL
;
93 nv98_crypt_object_new(struct nouveau_channel
*chan
, int engine
,
94 u32 handle
, u16
class)
96 struct nv98_crypt_chan
*cctx
= chan
->engctx
[engine
];
98 /* fuc engine doesn't need an object, our ramht code does.. */
99 cctx
->mem
->engine
= 5;
100 cctx
->mem
->class = class;
101 return nouveau_ramht_insert(chan
, handle
, cctx
->mem
);
105 nv98_crypt_tlb_flush(struct drm_device
*dev
, int engine
)
107 nv50_vm_flush_engine(dev
, 0x0a);
111 nv98_crypt_fini(struct drm_device
*dev
, int engine
, bool suspend
)
113 nv_mask(dev
, 0x000200, 0x00004000, 0x00000000);
118 nv98_crypt_init(struct drm_device
*dev
, int engine
)
123 nv_mask(dev
, 0x000200, 0x00004000, 0x00000000);
124 nv_mask(dev
, 0x000200, 0x00004000, 0x00004000);
126 /* wait for exit interrupt to signal */
127 nv_wait(dev
, 0x087008, 0x00000010, 0x00000010);
128 nv_wr32(dev
, 0x087004, 0x00000010);
130 /* upload microcode code and data segments */
131 nv_wr32(dev
, 0x087ff8, 0x00100000);
132 for (i
= 0; i
< ARRAY_SIZE(nv98_pcrypt_code
); i
++)
133 nv_wr32(dev
, 0x087ff4, nv98_pcrypt_code
[i
]);
135 nv_wr32(dev
, 0x087ff8, 0x00000000);
136 for (i
= 0; i
< ARRAY_SIZE(nv98_pcrypt_data
); i
++)
137 nv_wr32(dev
, 0x087ff4, nv98_pcrypt_data
[i
]);
139 /* start it running */
140 nv_wr32(dev
, 0x08710c, 0x00000000);
141 nv_wr32(dev
, 0x087104, 0x00000000); /* ENTRY */
142 nv_wr32(dev
, 0x087100, 0x00000002); /* TRIGGER */
146 static struct nouveau_enum nv98_crypt_isr_error_name
[] = {
147 { 0x0000, "ILLEGAL_MTHD" },
148 { 0x0001, "INVALID_BITFIELD" },
149 { 0x0002, "INVALID_ENUM" },
155 nv98_crypt_isr(struct drm_device
*dev
)
157 u32 disp
= nv_rd32(dev
, 0x08701c);
158 u32 stat
= nv_rd32(dev
, 0x087008) & disp
& ~(disp
>> 16);
159 u32 inst
= nv_rd32(dev
, 0x087050) & 0x3fffffff;
160 u32 ssta
= nv_rd32(dev
, 0x087040) & 0x0000ffff;
161 u32 addr
= nv_rd32(dev
, 0x087040) >> 16;
162 u32 mthd
= (addr
& 0x07ff) << 2;
163 u32 subc
= (addr
& 0x3800) >> 11;
164 u32 data
= nv_rd32(dev
, 0x087044);
165 int chid
= nv50_graph_isr_chid(dev
, inst
);
167 if (stat
& 0x00000040) {
168 NV_INFO(dev
, "PCRYPT: DISPATCH_ERROR [");
169 nouveau_enum_print(nv98_crypt_isr_error_name
, ssta
);
170 printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n",
171 chid
, inst
, subc
, mthd
, data
);
172 nv_wr32(dev
, 0x087004, 0x00000040);
177 NV_INFO(dev
, "PCRYPT: unhandled intr 0x%08x\n", stat
);
178 nv_wr32(dev
, 0x087004, stat
);
181 nv50_fb_vm_trap(dev
, 1);
185 nv98_crypt_destroy(struct drm_device
*dev
, int engine
)
187 struct nv98_crypt_priv
*priv
= nv_engine(dev
, engine
);
189 nouveau_irq_unregister(dev
, 14);
190 NVOBJ_ENGINE_DEL(dev
, CRYPT
);
195 nv98_crypt_create(struct drm_device
*dev
)
197 struct nv98_crypt_priv
*priv
;
199 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
203 priv
->base
.destroy
= nv98_crypt_destroy
;
204 priv
->base
.init
= nv98_crypt_init
;
205 priv
->base
.fini
= nv98_crypt_fini
;
206 priv
->base
.context_new
= nv98_crypt_context_new
;
207 priv
->base
.context_del
= nv98_crypt_context_del
;
208 priv
->base
.object_new
= nv98_crypt_object_new
;
209 priv
->base
.tlb_flush
= nv98_crypt_tlb_flush
;
211 nouveau_irq_register(dev
, 14, nv98_crypt_isr
);
213 NVOBJ_ENGINE_ADD(dev
, CRYPT
, &priv
->base
);
214 NVOBJ_CLASS(dev
, 0x88b4, CRYPT
);