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