Commit | Line | Data |
---|---|---|
ad4a3626 BS |
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 | */ | |
ad4a3626 BS |
23 | #include "priv.h" |
24 | ||
25 | struct priv { | |
d390b480 | 26 | struct nvkm_bios *bios; |
ad4a3626 BS |
27 | u32 bar0; |
28 | }; | |
29 | ||
30 | static u32 | |
d390b480 | 31 | pramin_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) |
ad4a3626 | 32 | { |
d8f266a3 | 33 | struct nvkm_device *device = bios->subdev.device; |
ad4a3626 BS |
34 | u32 i; |
35 | if (offset + length <= 0x00100000) { | |
36 | for (i = offset; i < offset + length; i += 4) | |
d8f266a3 | 37 | *(u32 *)&bios->data[i] = nvkm_rd32(device, 0x700000 + i); |
ad4a3626 BS |
38 | return length; |
39 | } | |
40 | return 0; | |
41 | } | |
42 | ||
43 | static void | |
44 | pramin_fini(void *data) | |
45 | { | |
46 | struct priv *priv = data; | |
c7e873f8 | 47 | if (priv) { |
d8f266a3 BS |
48 | struct nvkm_device *device = priv->bios->subdev.device; |
49 | nvkm_wr32(device, 0x001700, priv->bar0); | |
c7e873f8 BS |
50 | kfree(priv); |
51 | } | |
ad4a3626 BS |
52 | } |
53 | ||
54 | static void * | |
d390b480 | 55 | pramin_init(struct nvkm_bios *bios, const char *name) |
ad4a3626 | 56 | { |
60b29d20 BS |
57 | struct nvkm_subdev *subdev = &bios->subdev; |
58 | struct nvkm_device *device = subdev->device; | |
ad4a3626 BS |
59 | struct priv *priv = NULL; |
60 | u64 addr = 0; | |
61 | ||
62 | /* PRAMIN always potentially available prior to nv50 */ | |
d8f266a3 | 63 | if (device->card_type < NV_50) |
ad4a3626 BS |
64 | return NULL; |
65 | ||
66 | /* we can't get the bios image pointer without PDISP */ | |
a3463248 BS |
67 | if (device->card_type >= GA100) |
68 | addr = device->chipset == 0x170; /*XXX: find the fuse reg for this */ | |
69 | else | |
d8f266a3 BS |
70 | if (device->card_type >= GM100) |
71 | addr = nvkm_rd32(device, 0x021c04); | |
ad4a3626 | 72 | else |
d8f266a3 BS |
73 | if (device->card_type >= NV_C0) |
74 | addr = nvkm_rd32(device, 0x022500); | |
ad4a3626 | 75 | if (addr & 0x00000001) { |
60b29d20 | 76 | nvkm_debug(subdev, "... display disabled\n"); |
ad4a3626 BS |
77 | return ERR_PTR(-ENODEV); |
78 | } | |
79 | ||
80 | /* check that the window is enabled and in vram, particularly | |
81 | * important as we don't want to be touching vram on an | |
82 | * uninitialised board | |
83 | */ | |
75e482ef BS |
84 | if (device->card_type >= GV100) |
85 | addr = nvkm_rd32(device, 0x625f04); | |
86 | else | |
87 | addr = nvkm_rd32(device, 0x619f04); | |
ad4a3626 | 88 | if (!(addr & 0x00000008)) { |
60b29d20 | 89 | nvkm_debug(subdev, "... not enabled\n"); |
ad4a3626 BS |
90 | return ERR_PTR(-ENODEV); |
91 | } | |
92 | if ( (addr & 0x00000003) != 1) { | |
60b29d20 | 93 | nvkm_debug(subdev, "... not in vram\n"); |
ad4a3626 BS |
94 | return ERR_PTR(-ENODEV); |
95 | } | |
96 | ||
97 | /* some alternate method inherited from xf86-video-nv... */ | |
98 | addr = (addr & 0xffffff00) << 8; | |
99 | if (!addr) { | |
d8f266a3 | 100 | addr = (u64)nvkm_rd32(device, 0x001700) << 16; |
ad4a3626 BS |
101 | addr += 0xf0000; |
102 | } | |
103 | ||
104 | /* modify bar0 PRAMIN window to cover the bios image */ | |
105 | if (!(priv = kmalloc(sizeof(*priv), GFP_KERNEL))) { | |
60b29d20 | 106 | nvkm_error(subdev, "... out of memory\n"); |
ad4a3626 BS |
107 | return ERR_PTR(-ENOMEM); |
108 | } | |
109 | ||
110 | priv->bios = bios; | |
d8f266a3 BS |
111 | priv->bar0 = nvkm_rd32(device, 0x001700); |
112 | nvkm_wr32(device, 0x001700, addr >> 16); | |
ad4a3626 BS |
113 | return priv; |
114 | } | |
115 | ||
116 | const struct nvbios_source | |
117 | nvbios_ramin = { | |
118 | .name = "PRAMIN", | |
119 | .init = pramin_init, | |
120 | .fini = pramin_fini, | |
121 | .read = pramin_read, | |
122 | .rw = true, | |
123 | }; |