linux/drivers/staging/sm750fb/ddk750_chip.c
<<
>>
Prefs
   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
  11static enum logical_chip_type chip;
  12
  13enum logical_chip_type sm750_get_chip_type(void)
  14{
  15        return chip;
  16}
  17
  18void sm750_set_chip_type(unsigned short devId, u8 revId)
  19{
  20        if (devId == 0x718) {
  21                chip = SM718;
  22        } else if (devId == 0x750) {
  23                chip = SM750;
  24                /* SM750 and SM750LE are different in their revision ID only. */
  25                if (revId == SM750LE_REVISION_ID) {
  26                        chip = SM750LE;
  27                        pr_info("found sm750le\n");
  28                }
  29        } else {
  30                chip = SM_UNKNOWN;
  31        }
  32}
  33
  34static 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 / (1 << OD) / (1 << POD);
  49}
  50
  51/*
  52 * This function set up the main chip clock.
  53 *
  54 * Input: Frequency to be set.
  55 */
  56static void set_chip_clock(unsigned int frequency)
  57{
  58        struct pll_value pll;
  59        unsigned int ulActualMxClk;
  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                ulActualMxClk = 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
  86static 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 */
 138static 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
 182unsigned 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
 214int 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 */
 313unsigned 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 tmpClock, 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                                tmpClock = pll->inputFreq * M / N / X;
 369                                diff = abs(tmpClock - 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 = tmpClock;
 379                                }
 380                        }
 381                }
 382        }
 383        return ret;
 384}
 385
 386unsigned 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        unsigned int reg = 0;
 395
 396        /*
 397         * Note that all PLL's have the same format. Here, we just use
 398         * Panel PLL parameter to work out the bit fields in the
 399         * register. On returning a 32 bit number, the value can be
 400         * applied to any PLL in the calling function.
 401         */
 402        reg = PLL_CTRL_POWER |
 403#ifndef VALIDATION_CHIP
 404                ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
 405#endif
 406                ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) |
 407                ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) |
 408                ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK);
 409
 410        return reg;
 411}
 412