^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/kyro/STG4000InitDevice.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2000 Imagination Technologies Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2002 STMicroelectronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "STG4000Reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "STG4000Interface.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* SDRAM fixed settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SDRAM_CFG_0 0x49A1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define SDRAM_CFG_1 0xA732
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SDRAM_CFG_2 0x31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SDRAM_ARB_CFG 0xA0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SDRAM_REFRESH 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Reset values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PMX2_SOFTRESET_DAC_RST 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define PMX2_SOFTRESET_C1_RST 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PMX2_SOFTRESET_C2_RST 0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define PMX2_SOFTRESET_3D_RST 0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define PMX2_SOFTRESET_VIDIN_RST 0x0020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define PMX2_SOFTRESET_TLB_RST 0x0040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define PMX2_SOFTRESET_SD_RST 0x0080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define PMX2_SOFTRESET_VGA_RST 0x0100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define PMX2_SOFTRESET_ROM_RST 0x0200 /* reserved bit, do not reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define PMX2_SOFTRESET_TA_RST 0x0400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define PMX2_SOFTRESET_REG_RST 0x4000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define PMX2_SOFTRESET_ALL 0x7fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* Core clock freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CORE_PLL_FREQ 1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Reference Clock freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define REF_FREQ 14318
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* PCI Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static u16 CorePllControl = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define PCI_CONFIG_SUBSYS_ID 0x2e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* Misc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define CORE_PLL_MODE_REG_0_7 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define CORE_PLL_MODE_REG_8_15 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define CORE_PLL_MODE_CONFIG_REG 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define DAC_PLL_CONFIG_REG 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define STG_MAX_VCO 500000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define STG_MIN_VCO 100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* PLL Clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define STG4K3_PLL_SCALER 8 /* scale numbers by 2^8 for fixed point calc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define STG4K3_PLL_MIN_R 2 /* Minimum multiplier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define STG4K3_PLL_MAX_R 33 /* Max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define STG4K3_PLL_MIN_F 2 /* Minimum divisor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define STG4K3_PLL_MAX_F 513 /* Max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define STG4K3_PLL_MIN_OD 0 /* Min output divider (shift) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define STG4K3_PLL_MAX_OD 2 /* Max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define STG4K3_PLL_MIN_VCO_SC (100000000 >> STG4K3_PLL_SCALER) /* Min VCO rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define STG4K3_PLL_MAX_VCO_SC (500000000 >> STG4K3_PLL_SCALER) /* Max VCO rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define STG4K3_PLL_MINR_VCO_SC (100000000 >> STG4K3_PLL_SCALER) /* Min VCO rate (restricted) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define STG4K3_PLL_MAXR_VCO_SC (500000000 >> STG4K3_PLL_SCALER) /* Max VCO rate (restricted) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define STG4K3_PLL_MINR_VCO 100000000 /* Min VCO rate (restricted) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define STG4K3_PLL_MAX_VCO 500000000 /* Max VCO rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define STG4K3_PLL_MAXR_VCO 500000000 /* Max VCO rate (restricted) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define OS_DELAY(X) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) volatile u32 i,count=0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) for(i=0;i<X;i++) count++; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static u32 InitSDRAMRegisters(volatile STG4000REG __iomem *pSTGReg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u32 dwSubSysID, u32 dwRevID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u32 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u32 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u32 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 adwSDRAMRsh[] = { 36, 39, 40 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 adwChipSpeed[] = { 110, 120, 125 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u32 dwMemTypeIdx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 dwChipSpeedIdx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Get memory tpye and chip speed indexs from the SubSysDevID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) dwMemTypeIdx = (dwSubSysID & 0x70) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dwChipSpeedIdx = (dwSubSysID & 0x180) >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (dwMemTypeIdx > 4 || dwChipSpeedIdx > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* Program SD-RAM interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) STG_WRITE_REG(SDRAMArbiterConf, adwSDRAMArgCfg0[dwMemTypeIdx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (dwRevID < 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) STG_WRITE_REG(SDRAMConf0, 0x49A1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) STG_WRITE_REG(SDRAMConf1, adwSDRAMCfg1[dwMemTypeIdx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) STG_WRITE_REG(SDRAMConf0, 0x4DF1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) STG_WRITE_REG(SDRAMConf1, adwSDRAMCfg2[dwMemTypeIdx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) STG_WRITE_REG(SDRAMConf2, 0x31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) STG_WRITE_REG(SDRAMRefresh, adwSDRAMRsh[dwChipSpeedIdx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return adwChipSpeed[dwChipSpeedIdx] * 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u32 ProgramClock(u32 refClock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u32 coreClock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u32 * FOut, u32 * ROut, u32 * POut)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) u32 R = 0, F = 0, OD = 0, ODIndex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u32 ulBestR = 0, ulBestF = 0, ulBestOD = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) u32 ulBestClk = 0, ulBestScore = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u32 ulScore, ulPhaseScore, ulVcoScore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u32 ulTmp = 0, ulVCO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u32 ulScaleClockReq, ulMinClock, ulMaxClock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 ODValues[] = { 1, 2, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* Translate clock in Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) coreClock *= 100; /* in Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) refClock *= 1000; /* in Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* Work out acceptable clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * The method calculates ~ +- 0.4% (1/256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ulMinClock = coreClock - (coreClock >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ulMaxClock = coreClock + (coreClock >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Scale clock required for use in calculations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ulScaleClockReq = coreClock >> STG4K3_PLL_SCALER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* Iterate through post divider values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) for (ODIndex = 0; ODIndex < 3; ODIndex++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) OD = ODValues[ODIndex];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) R = STG4K3_PLL_MIN_R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* loop for pre-divider from min to max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) while (R <= STG4K3_PLL_MAX_R) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* estimate required feedback multiplier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ulTmp = R * (ulScaleClockReq << OD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* F = ClkRequired * R * (2^OD) / Fref */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) F = (u32)(ulTmp / (refClock >> STG4K3_PLL_SCALER));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* compensate for accuracy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (F > STG4K3_PLL_MIN_F)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) F--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * We should be close to our target frequency (if it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * achievable with current OD & R) let's iterate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * through F for best fit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) while ((F >= STG4K3_PLL_MIN_F) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) (F <= STG4K3_PLL_MAX_F)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* Calc VCO at full accuracy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ulVCO = refClock / R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ulVCO = F * ulVCO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Check it's within restricted VCO range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * unless of course the desired frequency is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * above the restricted range, then test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * against VCO limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if ((ulVCO >= STG4K3_PLL_MINR_VCO) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ((ulVCO <= STG4K3_PLL_MAXR_VCO) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ((coreClock > STG4K3_PLL_MAXR_VCO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) && (ulVCO <= STG4K3_PLL_MAX_VCO)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ulTmp = (ulVCO >> OD); /* Clock = VCO / (2^OD) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* Is this clock good enough? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if ((ulTmp >= ulMinClock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) && (ulTmp <= ulMaxClock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ulPhaseScore = (((refClock / R) - (refClock / STG4K3_PLL_MAX_R))) / ((refClock - (refClock / STG4K3_PLL_MAX_R)) >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ulVcoScore = ((ulVCO - STG4K3_PLL_MINR_VCO)) / ((STG4K3_PLL_MAXR_VCO - STG4K3_PLL_MINR_VCO) >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ulScore = ulPhaseScore + ulVcoScore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (!ulBestScore) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ulBestOD = OD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ulBestF = F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ulBestR = R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ulBestClk = ulTmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ulBestScore =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ulScore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* is this better, ( aim for highest Score) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /*--------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) Here we want to use a scoring system which will take account of both the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) value at the phase comparater and the VCO output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) to do this we will use a cumulative score between the two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) The way this ends up is that we choose the first value in the loop anyway
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) but we shall keep this code in case new restrictions come into play
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) --------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if ((ulScore >= ulBestScore) && (OD > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ulBestOD = OD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ulBestF = F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ulBestR = R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ulBestClk = ulTmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ulBestScore =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ulScore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) F++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) R++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) did we find anything?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) Then return RFOD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (ulBestScore) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *ROut = ulBestR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) *FOut = ulBestF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if ((ulBestOD == 2) || (ulBestOD == 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) *POut = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *POut = ulBestOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return (ulBestClk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) u32 F, R, P;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u16 core_pll = 0, sub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) u32 ulChipSpeed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) STG_WRITE_REG(IntMask, 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* Disable Primary Core Thread0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) tmp = STG_READ_REG(Thread0Enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) CLEAR_BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) STG_WRITE_REG(Thread0Enable, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Disable Primary Core Thread1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) tmp = STG_READ_REG(Thread1Enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) CLEAR_BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) STG_WRITE_REG(Thread1Enable, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) STG_WRITE_REG(SoftwareReset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_ROM_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) STG_WRITE_REG(SoftwareReset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_TA_RST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) PMX2_SOFTRESET_ROM_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* Need to play around to reset TA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) STG_WRITE_REG(TAConfiguration, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) STG_WRITE_REG(SoftwareReset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_ROM_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) STG_WRITE_REG(SoftwareReset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_TA_RST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) PMX2_SOFTRESET_ROM_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) pci_read_config_word(pDev, PCI_CONFIG_SUBSYS_ID, &sub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) (u32)pDev->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (ulChipSpeed == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ProgramClock(REF_FREQ, CORE_PLL_FREQ, &F, &R, &P);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) core_pll |= ((P) | ((F - 2) << 2) | ((R - 2) << 11));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* Set Core PLL Control to Core PLL Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* Send bits 0:7 of the Core PLL Mode register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) tmp = ((CORE_PLL_MODE_REG_0_7 << 8) | (core_pll & 0x00FF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) pci_write_config_word(pDev, CorePllControl, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Without some delay between the PCI config writes the clock does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) not reliably set when the code is compiled -O3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) OS_DELAY(1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) tmp |= SET_BIT(14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) pci_write_config_word(pDev, CorePllControl, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) OS_DELAY(1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* Send bits 8:15 of the Core PLL Mode register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) tmp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ((CORE_PLL_MODE_REG_8_15 << 8) | ((core_pll & 0xFF00) >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) pci_write_config_word(pDev, CorePllControl, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) OS_DELAY(1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) tmp |= SET_BIT(14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) pci_write_config_word(pDev, CorePllControl, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) OS_DELAY(1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) STG_WRITE_REG(SoftwareReset, PMX2_SOFTRESET_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* Enable Primary Core Thread0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) tmp = ((STG_READ_REG(Thread0Enable)) | SET_BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) STG_WRITE_REG(Thread0Enable, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* Enable Primary Core Thread1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) tmp = ((STG_READ_REG(Thread1Enable)) | SET_BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) STG_WRITE_REG(Thread1Enable, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }