1 #include <linux/kernel.h> 2 #include <linux/sizes.h> 3 4 #include "ddk750_help.h" 5 #include "ddk750_reg.h" 6 #include "ddk750_chip.h" 7 #include "ddk750_power.h" 8 9 /* n / d + 1 / 2 = (2n + d) / 2d */ 10 #define roundedDiv(num, denom) ((2 * (num) + (denom)) / (2 * (denom))) 11 #define MHz(x) ((x) * 1000000) 12 13 logical_chip_type_t getChipType(void) 14 { 15 unsigned short physicalID; 16 char physicalRev; 17 logical_chip_type_t chip; 18 19 physicalID = devId750; /* either 0x718 or 0x750 */ 20 physicalRev = revId750; 21 22 if (physicalID == 0x718) 23 chip = SM718; 24 else if (physicalID == 0x750) { 25 chip = SM750; 26 /* SM750 and SM750LE are different in their revision ID only. */ 27 if (physicalRev == SM750LE_REVISION_ID) 28 chip = SM750LE; 29 } else 30 chip = SM_UNKNOWN; 31 32 return chip; 33 } 34 35 static unsigned int get_mxclk_freq(void) 36 { 37 unsigned int pll_reg; 38 unsigned int M, N, OD, POD; 39 40 if (getChipType() == SM750LE) 41 return MHz(130); 42 43 pll_reg = PEEK32(MXCLK_PLL_CTRL); 44 M = (pll_reg & PLL_CTRL_M_MASK) >> PLL_CTRL_M_SHIFT; 45 N = (pll_reg & PLL_CTRL_N_MASK) >> PLL_CTRL_M_SHIFT; 46 OD = (pll_reg & PLL_CTRL_OD_MASK) >> PLL_CTRL_OD_SHIFT; 47 POD = (pll_reg & PLL_CTRL_POD_MASK) >> PLL_CTRL_POD_SHIFT; 48 49 return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD); 50 } 51 52 /* 53 * This function set up the main chip clock. 54 * 55 * Input: Frequency to be set. 56 */ 57 static void setChipClock(unsigned int frequency) 58 { 59 pll_value_t pll; 60 unsigned int ulActualMxClk; 61 62 /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */ 63 if (getChipType() == SM750LE) 64 return; 65 66 if (frequency) { 67 /* 68 * Set up PLL, a structure to hold the value to be set in clocks. 69 */ 70 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */ 71 pll.clockType = MXCLK_PLL; 72 73 /* 74 * Call calcPllValue() to fill up the other fields for PLL structure. 75 * Sometime, the chip cannot set up the exact clock required by User. 76 * Return value from calcPllValue() gives the actual possible clock. 77 */ 78 ulActualMxClk = calcPllValue(frequency, &pll); 79 80 /* Master Clock Control: MXCLK_PLL */ 81 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll)); 82 } 83 } 84 85 static void setMemoryClock(unsigned int frequency) 86 { 87 unsigned int reg, divisor; 88 89 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ 90 if (getChipType() == SM750LE) 91 return; 92 93 if (frequency) { 94 /* Set the frequency to the maximum frequency that the DDR Memory can take 95 which is 336MHz. */ 96 if (frequency > MHz(336)) 97 frequency = MHz(336); 98 99 /* Calculate the divisor */ 100 divisor = roundedDiv(get_mxclk_freq(), frequency); 101 102 /* Set the corresponding divisor in the register. */ 103 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK; 104 switch (divisor) { 105 default: 106 case 1: 107 reg |= CURRENT_GATE_M2XCLK_DIV_1; 108 break; 109 case 2: 110 reg |= CURRENT_GATE_M2XCLK_DIV_2; 111 break; 112 case 3: 113 reg |= CURRENT_GATE_M2XCLK_DIV_3; 114 break; 115 case 4: 116 reg |= CURRENT_GATE_M2XCLK_DIV_4; 117 break; 118 } 119 120 setCurrentGate(reg); 121 } 122 } 123 124 /* 125 * This function set up the master clock (MCLK). 126 * 127 * Input: Frequency to be set. 128 * 129 * NOTE: 130 * The maximum frequency the engine can run is 168MHz. 131 */ 132 static void setMasterClock(unsigned int frequency) 133 { 134 unsigned int reg, divisor; 135 136 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ 137 if (getChipType() == SM750LE) 138 return; 139 140 if (frequency) { 141 /* Set the frequency to the maximum frequency that the SM750 engine can 142 run, which is about 190 MHz. */ 143 if (frequency > MHz(190)) 144 frequency = MHz(190); 145 146 /* Calculate the divisor */ 147 divisor = roundedDiv(get_mxclk_freq(), frequency); 148 149 /* Set the corresponding divisor in the register. */ 150 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK; 151 switch (divisor) { 152 default: 153 case 3: 154 reg |= CURRENT_GATE_MCLK_DIV_3; 155 break; 156 case 4: 157 reg |= CURRENT_GATE_MCLK_DIV_4; 158 break; 159 case 6: 160 reg |= CURRENT_GATE_MCLK_DIV_6; 161 break; 162 case 8: 163 reg |= CURRENT_GATE_MCLK_DIV_8; 164 break; 165 } 166 167 setCurrentGate(reg); 168 } 169 } 170 171 unsigned int ddk750_getVMSize(void) 172 { 173 unsigned int reg; 174 unsigned int data; 175 176 /* sm750le only use 64 mb memory*/ 177 if (getChipType() == SM750LE) 178 return SZ_64M; 179 180 /* for 750,always use power mode0*/ 181 reg = PEEK32(MODE0_GATE); 182 reg |= MODE0_GATE_GPIO; 183 POKE32(MODE0_GATE, reg); 184 185 /* get frame buffer size from GPIO */ 186 reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK; 187 switch (reg) { 188 case MISC_CTRL_LOCALMEM_SIZE_8M: 189 data = SZ_8M; break; /* 8 Mega byte */ 190 case MISC_CTRL_LOCALMEM_SIZE_16M: 191 data = SZ_16M; break; /* 16 Mega byte */ 192 case MISC_CTRL_LOCALMEM_SIZE_32M: 193 data = SZ_32M; break; /* 32 Mega byte */ 194 case MISC_CTRL_LOCALMEM_SIZE_64M: 195 data = SZ_64M; break; /* 64 Mega byte */ 196 default: 197 data = 0; 198 break; 199 } 200 return data; 201 } 202 203 int ddk750_initHw(initchip_param_t *pInitParam) 204 { 205 unsigned int reg; 206 207 if (pInitParam->powerMode != 0) 208 pInitParam->powerMode = 0; 209 setPowerMode(pInitParam->powerMode); 210 211 /* Enable display power gate & LOCALMEM power gate*/ 212 reg = PEEK32(CURRENT_GATE); 213 reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM); 214 setCurrentGate(reg); 215 216 if (getChipType() != SM750LE) { 217 /* set panel pll and graphic mode via mmio_88 */ 218 reg = PEEK32(VGA_CONFIGURATION); 219 reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE); 220 POKE32(VGA_CONFIGURATION, reg); 221 } else { 222 #if defined(__i386__) || defined(__x86_64__) 223 /* set graphic mode via IO method */ 224 outb_p(0x88, 0x3d4); 225 outb_p(0x06, 0x3d5); 226 #endif 227 } 228 229 /* Set the Main Chip Clock */ 230 setChipClock(MHz((unsigned int)pInitParam->chipClock)); 231 232 /* Set up memory clock. */ 233 setMemoryClock(MHz(pInitParam->memClock)); 234 235 /* Set up master clock */ 236 setMasterClock(MHz(pInitParam->masterClock)); 237 238 239 /* Reset the memory controller. If the memory controller is not reset in SM750, 240 the system might hang when sw accesses the memory. 241 The memory should be resetted after changing the MXCLK. 242 */ 243 if (pInitParam->resetMemory == 1) { 244 reg = PEEK32(MISC_CTRL); 245 reg &= ~MISC_CTRL_LOCALMEM_RESET; 246 POKE32(MISC_CTRL, reg); 247 248 reg |= MISC_CTRL_LOCALMEM_RESET; 249 POKE32(MISC_CTRL, reg); 250 } 251 252 if (pInitParam->setAllEngOff == 1) { 253 enable2DEngine(0); 254 255 /* Disable Overlay, if a former application left it on */ 256 reg = PEEK32(VIDEO_DISPLAY_CTRL); 257 reg &= ~DISPLAY_CTRL_PLANE; 258 POKE32(VIDEO_DISPLAY_CTRL, reg); 259 260 /* Disable video alpha, if a former application left it on */ 261 reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); 262 reg &= ~DISPLAY_CTRL_PLANE; 263 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg); 264 265 /* Disable alpha plane, if a former application left it on */ 266 reg = PEEK32(ALPHA_DISPLAY_CTRL); 267 reg &= ~DISPLAY_CTRL_PLANE; 268 POKE32(ALPHA_DISPLAY_CTRL, reg); 269 270 /* Disable DMA Channel, if a former application left it on */ 271 reg = PEEK32(DMA_ABORT_INTERRUPT); 272 reg |= DMA_ABORT_INTERRUPT_ABORT_1; 273 POKE32(DMA_ABORT_INTERRUPT, reg); 274 275 /* Disable DMA Power, if a former application left it on */ 276 enableDMA(0); 277 } 278 279 /* We can add more initialization as needed. */ 280 281 return 0; 282 } 283 284 /* 285 monk liu @ 4/6/2011: 286 re-write the calculatePLL function of ddk750. 287 the original version function does not use some mathematics tricks and shortcut 288 when it doing the calculation of the best N,M,D combination 289 I think this version gives a little upgrade in speed 290 291 750 pll clock formular: 292 Request Clock = (Input Clock * M )/(N * X) 293 294 Input Clock = 14318181 hz 295 X = 2 power D 296 D ={0,1,2,3,4,5,6} 297 M = {1,...,255} 298 N = {2,...,15} 299 */ 300 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) 301 { 302 /* as sm750 register definition, N located in 2,15 and M located in 1,255 */ 303 int N, M, X, d; 304 int mini_diff; 305 unsigned int RN, quo, rem, fl_quo; 306 unsigned int input, request; 307 unsigned int tmpClock, ret; 308 const int max_OD = 3; 309 int max_d = 6; 310 311 if (getChipType() == SM750LE) { 312 /* SM750LE don't have prgrammable PLL and M/N values to work on. 313 Just return the requested clock. */ 314 return request_orig; 315 } 316 317 ret = 0; 318 mini_diff = ~0; 319 request = request_orig / 1000; 320 input = pll->inputFreq / 1000; 321 322 /* for MXCLK register , no POD provided, so need be treated differently */ 323 if (pll->clockType == MXCLK_PLL) 324 max_d = 3; 325 326 for (N = 15; N > 1; N--) { 327 /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */ 328 RN = N * request; 329 quo = RN / input; 330 rem = RN % input;/* rem always small than 14318181 */ 331 fl_quo = (rem * 10000 / input); 332 333 for (d = max_d; d >= 0; d--) { 334 X = (1 << d); 335 M = quo * X; 336 M += fl_quo * X / 10000; 337 /* round step */ 338 M += (fl_quo * X % 10000) > 5000 ? 1 : 0; 339 if (M < 256 && M > 0) { 340 unsigned int diff; 341 342 tmpClock = pll->inputFreq * M / N / X; 343 diff = abs(tmpClock - request_orig); 344 if (diff < mini_diff) { 345 pll->M = M; 346 pll->N = N; 347 pll->POD = 0; 348 if (d > max_OD) 349 pll->POD = d - max_OD; 350 pll->OD = d - pll->POD; 351 mini_diff = diff; 352 ret = tmpClock; 353 } 354 } 355 } 356 } 357 return ret; 358 } 359 360 unsigned int formatPllReg(pll_value_t *pPLL) 361 { 362 #ifndef VALIDATION_CHIP 363 unsigned int POD = pPLL->POD; 364 #endif 365 unsigned int OD = pPLL->OD; 366 unsigned int M = pPLL->M; 367 unsigned int N = pPLL->N; 368 unsigned int reg = 0; 369 370 /* 371 * Note that all PLL's have the same format. Here, we just use 372 * Panel PLL parameter to work out the bit fields in the 373 * register. On returning a 32 bit number, the value can be 374 * applied to any PLL in the calling function. 375 */ 376 reg = PLL_CTRL_POWER | 377 #ifndef VALIDATION_CHIP 378 ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) | 379 #endif 380 ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) | 381 ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) | 382 ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK); 383 384 return reg; 385 } 386 387 388