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