cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ddk750_chip.c (9760B)


      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}