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 "nv04.h" 26 27/****************************************************************************** 28 * instmem object implementation 29 *****************************************************************************/ 30 31static u32 32nv04_instobj_rd32(struct nouveau_object *object, u64 addr) 33{ 34 struct nv04_instobj_priv *node = (void *)object; 35 return nv_ro32(object->engine, node->mem->offset + addr); 36} 37 38static void 39nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data) 40{ 41 struct nv04_instobj_priv *node = (void *)object; 42 nv_wo32(object->engine, node->mem->offset + addr, data); 43} 44 45static void 46nv04_instobj_dtor(struct nouveau_object *object) 47{ 48 struct nv04_instmem_priv *priv = (void *)object->engine; 49 struct nv04_instobj_priv *node = (void *)object; 50 nouveau_mm_free(&priv->heap, &node->mem); 51 nouveau_instobj_destroy(&node->base); 52} 53 54static int 55nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 56 struct nouveau_oclass *oclass, void *data, u32 size, 57 struct nouveau_object **pobject) 58{ 59 struct nv04_instmem_priv *priv = (void *)engine; 60 struct nv04_instobj_priv *node; 61 struct nouveau_instobj_args *args = data; 62 int ret; 63 64 if (!args->align) 65 args->align = 1; 66 67 ret = nouveau_instobj_create(parent, engine, oclass, &node); 68 *pobject = nv_object(node); 69 if (ret) 70 return ret; 71 72 ret = nouveau_mm_head(&priv->heap, 0, 1, args->size, args->size, 73 args->align, &node->mem); 74 if (ret) 75 return ret; 76 77 node->base.addr = node->mem->offset; 78 node->base.size = node->mem->length; 79 return 0; 80} 81 82struct nouveau_instobj_impl 83nv04_instobj_oclass = { 84 .base.ofuncs = &(struct nouveau_ofuncs) { 85 .ctor = nv04_instobj_ctor, 86 .dtor = nv04_instobj_dtor, 87 .init = _nouveau_instobj_init, 88 .fini = _nouveau_instobj_fini, 89 .rd32 = nv04_instobj_rd32, 90 .wr32 = nv04_instobj_wr32, 91 }, 92}; 93 94/****************************************************************************** 95 * instmem subdev implementation 96 *****************************************************************************/ 97 98static u32 99nv04_instmem_rd32(struct nouveau_object *object, u64 addr) 100{ 101 return nv_rd32(object, 0x700000 + addr); 102} 103 104static void 105nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) 106{ 107 return nv_wr32(object, 0x700000 + addr, data); 108} 109 110void 111nv04_instmem_dtor(struct nouveau_object *object) 112{ 113 struct nv04_instmem_priv *priv = (void *)object; 114 nouveau_gpuobj_ref(NULL, &priv->ramfc); 115 nouveau_gpuobj_ref(NULL, &priv->ramro); 116 nouveau_ramht_ref(NULL, &priv->ramht); 117 nouveau_gpuobj_ref(NULL, &priv->vbios); 118 nouveau_mm_fini(&priv->heap); 119 if (priv->iomem) 120 iounmap(priv->iomem); 121 nouveau_instmem_destroy(&priv->base); 122} 123 124static int 125nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 126 struct nouveau_oclass *oclass, void *data, u32 size, 127 struct nouveau_object **pobject) 128{ 129 struct nv04_instmem_priv *priv; 130 int ret; 131 132 ret = nouveau_instmem_create(parent, engine, oclass, &priv); 133 *pobject = nv_object(priv); 134 if (ret) 135 return ret; 136 137 /* PRAMIN aperture maps over the end of VRAM, reserve it */ 138 priv->base.reserved = 512 * 1024; 139 140 ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1); 141 if (ret) 142 return ret; 143 144 /* 0x00000-0x10000: reserve for probable vbios image */ 145 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x10000, 0, 0, 146 &priv->vbios); 147 if (ret) 148 return ret; 149 150 /* 0x10000-0x18000: reserve for RAMHT */ 151 ret = nouveau_ramht_new(nv_object(priv), NULL, 0x08000, 0, &priv->ramht); 152 if (ret) 153 return ret; 154 155 /* 0x18000-0x18800: reserve for RAMFC (enough for 32 nv30 channels) */ 156 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x00800, 0, 157 NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc); 158 if (ret) 159 return ret; 160 161 /* 0x18800-0x18a00: reserve for RAMRO */ 162 ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x00200, 0, 0, 163 &priv->ramro); 164 if (ret) 165 return ret; 166 167 return 0; 168} 169 170struct nouveau_oclass * 171nv04_instmem_oclass = &(struct nouveau_instmem_impl) { 172 .base.handle = NV_SUBDEV(INSTMEM, 0x04), 173 .base.ofuncs = &(struct nouveau_ofuncs) { 174 .ctor = nv04_instmem_ctor, 175 .dtor = nv04_instmem_dtor, 176 .init = _nouveau_instmem_init, 177 .fini = _nouveau_instmem_fini, 178 .rd32 = nv04_instmem_rd32, 179 .wr32 = nv04_instmem_wr32, 180 }, 181 .instobj = &nv04_instobj_oclass.base, 182}.base; 183