root/drivers/staging/sm750fb/ddk750_chip.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sm750_get_chip_type
  2. sm750_set_chip_type
  3. get_mxclk_freq
  4. set_chip_clock
  5. set_memory_clock
  6. set_master_clock
  7. ddk750_get_vm_size
  8. ddk750_init_hw
  9. sm750_calc_pll_value
  10. sm750_format_pll_reg

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

/* [<][>][^][v][top][bottom][index][help] */