From: Benjamin Herrenschmidt So you remember all those weird lockups at boot that happened in late 2.6.11-rc with radeonfb. I posted a "workaround" which just moved code around a bit and it appeared to work. I finally got some real infos about the problem from ATI, and it seems my "workaround" is not very safe and there are other potential issues realted to HW bugs when accessing the PLL registers. This patch implements all of these workarounds (and puts back the code where it was before my previous fix). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton --- 25-akpm/drivers/video/aty/radeon_base.c | 32 ++++++++-- 25-akpm/drivers/video/aty/radeon_monitor.c | 10 ++- 25-akpm/drivers/video/aty/radeon_pm.c | 26 ++++++-- 25-akpm/drivers/video/aty/radeonfb.h | 86 +++++++++++------------------ 4 files changed, 88 insertions(+), 66 deletions(-) diff -puN drivers/video/aty/radeon_base.c~radeonfb-pll-access-workaround drivers/video/aty/radeon_base.c --- 25/drivers/video/aty/radeon_base.c~radeonfb-pll-access-workaround 2005-03-07 22:43:18.000000000 -0800 +++ 25-akpm/drivers/video/aty/radeon_base.c 2005-03-07 22:43:18.000000000 -0800 @@ -530,7 +530,11 @@ static int __devinit radeon_probe_pll_pa break; } + radeon_pll_workaround_before(rinfo); ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3; + radeon_pll_workaround_after(rinfo); + if (rinfo->R300_cg_workaround) + R300_cg_workardound(rinfo); n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff); m = (INPLL(PPLL_REF_DIV) & 0x3ff); @@ -1169,7 +1173,11 @@ static void radeon_save_state (struct ra save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL); /* PLL regs */ + radeon_pll_workaround_before(rinfo); save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f; + radeon_pll_workaround_after(rinfo); + if (rinfo->R300_cg_workaround) + R300_cg_workardound(rinfo); save->ppll_div_3 = INPLL(PPLL_DIV_3); save->ppll_ref_div = INPLL(PPLL_REF_DIV); } @@ -1196,9 +1204,13 @@ static void radeon_write_pll_regs(struct /* We still have to force a switch to selected PPLL div thanks to * an XFree86 driver bug which will switch it away in some cases * even when using UseFDev */ + radeon_pll_workaround_before(rinfo); OUTREGP(CLOCK_CNTL_INDEX, mode->clk_cntl_index & PPLL_DIV_SEL_MASK, ~PPLL_DIV_SEL_MASK); + radeon_pll_workaround_after(rinfo); + if (rinfo->R300_cg_workaround) + R300_cg_workardound(rinfo); return; } } @@ -1212,9 +1224,13 @@ static void radeon_write_pll_regs(struct ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN)); /* Switch to selected PPLL divider */ + radeon_pll_workaround_before(rinfo); OUTREGP(CLOCK_CNTL_INDEX, mode->clk_cntl_index & PPLL_DIV_SEL_MASK, ~PPLL_DIV_SEL_MASK); + radeon_pll_workaround_after(rinfo); + if (rinfo->R300_cg_workaround) + R300_cg_workardound(rinfo); /* Set PPLL ref. div */ if (rinfo->family == CHIP_FAMILY_R300 || @@ -2360,6 +2376,15 @@ static int radeonfb_pci_register (struct radeon_save_state (rinfo, &rinfo->init_state); memcpy(&rinfo->state, &rinfo->init_state, sizeof(struct radeon_regs)); + /* Setup Power Management capabilities */ + if (default_dynclk < -1) { + /* -2 is special: means ON on mobility chips and do not + * change on others + */ + radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1); + } else + radeonfb_pm_init(rinfo, default_dynclk); + pci_set_drvdata(pdev, info); /* Register with fbdev layer */ @@ -2370,13 +2395,6 @@ static int radeonfb_pci_register (struct goto err_unmap_fb; } - /* Setup Power Management capabilities */ - if (default_dynclk < -1) { - /* -2 is special: means ON on mobility chips and do not change on others */ - radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1); - } else - radeonfb_pm_init(rinfo, default_dynclk); - #ifdef CONFIG_MTRR rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys, rinfo->video_ram, diff -puN drivers/video/aty/radeonfb.h~radeonfb-pll-access-workaround drivers/video/aty/radeonfb.h --- 25/drivers/video/aty/radeonfb.h~radeonfb-pll-access-workaround 2005-03-07 22:43:18.000000000 -0800 +++ 25-akpm/drivers/video/aty/radeonfb.h 2005-03-07 22:43:18.000000000 -0800 @@ -22,11 +22,6 @@ #include