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