radeonfb_bios.c revision 1.1.32.1 1 1.1.32.1 joerg /* $NetBSD: radeonfb_bios.c,v 1.1.32.1 2007/10/26 15:46:54 joerg Exp $ */
2 1.1 gdamore
3 1.1 gdamore /*-
4 1.1 gdamore * Copyright (c) 2006 Itronix Inc.
5 1.1 gdamore * All rights reserved.
6 1.1 gdamore *
7 1.1 gdamore * Written by Garrett D'Amore for Itronix Inc.
8 1.1 gdamore *
9 1.1 gdamore * Redistribution and use in source and binary forms, with or without
10 1.1 gdamore * modification, are permitted provided that the following conditions
11 1.1 gdamore * are met:
12 1.1 gdamore * 1. Redistributions of source code must retain the above copyright
13 1.1 gdamore * notice, this list of conditions and the following disclaimer.
14 1.1 gdamore * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 gdamore * notice, this list of conditions and the following disclaimer in the
16 1.1 gdamore * documentation and/or other materials provided with the distribution.
17 1.1 gdamore * 3. The name of Itronix Inc. may not be used to endorse
18 1.1 gdamore * or promote products derived from this software without specific
19 1.1 gdamore * prior written permission.
20 1.1 gdamore *
21 1.1 gdamore * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 1.1 gdamore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 1.1 gdamore * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 1.1 gdamore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 1.1 gdamore * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 1.1 gdamore * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 1.1 gdamore * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 1.1 gdamore * ON ANY THEORY OF LIABILITY, WHETHER IN
29 1.1 gdamore * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 1.1 gdamore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 1.1 gdamore * POSSIBILITY OF SUCH DAMAGE.
32 1.1 gdamore */
33 1.1 gdamore
34 1.1 gdamore /*
35 1.1 gdamore * ATI Technologies Inc. ("ATI") has not assisted in the creation of, and
36 1.1 gdamore * does not endorse, this software. ATI will not be responsible or liable
37 1.1 gdamore * for any actual or alleged damage or loss caused by or in connection with
38 1.1 gdamore * the use of or reliance on this software.
39 1.1 gdamore */
40 1.1 gdamore
41 1.1 gdamore #include <sys/cdefs.h>
42 1.1.32.1 joerg __KERNEL_RCSID(0, "$NetBSD: radeonfb_bios.c,v 1.1.32.1 2007/10/26 15:46:54 joerg Exp $");
43 1.1 gdamore
44 1.1 gdamore #include <sys/param.h>
45 1.1 gdamore #include <sys/systm.h>
46 1.1 gdamore #include <sys/device.h>
47 1.1 gdamore #include <sys/malloc.h>
48 1.1.32.1 joerg #include <sys/bus.h>
49 1.1 gdamore
50 1.1 gdamore #include <dev/pci/pcidevs.h>
51 1.1 gdamore #include <dev/pci/pcireg.h>
52 1.1 gdamore #include <dev/pci/pcivar.h>
53 1.1 gdamore #include <dev/pci/radeonfbreg.h>
54 1.1 gdamore #include <dev/pci/radeonfbvar.h>
55 1.1 gdamore
56 1.1 gdamore #ifdef RADEON_BIOS_INIT
57 1.1 gdamore
58 1.1 gdamore /*
59 1.1 gdamore * Globals for the entire BIOS.
60 1.1 gdamore */
61 1.1 gdamore #define ROM_HEADER_OFFSET 0x48
62 1.1 gdamore #define MAX_REVISION 0x10
63 1.1 gdamore #define SINGLE_TABLE_REVISION 0x09
64 1.1 gdamore #define MIN_OFFSET 0x60
65 1.1 gdamore
66 1.1 gdamore /*
67 1.1 gdamore * Offsets of specific tables.
68 1.1 gdamore */
69 1.1 gdamore #define RAGE_REGS1_OFFSET 0x0c
70 1.1 gdamore #define RAGE_REGS2_OFFSET 0x4e
71 1.1 gdamore #define DYN_CLOCK_OFFSET 0x52
72 1.1 gdamore #define PLL_INIT_OFFSET 0x46
73 1.1 gdamore #define MEM_CONFIG_OFFSET 0x48
74 1.1 gdamore
75 1.1 gdamore /*
76 1.1 gdamore * Values related to generic intialization tables.
77 1.1 gdamore */
78 1.1 gdamore #define TABLE_ENTRY_FLAG_MASK 0xe000
79 1.1 gdamore #define TABLE_ENTRY_INDEX_MASK 0x1fff
80 1.1 gdamore #define TABLE_ENTRY_COMMAND_MASK 0x00ff
81 1.1 gdamore
82 1.1 gdamore #define TABLE_FLAG_WRITE_INDEXED 0x0000
83 1.1 gdamore #define TABLE_FLAG_WRITE_DIRECT 0x2000
84 1.1 gdamore #define TABLE_FLAG_MASK_INDEXED 0x4000
85 1.1 gdamore #define TABLE_FLAG_MASK_DIRECT 0x6000
86 1.1 gdamore #define TABLE_FLAG_DELAY 0x8000
87 1.1 gdamore #define TABLE_FLAG_SCOMMAND 0xa000
88 1.1 gdamore
89 1.1 gdamore #define TABLE_SCOMMAND_WAIT_MC_BUSY_MASK 0x03
90 1.1 gdamore #define TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE 0x08
91 1.1 gdamore
92 1.1 gdamore /*
93 1.1 gdamore * PLL initialization block values.
94 1.1 gdamore */
95 1.1 gdamore #define PLL_FLAG_MASK 0xc0
96 1.1 gdamore #define PLL_INDEX_MASK 0x3f
97 1.1 gdamore
98 1.1 gdamore #define PLL_FLAG_WRITE 0x00
99 1.1 gdamore #define PLL_FLAG_MASK_BYTE 0x40
100 1.1 gdamore #define PLL_FLAG_WAIT 0x80
101 1.1 gdamore
102 1.1 gdamore #define PLL_WAIT_150MKS 1
103 1.1 gdamore #define PLL_WAIT_5MS 2
104 1.1 gdamore #define PLL_WAIT_MC_BUSY_MASK 3
105 1.1 gdamore #define PLL_WAIT_DLL_READY_MASK 4
106 1.1 gdamore #define PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24 5
107 1.1 gdamore
108 1.1 gdamore
109 1.1 gdamore #ifdef RADEON_BIOS_DEBUG
110 1.1 gdamore #define DPRINTF(x) printf x
111 1.1 gdamore #else
112 1.1 gdamore #define DPRINTF(x)
113 1.1 gdamore #endif
114 1.1 gdamore
115 1.1 gdamore struct rb_table;
116 1.1 gdamore
117 1.1 gdamore static void rb_validate(struct radeonfb_softc *, struct rb_table *);
118 1.1 gdamore static uint16_t rb_find_asic_table(struct radeonfb_softc *, struct rb_table *);
119 1.1 gdamore static uint16_t rb_find_mem_reset_table(struct radeonfb_softc *,
120 1.1 gdamore struct rb_table *);
121 1.1 gdamore static uint16_t rb_find_short_mem_reset_table(struct radeonfb_softc *,
122 1.1 gdamore struct rb_table *);
123 1.1 gdamore static int rb_load_init_block(struct radeonfb_softc *, struct rb_table *);
124 1.1 gdamore static int rb_load_pll_block(struct radeonfb_softc *, struct rb_table *);
125 1.1 gdamore static int rb_reset_sdram(struct radeonfb_softc *, struct rb_table *);
126 1.1 gdamore
127 1.1 gdamore static void rb_wait_mc_busy_mask(struct radeonfb_softc *, uint16_t);
128 1.1 gdamore static void rb_wait_mem_pwrup_complete(struct radeonfb_softc *, uint16_t);
129 1.1 gdamore static void rb_wait_dll_ready_mask(struct radeonfb_softc *, uint16_t);
130 1.1 gdamore static void rb_wait_chk_set_clk_pwrmgt_cntl24(struct radeonfb_softc *);
131 1.1 gdamore
132 1.1 gdamore /*
133 1.1 gdamore * Generic structure describing the tables.
134 1.1 gdamore */
135 1.1 gdamore struct rb_table {
136 1.1 gdamore const unsigned char *name;
137 1.1 gdamore uint16_t offset;
138 1.1 gdamore struct rb_table *parent;
139 1.1 gdamore
140 1.1 gdamore /* validate that the table looks sane */
141 1.1 gdamore void (*validate)(struct radeonfb_softc *, struct rb_table *);
142 1.1 gdamore
143 1.1 gdamore /* find looks for the table relative to its "parent" */
144 1.1 gdamore uint16_t (*find)(struct radeonfb_softc *, struct rb_table *);
145 1.1 gdamore };
146 1.1 gdamore
147 1.1 gdamore /*
148 1.1 gdamore * Instances of specific tables.
149 1.1 gdamore */
150 1.1 gdamore static struct rb_table rb_rage_regs1_table = {
151 1.1 gdamore "rage_regs_1", /* name */
152 1.1 gdamore RAGE_REGS1_OFFSET, /* offset */
153 1.1 gdamore NULL, /* parent */
154 1.1 gdamore rb_validate, /* validate */
155 1.1 gdamore NULL, /* find */
156 1.1 gdamore };
157 1.1 gdamore
158 1.1 gdamore static struct rb_table rb_rage_regs2_table = {
159 1.1 gdamore "rage_regs_2", /* name */
160 1.1 gdamore RAGE_REGS2_OFFSET, /* offset */
161 1.1 gdamore NULL, /* parent */
162 1.1 gdamore rb_validate, /* validate */
163 1.1 gdamore NULL, /* find */
164 1.1 gdamore };
165 1.1 gdamore
166 1.1 gdamore static struct rb_table rb_dyn_clock_table = {
167 1.1 gdamore "dyn_clock", /* name */
168 1.1 gdamore DYN_CLOCK_OFFSET, /* offset */
169 1.1 gdamore NULL, /* parent */
170 1.1 gdamore rb_validate, /* validate */
171 1.1 gdamore NULL, /* find */
172 1.1 gdamore };
173 1.1 gdamore
174 1.1 gdamore static struct rb_table rb_pll_init_table = {
175 1.1 gdamore "pll_init", /* name */
176 1.1 gdamore PLL_INIT_OFFSET, /* offset */
177 1.1 gdamore NULL, /* parent */
178 1.1 gdamore rb_validate, /* validate */
179 1.1 gdamore NULL, /* find */
180 1.1 gdamore };
181 1.1 gdamore
182 1.1 gdamore static struct rb_table rb_mem_config_table = {
183 1.1 gdamore "mem_config", /* name */
184 1.1 gdamore MEM_CONFIG_OFFSET, /* offset */
185 1.1 gdamore NULL, /* parent */
186 1.1 gdamore rb_validate, /* validate */
187 1.1 gdamore NULL, /* find */
188 1.1 gdamore };
189 1.1 gdamore
190 1.1 gdamore static struct rb_table rb_mem_reset_table = {
191 1.1 gdamore "mem_reset", /* name */
192 1.1 gdamore 0, /* offset */
193 1.1 gdamore &rb_mem_config_table, /* parent */
194 1.1 gdamore NULL, /* validate */
195 1.1 gdamore rb_find_mem_reset_table, /* find */
196 1.1 gdamore };
197 1.1 gdamore
198 1.1 gdamore static struct rb_table rb_short_mem_reset_table = {
199 1.1 gdamore "short_mem_reset", /* name */
200 1.1 gdamore 0, /* offset */
201 1.1 gdamore &rb_mem_config_table, /* parent */
202 1.1 gdamore NULL, /* validate */
203 1.1 gdamore rb_find_short_mem_reset_table, /* find */
204 1.1 gdamore };
205 1.1 gdamore
206 1.1 gdamore static struct rb_table rb_rage_regs3_table = {
207 1.1 gdamore "rage_regs_3", /* name */
208 1.1 gdamore 0, /* offset */
209 1.1 gdamore &rb_rage_regs2_table, /* parent */
210 1.1 gdamore NULL, /* validate */
211 1.1 gdamore rb_find_asic_table, /* find */
212 1.1 gdamore };
213 1.1 gdamore
214 1.1 gdamore static struct rb_table rb_rage_regs4_table = {
215 1.1 gdamore "rage_regs_4", /* name */
216 1.1 gdamore 0, /* offset */
217 1.1 gdamore &rb_rage_regs3_table, /* parent */
218 1.1 gdamore NULL, /* validate */
219 1.1 gdamore rb_find_asic_table, /* find */
220 1.1 gdamore };
221 1.1 gdamore
222 1.1 gdamore static struct rb_table *rb_tables[] = {
223 1.1 gdamore &rb_rage_regs1_table,
224 1.1 gdamore &rb_rage_regs2_table,
225 1.1 gdamore &rb_dyn_clock_table,
226 1.1 gdamore &rb_pll_init_table,
227 1.1 gdamore &rb_mem_config_table,
228 1.1 gdamore &rb_mem_reset_table,
229 1.1 gdamore &rb_short_mem_reset_table,
230 1.1 gdamore &rb_rage_regs3_table,
231 1.1 gdamore &rb_rage_regs4_table,
232 1.1 gdamore NULL
233 1.1 gdamore };
234 1.1 gdamore
235 1.1 gdamore void
236 1.1 gdamore rb_validate(struct radeonfb_softc *sc, struct rb_table *tp)
237 1.1 gdamore {
238 1.1 gdamore uint8_t rev;
239 1.1 gdamore
240 1.1 gdamore rev = GETBIOS8(sc, tp->offset - 1);
241 1.1 gdamore
242 1.1 gdamore if (rev > MAX_REVISION) {
243 1.1 gdamore DPRINTF(("%s: bad rev %x of %s\n", XNAME(sc), rev, tp->name));
244 1.1 gdamore tp->offset = 0;
245 1.1 gdamore return;
246 1.1 gdamore }
247 1.1 gdamore
248 1.1 gdamore if (tp->offset < MIN_OFFSET) {
249 1.1 gdamore DPRINTF(("%s: wrong pointer to %s!\n", XNAME(sc), tp->name));
250 1.1 gdamore tp->offset = 0;
251 1.1 gdamore return;
252 1.1 gdamore }
253 1.1 gdamore }
254 1.1 gdamore
255 1.1 gdamore uint16_t
256 1.1 gdamore rb_find_asic_table(struct radeonfb_softc *sc, struct rb_table *tp)
257 1.1 gdamore {
258 1.1 gdamore uint16_t offset;
259 1.1 gdamore uint8_t c;
260 1.1 gdamore
261 1.1 gdamore if ((offset = tp->offset) != 0) {
262 1.1 gdamore while ((c = GETBIOS8(sc, offset + 1)) != 0) {
263 1.1 gdamore if (c & 0x40)
264 1.1 gdamore offset += 10;
265 1.1 gdamore else if (c & 0x80)
266 1.1 gdamore offset += 4;
267 1.1 gdamore else
268 1.1 gdamore offset += 6;
269 1.1 gdamore }
270 1.1 gdamore return offset + 2;
271 1.1 gdamore }
272 1.1 gdamore return 0;
273 1.1 gdamore }
274 1.1 gdamore
275 1.1 gdamore uint16_t
276 1.1 gdamore rb_find_mem_reset_table(struct radeonfb_softc *sc, struct rb_table *tp)
277 1.1 gdamore {
278 1.1 gdamore uint16_t offset;
279 1.1 gdamore
280 1.1 gdamore if ((offset = tp->offset) != 0) {
281 1.1 gdamore while (GETBIOS8(sc, offset))
282 1.1 gdamore offset++;
283 1.1 gdamore offset++;
284 1.1 gdamore return offset + 2; /* skip table revision and mask */
285 1.1 gdamore }
286 1.1 gdamore return 0;
287 1.1 gdamore }
288 1.1 gdamore
289 1.1 gdamore uint16_t
290 1.1 gdamore rb_find_short_mem_reset_table(struct radeonfb_softc *sc, struct rb_table *tp)
291 1.1 gdamore {
292 1.1 gdamore
293 1.1 gdamore if ((tp->offset != 0) && (GETBIOS8(sc, tp->offset - 2) <= 64))
294 1.1 gdamore return (tp->offset + GETBIOS8(sc, tp->offset - 3));
295 1.1 gdamore
296 1.1 gdamore return 0;
297 1.1 gdamore }
298 1.1 gdamore
299 1.1 gdamore /* helper commands */
300 1.1 gdamore void
301 1.1 gdamore rb_wait_mc_busy_mask(struct radeonfb_softc *sc, uint16_t count)
302 1.1 gdamore {
303 1.1 gdamore DPRINTF(("WAIT_MC_BUSY_MASK: %d ", count));
304 1.1 gdamore while (count--) {
305 1.1 gdamore if (!(radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL) &
306 1.1 gdamore RADEON_MC_BUSY_MASK))
307 1.1 gdamore break;
308 1.1 gdamore }
309 1.1 gdamore DPRINTF(("%d\n", count));
310 1.1 gdamore }
311 1.1 gdamore
312 1.1 gdamore void
313 1.1 gdamore rb_wait_mem_pwrup_complete(struct radeonfb_softc *sc, uint16_t count)
314 1.1 gdamore {
315 1.1 gdamore DPRINTF(("WAIT_MEM_PWRUP_COMPLETE: %d ", count));
316 1.1 gdamore while (count--) {
317 1.1 gdamore if ((radeonfb_getindex(sc, RADEON_MEM_STR_CNTL) &
318 1.1 gdamore RADEON_MEM_PWRUP_COMPLETE) ==
319 1.1 gdamore RADEON_MEM_PWRUP_COMPLETE)
320 1.1 gdamore break;
321 1.1 gdamore }
322 1.1 gdamore DPRINTF(("%d\n", count));
323 1.1 gdamore }
324 1.1 gdamore
325 1.1 gdamore void
326 1.1 gdamore rb_wait_dll_ready_mask(struct radeonfb_softc *sc, uint16_t count)
327 1.1 gdamore {
328 1.1 gdamore DPRINTF(("WAIT_DLL_READY_MASK: %d ", count));
329 1.1 gdamore while (count--) {
330 1.1 gdamore if (radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL) &
331 1.1 gdamore RADEON_DLL_READY_MASK)
332 1.1 gdamore break;
333 1.1 gdamore }
334 1.1 gdamore DPRINTF(("%d\n", count));
335 1.1 gdamore }
336 1.1 gdamore
337 1.1 gdamore void
338 1.1 gdamore rb_wait_chk_set_clk_pwrmgt_cntl24(struct radeonfb_softc *sc)
339 1.1 gdamore {
340 1.1 gdamore uint32_t pmc;
341 1.1 gdamore DPRINTF(("WAIT CHK_SET_CLK_PWRMGT_CNTL24\n"));
342 1.1 gdamore pmc = radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL);
343 1.1 gdamore
344 1.1 gdamore if (pmc & RADEON_CLK_PWRMGT_CNTL24) {
345 1.1 gdamore radeonfb_maskpll(sc, RADEON_MCLK_CNTL, 0xFFFF0000,
346 1.1 gdamore RADEON_SET_ALL_SRCS_TO_PCI);
347 1.1 gdamore delay(10000);
348 1.1 gdamore radeonfb_putpll(sc, RADEON_CLK_PWRMGT_CNTL,
349 1.1 gdamore pmc & ~RADEON_CLK_PWRMGT_CNTL24);
350 1.1 gdamore delay(10000);
351 1.1 gdamore }
352 1.1 gdamore }
353 1.1 gdamore
354 1.1 gdamore /*
355 1.1 gdamore * Block initialization routines. These take action based on data in
356 1.1 gdamore * the tables.
357 1.1 gdamore */
358 1.1 gdamore int
359 1.1 gdamore rb_load_init_block(struct radeonfb_softc *sc, struct rb_table *tp)
360 1.1 gdamore {
361 1.1 gdamore uint16_t offset;
362 1.1 gdamore uint16_t value;
363 1.1 gdamore
364 1.1 gdamore if ((tp == NULL) || ((offset = tp->offset) == 0))
365 1.1 gdamore return 1;
366 1.1 gdamore
367 1.1 gdamore DPRINTF(("%s: load_init_block processing %s\n", XNAME(sc), tp->name));
368 1.1 gdamore while ((value = GETBIOS16(sc, offset)) != 0) {
369 1.1 gdamore uint16_t flag = value & TABLE_ENTRY_FLAG_MASK;
370 1.1 gdamore uint16_t index = value & TABLE_ENTRY_INDEX_MASK;
371 1.1 gdamore uint8_t command = value & TABLE_ENTRY_COMMAND_MASK;
372 1.1 gdamore uint32_t ormask;
373 1.1 gdamore uint32_t andmask;
374 1.1 gdamore uint16_t count;
375 1.1 gdamore
376 1.1 gdamore offset += 2;
377 1.1 gdamore
378 1.1 gdamore switch (flag) {
379 1.1 gdamore case TABLE_FLAG_WRITE_INDEXED:
380 1.1 gdamore DPRINTF(("WRITE INDEXED: %x %x\n",
381 1.1 gdamore index, (uint32_t)GETBIOS32(sc, offset)));
382 1.1 gdamore radeonfb_putindex(sc, index, GETBIOS32(sc, offset));
383 1.1 gdamore offset += 4;
384 1.1 gdamore break;
385 1.1 gdamore
386 1.1 gdamore case TABLE_FLAG_WRITE_DIRECT:
387 1.1 gdamore DPRINTF(("WRITE DIRECT: %x %x\n",
388 1.1 gdamore index, (uint32_t)GETBIOS32(sc, offset)));
389 1.1 gdamore radeonfb_put32(sc, index, GETBIOS32(sc, offset));
390 1.1 gdamore offset += 4;
391 1.1 gdamore break;
392 1.1 gdamore
393 1.1 gdamore case TABLE_FLAG_MASK_INDEXED:
394 1.1 gdamore andmask = GETBIOS32(sc, offset);
395 1.1 gdamore offset += 4;
396 1.1 gdamore ormask = GETBIOS32(sc, offset);
397 1.1 gdamore offset += 4;
398 1.1 gdamore DPRINTF(("MASK INDEXED: %x %x %x\n",
399 1.1 gdamore index, andmask, ormask));
400 1.1 gdamore radeonfb_maskindex(sc, index, andmask, ormask);
401 1.1 gdamore break;
402 1.1 gdamore
403 1.1 gdamore case TABLE_FLAG_MASK_DIRECT:
404 1.1 gdamore andmask = GETBIOS32(sc, offset);
405 1.1 gdamore offset += 4;
406 1.1 gdamore ormask = GETBIOS32(sc, offset);
407 1.1 gdamore offset += 4;
408 1.1 gdamore DPRINTF(("MASK DIRECT: %x %x %x\n",
409 1.1 gdamore index, andmask, ormask));
410 1.1 gdamore radeonfb_mask32(sc, index, andmask, ormask);
411 1.1 gdamore break;
412 1.1 gdamore
413 1.1 gdamore case TABLE_FLAG_DELAY:
414 1.1 gdamore /* in the worst case, this would be 16msec */
415 1.1 gdamore count = GETBIOS16(sc, offset);
416 1.1 gdamore DPRINTF(("DELAY: %d\n", count));
417 1.1 gdamore delay(count);
418 1.1 gdamore offset += 2;
419 1.1 gdamore break;
420 1.1 gdamore
421 1.1 gdamore case TABLE_FLAG_SCOMMAND:
422 1.1 gdamore DPRINTF(("SCOMMAND %x\n", command));
423 1.1 gdamore switch (command) {
424 1.1 gdamore
425 1.1 gdamore case TABLE_SCOMMAND_WAIT_MC_BUSY_MASK:
426 1.1 gdamore count = GETBIOS16(sc, offset);
427 1.1 gdamore rb_wait_mc_busy_mask(sc, count);
428 1.1 gdamore break;
429 1.1 gdamore
430 1.1 gdamore case TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE:
431 1.1 gdamore count = GETBIOS16(sc, offset);
432 1.1 gdamore rb_wait_mem_pwrup_complete(sc, count);
433 1.1 gdamore break;
434 1.1 gdamore
435 1.1 gdamore }
436 1.1 gdamore offset += 2;
437 1.1 gdamore break;
438 1.1 gdamore }
439 1.1 gdamore }
440 1.1 gdamore return 0;
441 1.1 gdamore }
442 1.1 gdamore
443 1.1 gdamore int
444 1.1 gdamore rb_load_pll_block(struct radeonfb_softc *sc, struct rb_table *tp)
445 1.1 gdamore {
446 1.1 gdamore uint16_t offset;
447 1.1 gdamore uint8_t index;
448 1.1 gdamore uint8_t shift;
449 1.1 gdamore uint32_t andmask;
450 1.1 gdamore uint32_t ormask;
451 1.1 gdamore
452 1.1 gdamore if ((tp == NULL) || ((offset = tp->offset) == 0))
453 1.1 gdamore return 1;
454 1.1 gdamore
455 1.1 gdamore DPRINTF(("%s: load_pll_block processing %s\n", XNAME(sc), tp->name));
456 1.1 gdamore while ((index = GETBIOS8(sc, offset)) != 0) {
457 1.1 gdamore offset++;
458 1.1 gdamore
459 1.1 gdamore switch (index & PLL_FLAG_MASK) {
460 1.1 gdamore case PLL_FLAG_WAIT:
461 1.1 gdamore switch (index & PLL_INDEX_MASK) {
462 1.1 gdamore case PLL_WAIT_150MKS:
463 1.1 gdamore delay(150);
464 1.1 gdamore break;
465 1.1 gdamore case PLL_WAIT_5MS:
466 1.1 gdamore /* perhaps this should be tsleep? */
467 1.1 gdamore delay(5000);
468 1.1 gdamore break;
469 1.1 gdamore
470 1.1 gdamore case PLL_WAIT_MC_BUSY_MASK:
471 1.1 gdamore rb_wait_mc_busy_mask(sc, 1000);
472 1.1 gdamore break;
473 1.1 gdamore
474 1.1 gdamore case PLL_WAIT_DLL_READY_MASK:
475 1.1 gdamore rb_wait_dll_ready_mask(sc, 1000);
476 1.1 gdamore break;
477 1.1 gdamore
478 1.1 gdamore case PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24:
479 1.1 gdamore rb_wait_chk_set_clk_pwrmgt_cntl24(sc);
480 1.1 gdamore break;
481 1.1 gdamore }
482 1.1 gdamore break;
483 1.1 gdamore
484 1.1 gdamore case PLL_FLAG_MASK_BYTE:
485 1.1 gdamore shift = GETBIOS8(sc, offset) * 8;
486 1.1 gdamore offset++;
487 1.1 gdamore
488 1.1 gdamore andmask =
489 1.1 gdamore (((uint32_t)GETBIOS8(sc, offset)) << shift) |
490 1.1 gdamore ~((uint32_t)0xff << shift);
491 1.1 gdamore offset++;
492 1.1 gdamore
493 1.1 gdamore ormask = ((uint32_t)GETBIOS8(sc, offset)) << shift;
494 1.1 gdamore offset++;
495 1.1 gdamore
496 1.1 gdamore DPRINTF(("PLL_MASK_BYTE %u %u %x %x\n", index,
497 1.1 gdamore shift, andmask, ormask));
498 1.1 gdamore radeonfb_maskpll(sc, index, andmask, ormask);
499 1.1 gdamore break;
500 1.1 gdamore
501 1.1 gdamore case PLL_FLAG_WRITE:
502 1.1 gdamore DPRINTF(("PLL_WRITE %u %x\n", index,
503 1.1 gdamore GETBIOS32(sc, offset)));
504 1.1 gdamore radeonfb_putpll(sc, index, GETBIOS32(sc, offset));
505 1.1 gdamore offset += 4;
506 1.1 gdamore break;
507 1.1 gdamore }
508 1.1 gdamore }
509 1.1 gdamore
510 1.1 gdamore return 0;
511 1.1 gdamore }
512 1.1 gdamore
513 1.1 gdamore int
514 1.1 gdamore rb_reset_sdram(struct radeonfb_softc *sc, struct rb_table *tp)
515 1.1 gdamore {
516 1.1 gdamore uint16_t offset;
517 1.1 gdamore uint8_t index;
518 1.1 gdamore
519 1.1 gdamore if ((tp == NULL) || ((offset = tp->offset) == 0))
520 1.1 gdamore return 1;
521 1.1 gdamore
522 1.1 gdamore DPRINTF(("%s: reset_sdram processing %s\n", XNAME(sc), tp->name));
523 1.1 gdamore
524 1.1 gdamore while ((index = GETBIOS8(sc, offset)) != 0xff) {
525 1.1 gdamore offset++;
526 1.1 gdamore if (index == 0x0f) {
527 1.1 gdamore rb_wait_mem_pwrup_complete(sc, 20000);
528 1.1 gdamore } else {
529 1.1 gdamore uint32_t ormask;
530 1.1 gdamore
531 1.1 gdamore ormask = GETBIOS16(sc, offset);
532 1.1 gdamore offset += 2;
533 1.1 gdamore
534 1.1 gdamore DPRINTF(("INDEX reg RADEON_MEM_SDRAM_MODE_REG %x %x\n",
535 1.1 gdamore RADEON_SDRAM_MODE_MASK, ormask));
536 1.1 gdamore radeonfb_maskindex(sc, RADEON_MEM_SDRAM_MODE_REG,
537 1.1 gdamore RADEON_SDRAM_MODE_MASK, ormask);
538 1.1 gdamore
539 1.1 gdamore ormask = (uint32_t)index << 24;
540 1.1 gdamore DPRINTF(("INDEX reg RADEON_MEM_SDRAM_MODE_REG %x %x\n",
541 1.1 gdamore RADEON_B3MEM_RESET_MASK, ormask));
542 1.1 gdamore radeonfb_maskindex(sc, RADEON_MEM_SDRAM_MODE_REG,
543 1.1 gdamore RADEON_B3MEM_RESET_MASK, ormask);
544 1.1 gdamore }
545 1.1 gdamore }
546 1.1 gdamore return 0;
547 1.1 gdamore }
548 1.1 gdamore
549 1.1 gdamore /*
550 1.1 gdamore * Master entry point to parse and act on table data.
551 1.1 gdamore */
552 1.1 gdamore int
553 1.1 gdamore radeonfb_bios_init(struct radeonfb_softc *sc)
554 1.1 gdamore {
555 1.1 gdamore uint16_t revision;
556 1.1 gdamore uint16_t scratch;
557 1.1 gdamore int i;
558 1.1 gdamore struct rb_table *tp;
559 1.1 gdamore
560 1.1 gdamore if (!sc->sc_biossz)
561 1.1 gdamore return 1;
562 1.1 gdamore
563 1.1 gdamore scratch = GETBIOS16(sc, ROM_HEADER_OFFSET);
564 1.1 gdamore revision = GETBIOS8(sc, scratch);
565 1.1 gdamore DPRINTF(("%s: Bios Rev: %d\n", XNAME(sc), revision));
566 1.1 gdamore
567 1.1 gdamore
568 1.1 gdamore /* First parse pass -- locate tables */
569 1.1 gdamore for (i = 0; (tp = rb_tables[i]) != NULL; i++) {
570 1.1 gdamore
571 1.1 gdamore DPRINTF(("%s: parsing table %s\n", XNAME(sc), tp->name));
572 1.1 gdamore
573 1.1 gdamore if (tp->offset != 0) {
574 1.1 gdamore uint16_t temp, offset;;
575 1.1 gdamore
576 1.1 gdamore temp = GETBIOS16(sc, ROM_HEADER_OFFSET);
577 1.1 gdamore offset = GETBIOS16(sc, temp + tp->offset);
578 1.1 gdamore if (offset)
579 1.1 gdamore tp->offset = offset;
580 1.1 gdamore
581 1.1 gdamore } else {
582 1.1 gdamore tp->offset = tp->find(sc, tp->parent);
583 1.1 gdamore }
584 1.1 gdamore
585 1.1 gdamore if (tp->validate)
586 1.1 gdamore tp->validate(sc, tp);
587 1.1 gdamore
588 1.1 gdamore if (revision > SINGLE_TABLE_REVISION)
589 1.1 gdamore break;
590 1.1 gdamore }
591 1.1 gdamore
592 1.1 gdamore if (rb_rage_regs3_table.offset + 1 == rb_pll_init_table.offset) {
593 1.1 gdamore rb_rage_regs3_table.offset = 0;
594 1.1 gdamore rb_rage_regs4_table.offset = 0;
595 1.1 gdamore }
596 1.1 gdamore
597 1.1 gdamore if (rb_rage_regs1_table.offset)
598 1.1 gdamore rb_load_init_block(sc, &rb_rage_regs1_table);
599 1.1 gdamore
600 1.1 gdamore if (revision < SINGLE_TABLE_REVISION) {
601 1.1 gdamore if (rb_pll_init_table.offset)
602 1.1 gdamore rb_load_pll_block(sc, &rb_pll_init_table);
603 1.1 gdamore if (rb_rage_regs2_table.offset)
604 1.1 gdamore rb_load_init_block(sc, &rb_rage_regs2_table);
605 1.1 gdamore if (rb_rage_regs4_table.offset)
606 1.1 gdamore rb_load_init_block(sc, &rb_rage_regs4_table);
607 1.1 gdamore if (rb_mem_reset_table.offset)
608 1.1 gdamore rb_reset_sdram(sc, &rb_mem_reset_table);
609 1.1 gdamore if (rb_rage_regs3_table.offset)
610 1.1 gdamore rb_load_init_block(sc, &rb_rage_regs3_table);
611 1.1 gdamore if (rb_dyn_clock_table.offset)
612 1.1 gdamore rb_load_pll_block(sc, &rb_dyn_clock_table);
613 1.1 gdamore }
614 1.1 gdamore
615 1.1 gdamore DPRINTF(("%s: BIOS parse done\n", XNAME(sc)));
616 1.1 gdamore return 0;
617 1.1 gdamore }
618 1.1 gdamore
619 1.1 gdamore #endif
620