radeonfb_bios.c revision 1.6 1 1.6 macallan /* $NetBSD: radeonfb_bios.c,v 1.6 2020/09/18 20:44:20 macallan 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.6 macallan __KERNEL_RCSID(0, "$NetBSD: radeonfb_bios.c,v 1.6 2020/09/18 20:44:20 macallan 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.2 ad #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.4 macallan #include "opt_radeonfb.h"
57 1.4 macallan
58 1.4 macallan #ifdef RADEONFB_BIOS_INIT
59 1.1 gdamore
60 1.1 gdamore /*
61 1.1 gdamore * Globals for the entire BIOS.
62 1.1 gdamore */
63 1.1 gdamore #define ROM_HEADER_OFFSET 0x48
64 1.1 gdamore #define MAX_REVISION 0x10
65 1.1 gdamore #define SINGLE_TABLE_REVISION 0x09
66 1.1 gdamore #define MIN_OFFSET 0x60
67 1.1 gdamore
68 1.1 gdamore /*
69 1.1 gdamore * Offsets of specific tables.
70 1.1 gdamore */
71 1.1 gdamore #define RAGE_REGS1_OFFSET 0x0c
72 1.1 gdamore #define RAGE_REGS2_OFFSET 0x4e
73 1.1 gdamore #define DYN_CLOCK_OFFSET 0x52
74 1.1 gdamore #define PLL_INIT_OFFSET 0x46
75 1.1 gdamore #define MEM_CONFIG_OFFSET 0x48
76 1.1 gdamore
77 1.1 gdamore /*
78 1.5 dholland * Values related to generic initialization tables.
79 1.1 gdamore */
80 1.1 gdamore #define TABLE_ENTRY_FLAG_MASK 0xe000
81 1.1 gdamore #define TABLE_ENTRY_INDEX_MASK 0x1fff
82 1.1 gdamore #define TABLE_ENTRY_COMMAND_MASK 0x00ff
83 1.1 gdamore
84 1.1 gdamore #define TABLE_FLAG_WRITE_INDEXED 0x0000
85 1.1 gdamore #define TABLE_FLAG_WRITE_DIRECT 0x2000
86 1.1 gdamore #define TABLE_FLAG_MASK_INDEXED 0x4000
87 1.1 gdamore #define TABLE_FLAG_MASK_DIRECT 0x6000
88 1.1 gdamore #define TABLE_FLAG_DELAY 0x8000
89 1.1 gdamore #define TABLE_FLAG_SCOMMAND 0xa000
90 1.1 gdamore
91 1.1 gdamore #define TABLE_SCOMMAND_WAIT_MC_BUSY_MASK 0x03
92 1.1 gdamore #define TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE 0x08
93 1.1 gdamore
94 1.1 gdamore /*
95 1.1 gdamore * PLL initialization block values.
96 1.1 gdamore */
97 1.1 gdamore #define PLL_FLAG_MASK 0xc0
98 1.1 gdamore #define PLL_INDEX_MASK 0x3f
99 1.1 gdamore
100 1.1 gdamore #define PLL_FLAG_WRITE 0x00
101 1.1 gdamore #define PLL_FLAG_MASK_BYTE 0x40
102 1.1 gdamore #define PLL_FLAG_WAIT 0x80
103 1.1 gdamore
104 1.1 gdamore #define PLL_WAIT_150MKS 1
105 1.1 gdamore #define PLL_WAIT_5MS 2
106 1.1 gdamore #define PLL_WAIT_MC_BUSY_MASK 3
107 1.1 gdamore #define PLL_WAIT_DLL_READY_MASK 4
108 1.1 gdamore #define PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24 5
109 1.1 gdamore
110 1.1 gdamore
111 1.4 macallan #ifdef RADEONFB_BIOS_DEBUG
112 1.1 gdamore #define DPRINTF(x) printf x
113 1.1 gdamore #else
114 1.1 gdamore #define DPRINTF(x)
115 1.1 gdamore #endif
116 1.1 gdamore
117 1.1 gdamore struct rb_table;
118 1.1 gdamore
119 1.1 gdamore static void rb_validate(struct radeonfb_softc *, struct rb_table *);
120 1.1 gdamore static uint16_t rb_find_asic_table(struct radeonfb_softc *, struct rb_table *);
121 1.1 gdamore static uint16_t rb_find_mem_reset_table(struct radeonfb_softc *,
122 1.1 gdamore struct rb_table *);
123 1.1 gdamore static uint16_t rb_find_short_mem_reset_table(struct radeonfb_softc *,
124 1.1 gdamore struct rb_table *);
125 1.1 gdamore static int rb_load_init_block(struct radeonfb_softc *, struct rb_table *);
126 1.1 gdamore static int rb_load_pll_block(struct radeonfb_softc *, struct rb_table *);
127 1.1 gdamore static int rb_reset_sdram(struct radeonfb_softc *, struct rb_table *);
128 1.1 gdamore
129 1.1 gdamore static void rb_wait_mc_busy_mask(struct radeonfb_softc *, uint16_t);
130 1.1 gdamore static void rb_wait_mem_pwrup_complete(struct radeonfb_softc *, uint16_t);
131 1.1 gdamore static void rb_wait_dll_ready_mask(struct radeonfb_softc *, uint16_t);
132 1.1 gdamore static void rb_wait_chk_set_clk_pwrmgt_cntl24(struct radeonfb_softc *);
133 1.1 gdamore
134 1.1 gdamore /*
135 1.1 gdamore * Generic structure describing the tables.
136 1.1 gdamore */
137 1.1 gdamore struct rb_table {
138 1.1 gdamore const unsigned char *name;
139 1.1 gdamore uint16_t offset;
140 1.1 gdamore struct rb_table *parent;
141 1.1 gdamore
142 1.1 gdamore /* validate that the table looks sane */
143 1.1 gdamore void (*validate)(struct radeonfb_softc *, struct rb_table *);
144 1.1 gdamore
145 1.1 gdamore /* find looks for the table relative to its "parent" */
146 1.1 gdamore uint16_t (*find)(struct radeonfb_softc *, struct rb_table *);
147 1.1 gdamore };
148 1.1 gdamore
149 1.1 gdamore /*
150 1.1 gdamore * Instances of specific tables.
151 1.1 gdamore */
152 1.1 gdamore static struct rb_table rb_rage_regs1_table = {
153 1.1 gdamore "rage_regs_1", /* name */
154 1.1 gdamore RAGE_REGS1_OFFSET, /* offset */
155 1.1 gdamore NULL, /* parent */
156 1.1 gdamore rb_validate, /* validate */
157 1.1 gdamore NULL, /* find */
158 1.1 gdamore };
159 1.1 gdamore
160 1.1 gdamore static struct rb_table rb_rage_regs2_table = {
161 1.1 gdamore "rage_regs_2", /* name */
162 1.1 gdamore RAGE_REGS2_OFFSET, /* offset */
163 1.1 gdamore NULL, /* parent */
164 1.1 gdamore rb_validate, /* validate */
165 1.1 gdamore NULL, /* find */
166 1.1 gdamore };
167 1.1 gdamore
168 1.1 gdamore static struct rb_table rb_dyn_clock_table = {
169 1.1 gdamore "dyn_clock", /* name */
170 1.1 gdamore DYN_CLOCK_OFFSET, /* offset */
171 1.1 gdamore NULL, /* parent */
172 1.1 gdamore rb_validate, /* validate */
173 1.1 gdamore NULL, /* find */
174 1.1 gdamore };
175 1.1 gdamore
176 1.1 gdamore static struct rb_table rb_pll_init_table = {
177 1.1 gdamore "pll_init", /* name */
178 1.1 gdamore PLL_INIT_OFFSET, /* offset */
179 1.1 gdamore NULL, /* parent */
180 1.1 gdamore rb_validate, /* validate */
181 1.1 gdamore NULL, /* find */
182 1.1 gdamore };
183 1.1 gdamore
184 1.1 gdamore static struct rb_table rb_mem_config_table = {
185 1.1 gdamore "mem_config", /* name */
186 1.1 gdamore MEM_CONFIG_OFFSET, /* offset */
187 1.1 gdamore NULL, /* parent */
188 1.1 gdamore rb_validate, /* validate */
189 1.1 gdamore NULL, /* find */
190 1.1 gdamore };
191 1.1 gdamore
192 1.1 gdamore static struct rb_table rb_mem_reset_table = {
193 1.1 gdamore "mem_reset", /* name */
194 1.1 gdamore 0, /* offset */
195 1.1 gdamore &rb_mem_config_table, /* parent */
196 1.1 gdamore NULL, /* validate */
197 1.1 gdamore rb_find_mem_reset_table, /* find */
198 1.1 gdamore };
199 1.1 gdamore
200 1.1 gdamore static struct rb_table rb_short_mem_reset_table = {
201 1.1 gdamore "short_mem_reset", /* name */
202 1.1 gdamore 0, /* offset */
203 1.1 gdamore &rb_mem_config_table, /* parent */
204 1.1 gdamore NULL, /* validate */
205 1.1 gdamore rb_find_short_mem_reset_table, /* find */
206 1.1 gdamore };
207 1.1 gdamore
208 1.1 gdamore static struct rb_table rb_rage_regs3_table = {
209 1.1 gdamore "rage_regs_3", /* name */
210 1.1 gdamore 0, /* offset */
211 1.1 gdamore &rb_rage_regs2_table, /* parent */
212 1.1 gdamore NULL, /* validate */
213 1.1 gdamore rb_find_asic_table, /* find */
214 1.1 gdamore };
215 1.1 gdamore
216 1.1 gdamore static struct rb_table rb_rage_regs4_table = {
217 1.1 gdamore "rage_regs_4", /* name */
218 1.1 gdamore 0, /* offset */
219 1.1 gdamore &rb_rage_regs3_table, /* parent */
220 1.1 gdamore NULL, /* validate */
221 1.1 gdamore rb_find_asic_table, /* find */
222 1.1 gdamore };
223 1.1 gdamore
224 1.1 gdamore static struct rb_table *rb_tables[] = {
225 1.1 gdamore &rb_rage_regs1_table,
226 1.1 gdamore &rb_rage_regs2_table,
227 1.1 gdamore &rb_dyn_clock_table,
228 1.1 gdamore &rb_pll_init_table,
229 1.1 gdamore &rb_mem_config_table,
230 1.1 gdamore &rb_mem_reset_table,
231 1.1 gdamore &rb_short_mem_reset_table,
232 1.1 gdamore &rb_rage_regs3_table,
233 1.1 gdamore &rb_rage_regs4_table,
234 1.1 gdamore NULL
235 1.1 gdamore };
236 1.1 gdamore
237 1.1 gdamore void
238 1.1 gdamore rb_validate(struct radeonfb_softc *sc, struct rb_table *tp)
239 1.1 gdamore {
240 1.1 gdamore uint8_t rev;
241 1.1 gdamore
242 1.1 gdamore rev = GETBIOS8(sc, tp->offset - 1);
243 1.1 gdamore
244 1.1 gdamore if (rev > MAX_REVISION) {
245 1.1 gdamore DPRINTF(("%s: bad rev %x of %s\n", XNAME(sc), rev, tp->name));
246 1.1 gdamore tp->offset = 0;
247 1.1 gdamore return;
248 1.1 gdamore }
249 1.1 gdamore
250 1.1 gdamore if (tp->offset < MIN_OFFSET) {
251 1.1 gdamore DPRINTF(("%s: wrong pointer to %s!\n", XNAME(sc), tp->name));
252 1.1 gdamore tp->offset = 0;
253 1.1 gdamore return;
254 1.1 gdamore }
255 1.1 gdamore }
256 1.1 gdamore
257 1.1 gdamore uint16_t
258 1.1 gdamore rb_find_asic_table(struct radeonfb_softc *sc, struct rb_table *tp)
259 1.1 gdamore {
260 1.1 gdamore uint16_t offset;
261 1.1 gdamore uint8_t c;
262 1.1 gdamore
263 1.1 gdamore if ((offset = tp->offset) != 0) {
264 1.1 gdamore while ((c = GETBIOS8(sc, offset + 1)) != 0) {
265 1.1 gdamore if (c & 0x40)
266 1.1 gdamore offset += 10;
267 1.1 gdamore else if (c & 0x80)
268 1.1 gdamore offset += 4;
269 1.1 gdamore else
270 1.1 gdamore offset += 6;
271 1.1 gdamore }
272 1.1 gdamore return offset + 2;
273 1.1 gdamore }
274 1.1 gdamore return 0;
275 1.1 gdamore }
276 1.1 gdamore
277 1.1 gdamore uint16_t
278 1.1 gdamore rb_find_mem_reset_table(struct radeonfb_softc *sc, struct rb_table *tp)
279 1.1 gdamore {
280 1.1 gdamore uint16_t offset;
281 1.1 gdamore
282 1.1 gdamore if ((offset = tp->offset) != 0) {
283 1.1 gdamore while (GETBIOS8(sc, offset))
284 1.1 gdamore offset++;
285 1.1 gdamore offset++;
286 1.1 gdamore return offset + 2; /* skip table revision and mask */
287 1.1 gdamore }
288 1.1 gdamore return 0;
289 1.1 gdamore }
290 1.1 gdamore
291 1.1 gdamore uint16_t
292 1.1 gdamore rb_find_short_mem_reset_table(struct radeonfb_softc *sc, struct rb_table *tp)
293 1.1 gdamore {
294 1.1 gdamore
295 1.1 gdamore if ((tp->offset != 0) && (GETBIOS8(sc, tp->offset - 2) <= 64))
296 1.1 gdamore return (tp->offset + GETBIOS8(sc, tp->offset - 3));
297 1.1 gdamore
298 1.1 gdamore return 0;
299 1.1 gdamore }
300 1.1 gdamore
301 1.1 gdamore /* helper commands */
302 1.1 gdamore void
303 1.1 gdamore rb_wait_mc_busy_mask(struct radeonfb_softc *sc, uint16_t count)
304 1.1 gdamore {
305 1.1 gdamore DPRINTF(("WAIT_MC_BUSY_MASK: %d ", count));
306 1.1 gdamore while (count--) {
307 1.1 gdamore if (!(radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL) &
308 1.6 macallan RADEON_MC_BUSY))
309 1.1 gdamore break;
310 1.1 gdamore }
311 1.1 gdamore DPRINTF(("%d\n", count));
312 1.1 gdamore }
313 1.1 gdamore
314 1.1 gdamore void
315 1.1 gdamore rb_wait_mem_pwrup_complete(struct radeonfb_softc *sc, uint16_t count)
316 1.1 gdamore {
317 1.1 gdamore DPRINTF(("WAIT_MEM_PWRUP_COMPLETE: %d ", count));
318 1.1 gdamore while (count--) {
319 1.1 gdamore if ((radeonfb_getindex(sc, RADEON_MEM_STR_CNTL) &
320 1.1 gdamore RADEON_MEM_PWRUP_COMPLETE) ==
321 1.1 gdamore RADEON_MEM_PWRUP_COMPLETE)
322 1.1 gdamore break;
323 1.1 gdamore }
324 1.1 gdamore DPRINTF(("%d\n", count));
325 1.1 gdamore }
326 1.1 gdamore
327 1.1 gdamore void
328 1.1 gdamore rb_wait_dll_ready_mask(struct radeonfb_softc *sc, uint16_t count)
329 1.1 gdamore {
330 1.1 gdamore DPRINTF(("WAIT_DLL_READY_MASK: %d ", count));
331 1.1 gdamore while (count--) {
332 1.1 gdamore if (radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL) &
333 1.6 macallan RADEON_DLL_READY)
334 1.1 gdamore break;
335 1.1 gdamore }
336 1.1 gdamore DPRINTF(("%d\n", count));
337 1.1 gdamore }
338 1.1 gdamore
339 1.1 gdamore void
340 1.1 gdamore rb_wait_chk_set_clk_pwrmgt_cntl24(struct radeonfb_softc *sc)
341 1.1 gdamore {
342 1.1 gdamore uint32_t pmc;
343 1.1 gdamore DPRINTF(("WAIT CHK_SET_CLK_PWRMGT_CNTL24\n"));
344 1.1 gdamore pmc = radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL);
345 1.1 gdamore
346 1.1 gdamore if (pmc & RADEON_CLK_PWRMGT_CNTL24) {
347 1.1 gdamore radeonfb_maskpll(sc, RADEON_MCLK_CNTL, 0xFFFF0000,
348 1.1 gdamore RADEON_SET_ALL_SRCS_TO_PCI);
349 1.1 gdamore delay(10000);
350 1.1 gdamore radeonfb_putpll(sc, RADEON_CLK_PWRMGT_CNTL,
351 1.1 gdamore pmc & ~RADEON_CLK_PWRMGT_CNTL24);
352 1.1 gdamore delay(10000);
353 1.1 gdamore }
354 1.1 gdamore }
355 1.1 gdamore
356 1.1 gdamore /*
357 1.1 gdamore * Block initialization routines. These take action based on data in
358 1.1 gdamore * the tables.
359 1.1 gdamore */
360 1.1 gdamore int
361 1.1 gdamore rb_load_init_block(struct radeonfb_softc *sc, struct rb_table *tp)
362 1.1 gdamore {
363 1.1 gdamore uint16_t offset;
364 1.1 gdamore uint16_t value;
365 1.1 gdamore
366 1.1 gdamore if ((tp == NULL) || ((offset = tp->offset) == 0))
367 1.1 gdamore return 1;
368 1.1 gdamore
369 1.1 gdamore DPRINTF(("%s: load_init_block processing %s\n", XNAME(sc), tp->name));
370 1.1 gdamore while ((value = GETBIOS16(sc, offset)) != 0) {
371 1.1 gdamore uint16_t flag = value & TABLE_ENTRY_FLAG_MASK;
372 1.1 gdamore uint16_t index = value & TABLE_ENTRY_INDEX_MASK;
373 1.1 gdamore uint8_t command = value & TABLE_ENTRY_COMMAND_MASK;
374 1.1 gdamore uint32_t ormask;
375 1.1 gdamore uint32_t andmask;
376 1.1 gdamore uint16_t count;
377 1.1 gdamore
378 1.1 gdamore offset += 2;
379 1.1 gdamore
380 1.1 gdamore switch (flag) {
381 1.1 gdamore case TABLE_FLAG_WRITE_INDEXED:
382 1.1 gdamore DPRINTF(("WRITE INDEXED: %x %x\n",
383 1.1 gdamore index, (uint32_t)GETBIOS32(sc, offset)));
384 1.1 gdamore radeonfb_putindex(sc, index, GETBIOS32(sc, offset));
385 1.1 gdamore offset += 4;
386 1.1 gdamore break;
387 1.1 gdamore
388 1.1 gdamore case TABLE_FLAG_WRITE_DIRECT:
389 1.1 gdamore DPRINTF(("WRITE DIRECT: %x %x\n",
390 1.1 gdamore index, (uint32_t)GETBIOS32(sc, offset)));
391 1.1 gdamore radeonfb_put32(sc, index, GETBIOS32(sc, offset));
392 1.1 gdamore offset += 4;
393 1.1 gdamore break;
394 1.1 gdamore
395 1.1 gdamore case TABLE_FLAG_MASK_INDEXED:
396 1.1 gdamore andmask = GETBIOS32(sc, offset);
397 1.1 gdamore offset += 4;
398 1.1 gdamore ormask = GETBIOS32(sc, offset);
399 1.1 gdamore offset += 4;
400 1.1 gdamore DPRINTF(("MASK INDEXED: %x %x %x\n",
401 1.1 gdamore index, andmask, ormask));
402 1.1 gdamore radeonfb_maskindex(sc, index, andmask, ormask);
403 1.1 gdamore break;
404 1.1 gdamore
405 1.1 gdamore case TABLE_FLAG_MASK_DIRECT:
406 1.1 gdamore andmask = GETBIOS32(sc, offset);
407 1.1 gdamore offset += 4;
408 1.1 gdamore ormask = GETBIOS32(sc, offset);
409 1.1 gdamore offset += 4;
410 1.1 gdamore DPRINTF(("MASK DIRECT: %x %x %x\n",
411 1.1 gdamore index, andmask, ormask));
412 1.1 gdamore radeonfb_mask32(sc, index, andmask, ormask);
413 1.1 gdamore break;
414 1.1 gdamore
415 1.1 gdamore case TABLE_FLAG_DELAY:
416 1.1 gdamore /* in the worst case, this would be 16msec */
417 1.1 gdamore count = GETBIOS16(sc, offset);
418 1.1 gdamore DPRINTF(("DELAY: %d\n", count));
419 1.1 gdamore delay(count);
420 1.1 gdamore offset += 2;
421 1.1 gdamore break;
422 1.1 gdamore
423 1.1 gdamore case TABLE_FLAG_SCOMMAND:
424 1.1 gdamore DPRINTF(("SCOMMAND %x\n", command));
425 1.1 gdamore switch (command) {
426 1.1 gdamore
427 1.1 gdamore case TABLE_SCOMMAND_WAIT_MC_BUSY_MASK:
428 1.1 gdamore count = GETBIOS16(sc, offset);
429 1.1 gdamore rb_wait_mc_busy_mask(sc, count);
430 1.1 gdamore break;
431 1.1 gdamore
432 1.1 gdamore case TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE:
433 1.1 gdamore count = GETBIOS16(sc, offset);
434 1.1 gdamore rb_wait_mem_pwrup_complete(sc, count);
435 1.1 gdamore break;
436 1.1 gdamore
437 1.1 gdamore }
438 1.1 gdamore offset += 2;
439 1.1 gdamore break;
440 1.1 gdamore }
441 1.1 gdamore }
442 1.1 gdamore return 0;
443 1.1 gdamore }
444 1.1 gdamore
445 1.1 gdamore int
446 1.1 gdamore rb_load_pll_block(struct radeonfb_softc *sc, struct rb_table *tp)
447 1.1 gdamore {
448 1.1 gdamore uint16_t offset;
449 1.1 gdamore uint8_t index;
450 1.1 gdamore uint8_t shift;
451 1.1 gdamore uint32_t andmask;
452 1.1 gdamore uint32_t ormask;
453 1.1 gdamore
454 1.1 gdamore if ((tp == NULL) || ((offset = tp->offset) == 0))
455 1.1 gdamore return 1;
456 1.1 gdamore
457 1.1 gdamore DPRINTF(("%s: load_pll_block processing %s\n", XNAME(sc), tp->name));
458 1.1 gdamore while ((index = GETBIOS8(sc, offset)) != 0) {
459 1.1 gdamore offset++;
460 1.1 gdamore
461 1.1 gdamore switch (index & PLL_FLAG_MASK) {
462 1.1 gdamore case PLL_FLAG_WAIT:
463 1.1 gdamore switch (index & PLL_INDEX_MASK) {
464 1.1 gdamore case PLL_WAIT_150MKS:
465 1.1 gdamore delay(150);
466 1.1 gdamore break;
467 1.1 gdamore case PLL_WAIT_5MS:
468 1.1 gdamore /* perhaps this should be tsleep? */
469 1.1 gdamore delay(5000);
470 1.1 gdamore break;
471 1.1 gdamore
472 1.1 gdamore case PLL_WAIT_MC_BUSY_MASK:
473 1.1 gdamore rb_wait_mc_busy_mask(sc, 1000);
474 1.1 gdamore break;
475 1.1 gdamore
476 1.1 gdamore case PLL_WAIT_DLL_READY_MASK:
477 1.1 gdamore rb_wait_dll_ready_mask(sc, 1000);
478 1.1 gdamore break;
479 1.1 gdamore
480 1.1 gdamore case PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24:
481 1.1 gdamore rb_wait_chk_set_clk_pwrmgt_cntl24(sc);
482 1.1 gdamore break;
483 1.1 gdamore }
484 1.1 gdamore break;
485 1.1 gdamore
486 1.1 gdamore case PLL_FLAG_MASK_BYTE:
487 1.1 gdamore shift = GETBIOS8(sc, offset) * 8;
488 1.1 gdamore offset++;
489 1.1 gdamore
490 1.1 gdamore andmask =
491 1.1 gdamore (((uint32_t)GETBIOS8(sc, offset)) << shift) |
492 1.1 gdamore ~((uint32_t)0xff << shift);
493 1.1 gdamore offset++;
494 1.1 gdamore
495 1.1 gdamore ormask = ((uint32_t)GETBIOS8(sc, offset)) << shift;
496 1.1 gdamore offset++;
497 1.1 gdamore
498 1.1 gdamore DPRINTF(("PLL_MASK_BYTE %u %u %x %x\n", index,
499 1.1 gdamore shift, andmask, ormask));
500 1.1 gdamore radeonfb_maskpll(sc, index, andmask, ormask);
501 1.1 gdamore break;
502 1.1 gdamore
503 1.1 gdamore case PLL_FLAG_WRITE:
504 1.1 gdamore DPRINTF(("PLL_WRITE %u %x\n", index,
505 1.1 gdamore GETBIOS32(sc, offset)));
506 1.1 gdamore radeonfb_putpll(sc, index, GETBIOS32(sc, offset));
507 1.1 gdamore offset += 4;
508 1.1 gdamore break;
509 1.1 gdamore }
510 1.1 gdamore }
511 1.1 gdamore
512 1.1 gdamore return 0;
513 1.1 gdamore }
514 1.1 gdamore
515 1.1 gdamore int
516 1.1 gdamore rb_reset_sdram(struct radeonfb_softc *sc, struct rb_table *tp)
517 1.1 gdamore {
518 1.1 gdamore uint16_t offset;
519 1.1 gdamore uint8_t index;
520 1.1 gdamore
521 1.1 gdamore if ((tp == NULL) || ((offset = tp->offset) == 0))
522 1.1 gdamore return 1;
523 1.1 gdamore
524 1.1 gdamore DPRINTF(("%s: reset_sdram processing %s\n", XNAME(sc), tp->name));
525 1.1 gdamore
526 1.1 gdamore while ((index = GETBIOS8(sc, offset)) != 0xff) {
527 1.1 gdamore offset++;
528 1.1 gdamore if (index == 0x0f) {
529 1.1 gdamore rb_wait_mem_pwrup_complete(sc, 20000);
530 1.1 gdamore } else {
531 1.1 gdamore uint32_t ormask;
532 1.1 gdamore
533 1.1 gdamore ormask = GETBIOS16(sc, offset);
534 1.1 gdamore offset += 2;
535 1.1 gdamore
536 1.1 gdamore DPRINTF(("INDEX reg RADEON_MEM_SDRAM_MODE_REG %x %x\n",
537 1.1 gdamore RADEON_SDRAM_MODE_MASK, ormask));
538 1.1 gdamore radeonfb_maskindex(sc, RADEON_MEM_SDRAM_MODE_REG,
539 1.1 gdamore RADEON_SDRAM_MODE_MASK, ormask);
540 1.1 gdamore
541 1.1 gdamore ormask = (uint32_t)index << 24;
542 1.1 gdamore DPRINTF(("INDEX reg RADEON_MEM_SDRAM_MODE_REG %x %x\n",
543 1.1 gdamore RADEON_B3MEM_RESET_MASK, ormask));
544 1.1 gdamore radeonfb_maskindex(sc, RADEON_MEM_SDRAM_MODE_REG,
545 1.1 gdamore RADEON_B3MEM_RESET_MASK, ormask);
546 1.1 gdamore }
547 1.1 gdamore }
548 1.1 gdamore return 0;
549 1.1 gdamore }
550 1.1 gdamore
551 1.1 gdamore /*
552 1.1 gdamore * Master entry point to parse and act on table data.
553 1.1 gdamore */
554 1.1 gdamore int
555 1.1 gdamore radeonfb_bios_init(struct radeonfb_softc *sc)
556 1.1 gdamore {
557 1.1 gdamore uint16_t revision;
558 1.1 gdamore uint16_t scratch;
559 1.1 gdamore int i;
560 1.1 gdamore struct rb_table *tp;
561 1.1 gdamore
562 1.1 gdamore if (!sc->sc_biossz)
563 1.1 gdamore return 1;
564 1.1 gdamore
565 1.1 gdamore scratch = GETBIOS16(sc, ROM_HEADER_OFFSET);
566 1.1 gdamore revision = GETBIOS8(sc, scratch);
567 1.1 gdamore DPRINTF(("%s: Bios Rev: %d\n", XNAME(sc), revision));
568 1.1 gdamore
569 1.1 gdamore
570 1.1 gdamore /* First parse pass -- locate tables */
571 1.1 gdamore for (i = 0; (tp = rb_tables[i]) != NULL; i++) {
572 1.1 gdamore
573 1.1 gdamore DPRINTF(("%s: parsing table %s\n", XNAME(sc), tp->name));
574 1.1 gdamore
575 1.1 gdamore if (tp->offset != 0) {
576 1.3 yamt uint16_t temp, offset;
577 1.1 gdamore
578 1.1 gdamore temp = GETBIOS16(sc, ROM_HEADER_OFFSET);
579 1.1 gdamore offset = GETBIOS16(sc, temp + tp->offset);
580 1.1 gdamore if (offset)
581 1.1 gdamore tp->offset = offset;
582 1.1 gdamore
583 1.1 gdamore } else {
584 1.1 gdamore tp->offset = tp->find(sc, tp->parent);
585 1.1 gdamore }
586 1.1 gdamore
587 1.1 gdamore if (tp->validate)
588 1.1 gdamore tp->validate(sc, tp);
589 1.1 gdamore
590 1.1 gdamore if (revision > SINGLE_TABLE_REVISION)
591 1.1 gdamore break;
592 1.1 gdamore }
593 1.1 gdamore
594 1.1 gdamore if (rb_rage_regs3_table.offset + 1 == rb_pll_init_table.offset) {
595 1.1 gdamore rb_rage_regs3_table.offset = 0;
596 1.1 gdamore rb_rage_regs4_table.offset = 0;
597 1.1 gdamore }
598 1.1 gdamore
599 1.1 gdamore if (rb_rage_regs1_table.offset)
600 1.1 gdamore rb_load_init_block(sc, &rb_rage_regs1_table);
601 1.1 gdamore
602 1.1 gdamore if (revision < SINGLE_TABLE_REVISION) {
603 1.1 gdamore if (rb_pll_init_table.offset)
604 1.1 gdamore rb_load_pll_block(sc, &rb_pll_init_table);
605 1.1 gdamore if (rb_rage_regs2_table.offset)
606 1.1 gdamore rb_load_init_block(sc, &rb_rage_regs2_table);
607 1.1 gdamore if (rb_rage_regs4_table.offset)
608 1.1 gdamore rb_load_init_block(sc, &rb_rage_regs4_table);
609 1.1 gdamore if (rb_mem_reset_table.offset)
610 1.1 gdamore rb_reset_sdram(sc, &rb_mem_reset_table);
611 1.1 gdamore if (rb_rage_regs3_table.offset)
612 1.1 gdamore rb_load_init_block(sc, &rb_rage_regs3_table);
613 1.1 gdamore if (rb_dyn_clock_table.offset)
614 1.1 gdamore rb_load_pll_block(sc, &rb_dyn_clock_table);
615 1.1 gdamore }
616 1.1 gdamore
617 1.1 gdamore DPRINTF(("%s: BIOS parse done\n", XNAME(sc)));
618 1.1 gdamore return 0;
619 1.1 gdamore }
620 1.1 gdamore
621 1.1 gdamore #endif
622