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
16void 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
28void 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"
59uint32 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"
71void 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"
84void 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