1 /*
2 Copyright (c) 2002/03, Thomas Kurschel
3
4
5 Part of Radeon driver and accelerant
6
7 Basic access of PLL registers
8 */
9
10 #include "radeon_interface.h"
11 #include "pll_access.h"
12 #include "pll_regs.h"
13 #include "crtc_regs.h"
14 #include "utils.h"
15
RADEONPllErrataAfterIndex(vuint8 * regs,radeon_type asic)16 void RADEONPllErrataAfterIndex( vuint8 *regs, radeon_type asic )
17 {
18 if (! ((asic == rt_rv200) || (asic == rt_rs200)))
19 return;
20
21 /* This workaround is necessary on rv200 and RS200 or PLL
22 * reads may return garbage (among others...)
23 */
24 INREG( regs, RADEON_CLOCK_CNTL_DATA);
25 INREG( regs, RADEON_CRTC_GEN_CNTL);
26 }
27
RADEONPllErrataAfterData(vuint8 * regs,radeon_type asic)28 void RADEONPllErrataAfterData( vuint8 *regs, radeon_type asic )
29 {
30 uint32 save, tmp;
31
32 /* This workarounds is necessary on RV100, RS100 and RS200 chips
33 * or the chip could hang on a subsequent access
34 */
35 if ((asic == rt_rv100) || (asic == rt_rs100) || (asic == rt_rs200))
36 {
37 /* we can't deal with posted writes here ... */
38 snooze(5000);
39 }
40
41 /* This function is required to workaround a hardware bug in some (all?)
42 * revisions of the R300. This workaround should be called after every
43 * CLOCK_CNTL_INDEX register access. If not, register reads afterward
44 * may not be correct.
45 */
46
47 if( asic != rt_r300 )
48 return;
49
50 save = INREG( regs, RADEON_CLOCK_CNTL_INDEX );
51 tmp = save & ~(0x3f | RADEON_PLL_WR_EN);
52 OUTREG( regs, RADEON_CLOCK_CNTL_INDEX, tmp );
53 tmp = INREG( regs, RADEON_CLOCK_CNTL_DATA );
54 OUTREG( regs, RADEON_CLOCK_CNTL_INDEX, save );
55
56 }
57
58 // read value "val" from PLL-register "addr"
Radeon_INPLL(vuint8 * regs,radeon_type asic,int addr)59 uint32 Radeon_INPLL( vuint8 *regs, radeon_type asic, int addr )
60 {
61 uint32 res;
62
63 OUTREG8( regs, RADEON_CLOCK_CNTL_INDEX, addr & 0x3f );
64 RADEONPllErrataAfterIndex(regs, asic);
65 res = INREG( regs, RADEON_CLOCK_CNTL_DATA );
66 RADEONPllErrataAfterData(regs, asic);
67 return res;
68 }
69
70 // write value "val" to PLL-register "addr"
Radeon_OUTPLL(vuint8 * regs,radeon_type asic,uint8 addr,uint32 val)71 void Radeon_OUTPLL( vuint8 *regs, radeon_type asic, uint8 addr, uint32 val )
72 {
73 (void)asic;
74
75 OUTREG8( regs, RADEON_CLOCK_CNTL_INDEX, ((addr & 0x3f ) |
76 RADEON_PLL_WR_EN));
77 RADEONPllErrataAfterIndex(regs, asic);
78 OUTREG( regs, RADEON_CLOCK_CNTL_DATA, val );
79 RADEONPllErrataAfterData(regs, asic);
80
81 }
82
83 // write "val" to PLL-register "addr" keeping bits "mask"
Radeon_OUTPLLP(vuint8 * regs,radeon_type asic,uint8 addr,uint32 val,uint32 mask)84 void Radeon_OUTPLLP( vuint8 *regs, radeon_type asic, uint8 addr,
85 uint32 val, uint32 mask )
86 {
87 uint32 tmp = Radeon_INPLL( regs, asic, addr );
88 tmp &= mask;
89 tmp |= val;
90 Radeon_OUTPLL( regs, asic, addr, tmp );
91 }
92