1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/sizes.h>
5 #include "ddk750_reg.h"
6 #include "ddk750_chip.h"
7 #include "ddk750_power.h"
9 #define MHz(x) ((x) * 1000000)
11 static enum logical_chip_type chip;
13 enum logical_chip_type sm750_get_chip_type(void)
18 void sm750_set_chip_type(unsigned short devId, u8 revId)
22 } else if (devId == 0x750) {
24 /* SM750 and SM750LE are different in their revision ID only. */
25 if (revId == SM750LE_REVISION_ID) {
27 pr_info("found sm750le\n");
34 static unsigned int get_mxclk_freq(void)
37 unsigned int M, N, OD, POD;
39 if (sm750_get_chip_type() == SM750LE)
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;
48 return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
52 * This function set up the main chip clock.
54 * Input: Frequency to be set.
56 static void set_chip_clock(unsigned int frequency)
59 unsigned int ulActualMxClk;
61 /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
62 if (sm750_get_chip_type() == SM750LE)
67 * Set up PLL structure to hold the value to be set in clocks.
69 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
70 pll.clockType = MXCLK_PLL;
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
79 ulActualMxClk = sm750_calc_pll_value(frequency, &pll);
81 /* Master Clock Control: MXCLK_PLL */
82 poke32(MXCLK_PLL_CTRL, sm750_format_pll_reg(&pll));
86 static void set_memory_clock(unsigned int frequency)
88 unsigned int reg, divisor;
91 * Cheok_0509: For SM750LE, the memory clock is fixed.
94 if (sm750_get_chip_type() == SM750LE)
99 * Set the frequency to the maximum frequency
100 * that the DDR Memory can take which is 336MHz.
102 if (frequency > MHz(336))
103 frequency = MHz(336);
105 /* Calculate the divisor */
106 divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency);
108 /* Set the corresponding divisor in the register. */
109 reg = peek32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
113 reg |= CURRENT_GATE_M2XCLK_DIV_1;
116 reg |= CURRENT_GATE_M2XCLK_DIV_2;
119 reg |= CURRENT_GATE_M2XCLK_DIV_3;
122 reg |= CURRENT_GATE_M2XCLK_DIV_4;
126 sm750_set_current_gate(reg);
131 * This function set up the master clock (MCLK).
133 * Input: Frequency to be set.
136 * The maximum frequency the engine can run is 168MHz.
138 static void set_master_clock(unsigned int frequency)
140 unsigned int reg, divisor;
143 * Cheok_0509: For SM750LE, the memory clock is fixed.
146 if (sm750_get_chip_type() == SM750LE)
151 * Set the frequency to the maximum frequency
152 * that the SM750 engine can run, which is about 190 MHz.
154 if (frequency > MHz(190))
155 frequency = MHz(190);
157 /* Calculate the divisor */
158 divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency);
160 /* Set the corresponding divisor in the register. */
161 reg = peek32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
165 reg |= CURRENT_GATE_MCLK_DIV_3;
168 reg |= CURRENT_GATE_MCLK_DIV_4;
171 reg |= CURRENT_GATE_MCLK_DIV_6;
174 reg |= CURRENT_GATE_MCLK_DIV_8;
178 sm750_set_current_gate(reg);
182 unsigned int ddk750_get_vm_size(void)
187 /* sm750le only use 64 mb memory*/
188 if (sm750_get_chip_type() == SM750LE)
191 /* for 750,always use power mode0*/
192 reg = peek32(MODE0_GATE);
193 reg |= MODE0_GATE_GPIO;
194 poke32(MODE0_GATE, reg);
196 /* get frame buffer size from GPIO */
197 reg = peek32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
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 */
214 int ddk750_init_hw(struct initchip_param *pInitParam)
218 if (pInitParam->powerMode != 0)
219 pInitParam->powerMode = 0;
220 sm750_set_power_mode(pInitParam->powerMode);
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);
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);
233 #if defined(__i386__) || defined(__x86_64__)
234 /* set graphic mode via IO method */
240 /* Set the Main Chip Clock */
241 set_chip_clock(MHz((unsigned int)pInitParam->chipClock));
243 /* Set up memory clock. */
244 set_memory_clock(MHz(pInitParam->memClock));
246 /* Set up master clock */
247 set_master_clock(MHz(pInitParam->masterClock));
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.
255 if (pInitParam->resetMemory == 1) {
256 reg = peek32(MISC_CTRL);
257 reg &= ~MISC_CTRL_LOCALMEM_RESET;
258 poke32(MISC_CTRL, reg);
260 reg |= MISC_CTRL_LOCALMEM_RESET;
261 poke32(MISC_CTRL, reg);
264 if (pInitParam->setAllEngOff == 1) {
265 sm750_enable_2d_engine(0);
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);
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);
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);
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);
287 /* Disable DMA Power, if a former application left it on */
291 /* We can add more initialization as needed. */
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
304 * 750 pll clock formular:
305 * Request Clock = (Input Clock * M )/(N * X)
307 * Input Clock = 14318181 hz
313 unsigned int sm750_calc_pll_value(unsigned int request_orig,
314 struct pll_value *pll)
317 * as sm750 register definition,
318 * N located in 2,15 and M located in 1,255
322 unsigned int RN, quo, rem, fl_quo;
323 unsigned int input, request;
324 unsigned int tmpClock, ret;
325 const int max_OD = 3;
328 if (sm750_get_chip_type() == SM750LE) {
331 * programmable PLL and M/N values to work on.
332 * Just return the requested clock.
339 request = request_orig / 1000;
340 input = pll->inputFreq / 1000;
343 * for MXCLK register,
344 * no POD provided, so need be treated differently
346 if (pll->clockType == MXCLK_PLL)
349 for (N = 15; N > 1; N--) {
351 * RN will not exceed maximum long
352 * if @request <= 285 MHZ (for 32bit cpu)
356 rem = RN % input;/* rem always small than 14318181 */
357 fl_quo = rem * 10000 / input;
359 for (d = max_d; d >= 0; d--) {
362 M += fl_quo * X / 10000;
364 M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
365 if (M < 256 && M > 0) {
368 tmpClock = pll->inputFreq * M / N / X;
369 diff = abs(tmpClock - request_orig);
370 if (diff < mini_diff) {
375 pll->POD = d - max_OD;
376 pll->OD = d - pll->POD;
386 unsigned int sm750_format_pll_reg(struct pll_value *pPLL)
388 #ifndef VALIDATION_CHIP
389 unsigned int POD = pPLL->POD;
391 unsigned int OD = pPLL->OD;
392 unsigned int M = pPLL->M;
393 unsigned int N = pPLL->N;
394 unsigned int reg = 0;
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.
402 reg = PLL_CTRL_POWER |
403 #ifndef VALIDATION_CHIP
404 ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
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);