📄 radeon_pm.c
字号:
CLK_PWRMGT_CNTL__SPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__PPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__P2PLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__MCLK_TURNOFF| CLK_PWRMGT_CNTL__SCLK_TURNOFF| CLK_PWRMGT_CNTL__PCLK_TURNOFF| CLK_PWRMGT_CNTL__P2CLK_TURNOFF| CLK_PWRMGT_CNTL__TVPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN| CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE| CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK| CLK_PWRMGT_CNTL__CG_NO1_DEBUG_MASK ); clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN | CLK_PWRMGT_CNTL__DISP_PM; OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl); clk_pin_cntl = INPLL( pllCLK_PIN_CNTL); clk_pin_cntl &= ~CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND; /* because both INPLL and OUTPLL take the same lock, that's why. */ tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; OUTPLL( pllMCLK_MISC, tmp); /* AGP PLL control */ if (rinfo->family <= CHIP_FAMILY_RV280) { OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX } else { OUTREG(BUS_CNTL1, INREG(BUS_CNTL1)); OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000); } OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL) & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN)); clk_pin_cntl &= ~CLK_PIN_CNTL__CG_CLK_TO_OUTPIN; clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb; OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl); /* Solano2M */ OUTREG(AGP_CNTL, (INREG(AGP_CNTL) & ~(AGP_CNTL__MAX_IDLE_CLK_MASK)) | (0x20<<AGP_CNTL__MAX_IDLE_CLK__SHIFT)); /* ACPI mode */ /* because both INPLL and OUTPLL take the same lock, that's why. */ tmp = INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL; OUTPLL( pllPLL_PWRMGT_CNTL, tmp); disp_mis_cntl = INREG(DISP_MISC_CNTL); disp_mis_cntl &= ~( DISP_MISC_CNTL__SOFT_RESET_GRPH_PP | DISP_MISC_CNTL__SOFT_RESET_SUBPIC_PP | DISP_MISC_CNTL__SOFT_RESET_OV0_PP | DISP_MISC_CNTL__SOFT_RESET_GRPH_SCLK| DISP_MISC_CNTL__SOFT_RESET_SUBPIC_SCLK| DISP_MISC_CNTL__SOFT_RESET_OV0_SCLK| DISP_MISC_CNTL__SOFT_RESET_GRPH2_PP| DISP_MISC_CNTL__SOFT_RESET_GRPH2_SCLK| DISP_MISC_CNTL__SOFT_RESET_LVDS| DISP_MISC_CNTL__SOFT_RESET_TMDS| DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS| DISP_MISC_CNTL__SOFT_RESET_TV); OUTREG(DISP_MISC_CNTL, disp_mis_cntl); disp_pwr_man = INREG(DISP_PWR_MAN); disp_pwr_man &= ~( DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN | DISP_PWR_MAN__DISP_PWR_MAN_DPMS_MASK| DISP_PWR_MAN__DISP_D3_RST| DISP_PWR_MAN__DISP_D3_REG_RST ); disp_pwr_man |= DISP_PWR_MAN__DISP_D3_GRPH_RST| DISP_PWR_MAN__DISP_D3_SUBPIC_RST| DISP_PWR_MAN__DISP_D3_OV0_RST| DISP_PWR_MAN__DISP_D1D2_GRPH_RST| DISP_PWR_MAN__DISP_D1D2_SUBPIC_RST| DISP_PWR_MAN__DISP_D1D2_OV0_RST| DISP_PWR_MAN__DIG_TMDS_ENABLE_RST| DISP_PWR_MAN__TV_ENABLE_RST| // DISP_PWR_MAN__AUTO_PWRUP_EN| 0; OUTREG(DISP_PWR_MAN, disp_pwr_man); clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL); pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL) ; clk_pin_cntl = INPLL( pllCLK_PIN_CNTL); disp_pwr_man = INREG(DISP_PWR_MAN); /* D2 */ clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__DISP_PM; pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__MOBILE_SU | PLL_PWRMGT_CNTL__SU_SCLK_USE_BCLK; clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb; disp_pwr_man &= ~(DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN_MASK | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN_MASK); OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl); OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl); OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl); OUTREG(DISP_PWR_MAN, disp_pwr_man); /* disable display request & disable display */ OUTREG( CRTC_GEN_CNTL, (INREG( CRTC_GEN_CNTL) & ~CRTC_GEN_CNTL__CRTC_EN) | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B); OUTREG( CRTC2_GEN_CNTL, (INREG( CRTC2_GEN_CNTL) & ~CRTC2_GEN_CNTL__CRTC2_EN) | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B); mdelay(17); }static void radeon_pm_yclk_mclk_sync(struct radeonfb_info *rinfo){ u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1; mc_chp_io_cntl_a1 = INMC( rinfo, ixMC_CHP_IO_CNTL_A1) & ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK; mc_chp_io_cntl_b1 = INMC( rinfo, ixMC_CHP_IO_CNTL_B1) & ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK; OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1 | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT)); OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1 | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT)); OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1); OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1); mdelay( 1);}static void radeon_pm_yclk_mclk_sync_m10(struct radeonfb_info *rinfo){ u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1; mc_chp_io_cntl_a1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1) & ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK; mc_chp_io_cntl_b1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1) & ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK; OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1 | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT)); OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1 | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT)); OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1); OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1); mdelay( 1);}static void radeon_pm_program_mode_reg(struct radeonfb_info *rinfo, u16 value, u8 delay_required){ u32 mem_sdram_mode; mem_sdram_mode = INREG( MEM_SDRAM_MODE_REG); mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK; mem_sdram_mode |= (value<<MEM_SDRAM_MODE_REG__MEM_MODE_REG__SHIFT) | MEM_SDRAM_MODE_REG__MEM_CFG_TYPE; OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); if (delay_required >= 2) mdelay(1); mem_sdram_mode |= MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET; OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); if (delay_required >= 2) mdelay(1); mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET; OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); if (delay_required >= 2) mdelay(1); if (delay_required) { do { if (delay_required >= 2) mdelay(1); } while ((INREG(MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A | MC_STATUS__MEM_PWRUP_COMPL_B)) == 0); }}static void radeon_pm_m10_program_mode_wait(struct radeonfb_info *rinfo){ int cnt; for (cnt = 0; cnt < 100; ++cnt) { mdelay(1); if (INREG(MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A | MC_STATUS__MEM_PWRUP_COMPL_B)) break; }}static void radeon_pm_enable_dll(struct radeonfb_info *rinfo){ #define DLL_RESET_DELAY 5#define DLL_SLEEP_DELAY 1 u32 cko = INPLL(pllMDLL_CKO) | MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOA_RESET; u32 cka = INPLL(pllMDLL_RDCKA) | MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP | MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET; u32 ckb = INPLL(pllMDLL_RDCKB) | MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP | MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET; /* Setting up the DLL range for write */ OUTPLL(pllMDLL_CKO, cko); OUTPLL(pllMDLL_RDCKA, cka); OUTPLL(pllMDLL_RDCKB, ckb); mdelay(DLL_RESET_DELAY*2); cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP); OUTPLL(pllMDLL_CKO, cko); mdelay(DLL_SLEEP_DELAY); cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET); OUTPLL(pllMDLL_CKO, cko); mdelay(DLL_RESET_DELAY); cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP); OUTPLL(pllMDLL_RDCKA, cka); mdelay(DLL_SLEEP_DELAY); cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET); OUTPLL(pllMDLL_RDCKA, cka); mdelay(DLL_RESET_DELAY); ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP); OUTPLL(pllMDLL_RDCKB, ckb); mdelay(DLL_SLEEP_DELAY); ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET); OUTPLL(pllMDLL_RDCKB, ckb); mdelay(DLL_RESET_DELAY);#undef DLL_RESET_DELAY#undef DLL_SLEEP_DELAY}static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo){ u32 dll_value; u32 dll_sleep_mask = 0; u32 dll_reset_mask = 0; u32 mc;#define DLL_RESET_DELAY 5#define DLL_SLEEP_DELAY 1 OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]); mc = INREG(MC_CNTL); /* Check which channels are enabled */ switch (mc & 0x3) { case 1: if (mc & 0x4) break; case 2: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKB_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKB_RESET; case 0: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKA_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKA_RESET; } switch (mc & 0x3) { case 1: if (!(mc & 0x4)) break; case 2: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKD_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKD_RESET; dll_sleep_mask |= MDLL_R300_RDCK__MRDCKC_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKC_RESET; } dll_value = INPLL(pllMDLL_RDCKA); /* Power Up */ dll_value &= ~(dll_sleep_mask); OUTPLL(pllMDLL_RDCKA, dll_value); mdelay( DLL_SLEEP_DELAY); dll_value &= ~(dll_reset_mask); OUTPLL(pllMDLL_RDCKA, dll_value); mdelay( DLL_RESET_DELAY); #undef DLL_RESET_DELAY #undef DLL_SLEEP_DELAY}static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo){ u32 crtcGenCntl, crtcGenCntl2, memRefreshCntl, crtc_more_cntl, fp_gen_cntl, fp2_gen_cntl; crtcGenCntl = INREG( CRTC_GEN_CNTL); crtcGenCntl2 = INREG( CRTC2_GEN_CNTL); crtc_more_cntl = INREG( CRTC_MORE_CNTL); fp_gen_cntl = INREG( FP_GEN_CNTL); fp2_gen_cntl = INREG( FP2_GEN_CNTL); OUTREG( CRTC_MORE_CNTL, 0); OUTREG( FP_GEN_CNTL, 0); OUTREG( FP2_GEN_CNTL,0); OUTREG( CRTC_GEN_CNTL, (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) ); OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) ); /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */ if (rinfo->family == CHIP_FAMILY_RV350) { u32 sdram_mode_reg = rinfo->save_regs[35]; static u32 default_mrtable[] = { 0x21320032, 0x21321000, 0xa1321000, 0x21321000, 0xffffffff, 0x21320032, 0xa1320032, 0x21320032, 0xffffffff, 0x21321002, 0xa1321002, 0x21321002, 0xffffffff, 0x21320132, 0xa1320132, 0x21320132, 0xffffffff, 0x21320032, 0xa1320032, 0x21320032, 0xffffffff, 0x31320032 }; u32 *mrtable = default_mrtable; int i, mrtable_size = ARRAY_SIZE(default_mrtable); mdelay(30); /* Disable refresh */ memRefreshCntl = INREG( MEM_REFRESH_CNTL) & ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS; OUTREG( MEM_REFRESH_CNTL, memRefreshCntl | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); /* Configure and enable M & SPLLs */ radeon_pm_enable_dll_m10(rinfo); radeon_pm_yclk_mclk_sync_m10(rinfo);#ifdef CONFIG_PPC_OF if (rinfo->of_node != NULL) { int size; mrtable = (u32 *)get_property(rinfo->of_node, "ATY,MRT", &size); if (mrtable) mrtable_size = size >> 2; else mrtable = default_mrtable; }#endif /* CONFIG_PPC_OF */ /* Program the SDRAM */ sdram_mode_reg = mrtable[0]; OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg); for (i = 0; i < mrtable_size; i++) { if (mrtable[i] == 0xffffffffu) radeon_pm_m10_program_mode_wait(rinfo); else { sdram_mode_reg &= ~(MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE | MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET); sdram_mode_reg |= mrtable[i]; OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg); mdelay(1); } } /* Restore memory refresh */ OUTREG(MEM_REFRESH_CNTL, memRefreshCntl); mdelay(30); } /* Here come the desktop RV200 "QW" card */ else if (!rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV200) { /* Disable refresh */ memRefreshCntl = INREG( MEM_REFRESH_CNTL) & ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS; OUTREG(MEM_REFRESH_CNTL, memRefreshCntl | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); mdelay(30); /* Reset memory */ OUTREG(MEM_SDRAM_MODE_REG, INREG( MEM_SDRAM_MODE_REG) & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); radeon_pm_program_mode_reg(rinfo, 0x2002, 2); radeon_pm_program_mode_reg(rinfo, 0x0132, 2); radeon_pm_program_mode_reg(rinfo, 0x0032, 2); OUTREG(MEM_SDRAM_MODE_REG, INREG(MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); OUTREG( MEM_REFRESH_CNTL, memRefreshCntl); } /* The M6 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -