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 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 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" 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" 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" 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