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

megacores_pll.c (8374B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2020 Unisoc Inc.
      4 */
      5
      6#include <asm/div64.h>
      7#include <linux/delay.h>
      8#include <linux/init.h>
      9#include <linux/kernel.h>
     10#include <linux/regmap.h>
     11#include <linux/string.h>
     12
     13#include "sprd_dsi.h"
     14
     15#define L						0
     16#define H						1
     17#define CLK						0
     18#define DATA					1
     19#define INFINITY				0xffffffff
     20#define MIN_OUTPUT_FREQ			(100)
     21
     22#define AVERAGE(a, b) (min(a, b) + abs((b) - (a)) / 2)
     23
     24/* sharkle */
     25#define VCO_BAND_LOW	750
     26#define VCO_BAND_MID	1100
     27#define VCO_BAND_HIGH	1500
     28#define PHY_REF_CLK	26000
     29
     30static int dphy_calc_pll_param(struct dphy_pll *pll)
     31{
     32	const u32 khz = 1000;
     33	const u32 mhz = 1000000;
     34	const unsigned long long factor = 100;
     35	unsigned long long tmp;
     36	int i;
     37
     38	pll->potential_fvco = pll->freq / khz;
     39	pll->ref_clk = PHY_REF_CLK / khz;
     40
     41	for (i = 0; i < 4; ++i) {
     42		if (pll->potential_fvco >= VCO_BAND_LOW &&
     43		    pll->potential_fvco <= VCO_BAND_HIGH) {
     44			pll->fvco = pll->potential_fvco;
     45			pll->out_sel = BIT(i);
     46			break;
     47		}
     48		pll->potential_fvco <<= 1;
     49	}
     50	if (pll->fvco == 0)
     51		return -EINVAL;
     52
     53	if (pll->fvco >= VCO_BAND_LOW && pll->fvco <= VCO_BAND_MID) {
     54		/* vco band control */
     55		pll->vco_band = 0x0;
     56		/* low pass filter control */
     57		pll->lpf_sel = 1;
     58	} else if (pll->fvco > VCO_BAND_MID && pll->fvco <= VCO_BAND_HIGH) {
     59		pll->vco_band = 0x1;
     60		pll->lpf_sel = 0;
     61	} else {
     62		return -EINVAL;
     63	}
     64
     65	pll->nint = pll->fvco / pll->ref_clk;
     66	tmp = pll->fvco * factor * mhz;
     67	do_div(tmp, pll->ref_clk);
     68	tmp = tmp - pll->nint * factor * mhz;
     69	tmp *= BIT(20);
     70	do_div(tmp, 100000000);
     71	pll->kint = (u32)tmp;
     72	pll->refin = 3; /* pre-divider bypass */
     73	pll->sdm_en = true; /* use fraction N PLL */
     74	pll->fdk_s = 0x1; /* fraction */
     75	pll->cp_s = 0x0;
     76	pll->det_delay = 0x1;
     77
     78	return 0;
     79}
     80
     81static void dphy_set_pll_reg(struct dphy_pll *pll, struct regmap *regmap)
     82{
     83	u8 reg_val[9] = {0};
     84	int i;
     85
     86	u8 reg_addr[] = {
     87		0x03, 0x04, 0x06, 0x08, 0x09,
     88		0x0a, 0x0b, 0x0e, 0x0f
     89	};
     90
     91	reg_val[0] = 1 | (1 << 1) |  (pll->lpf_sel << 2);
     92	reg_val[1] = pll->div | (1 << 3) | (pll->cp_s << 5) | (pll->fdk_s << 7);
     93	reg_val[2] = pll->nint;
     94	reg_val[3] = pll->vco_band | (pll->sdm_en << 1) | (pll->refin << 2);
     95	reg_val[4] = pll->kint >> 12;
     96	reg_val[5] = pll->kint >> 4;
     97	reg_val[6] = pll->out_sel | ((pll->kint << 4) & 0xf);
     98	reg_val[7] = 1 << 4;
     99	reg_val[8] = pll->det_delay;
    100
    101	for (i = 0; i < sizeof(reg_addr); ++i) {
    102		regmap_write(regmap, reg_addr[i], reg_val[i]);
    103		DRM_DEBUG("%02x: %02x\n", reg_addr[i], reg_val[i]);
    104	}
    105}
    106
    107int dphy_pll_config(struct dsi_context *ctx)
    108{
    109	struct sprd_dsi *dsi = container_of(ctx, struct sprd_dsi, ctx);
    110	struct regmap *regmap = ctx->regmap;
    111	struct dphy_pll *pll = &ctx->pll;
    112	int ret;
    113
    114	pll->freq = dsi->slave->hs_rate;
    115
    116	/* FREQ = 26M * (NINT + KINT / 2^20) / out_sel */
    117	ret = dphy_calc_pll_param(pll);
    118	if (ret) {
    119		drm_err(dsi->drm, "failed to calculate dphy pll parameters\n");
    120		return ret;
    121	}
    122	dphy_set_pll_reg(pll, regmap);
    123
    124	return 0;
    125}
    126
    127static void dphy_set_timing_reg(struct regmap *regmap, int type, u8 val[])
    128{
    129	switch (type) {
    130	case REQUEST_TIME:
    131		regmap_write(regmap, 0x31, val[CLK]);
    132		regmap_write(regmap, 0x41, val[DATA]);
    133		regmap_write(regmap, 0x51, val[DATA]);
    134		regmap_write(regmap, 0x61, val[DATA]);
    135		regmap_write(regmap, 0x71, val[DATA]);
    136
    137		regmap_write(regmap, 0x90, val[CLK]);
    138		regmap_write(regmap, 0xa0, val[DATA]);
    139		regmap_write(regmap, 0xb0, val[DATA]);
    140		regmap_write(regmap, 0xc0, val[DATA]);
    141		regmap_write(regmap, 0xd0, val[DATA]);
    142		break;
    143	case PREPARE_TIME:
    144		regmap_write(regmap, 0x32, val[CLK]);
    145		regmap_write(regmap, 0x42, val[DATA]);
    146		regmap_write(regmap, 0x52, val[DATA]);
    147		regmap_write(regmap, 0x62, val[DATA]);
    148		regmap_write(regmap, 0x72, val[DATA]);
    149
    150		regmap_write(regmap, 0x91, val[CLK]);
    151		regmap_write(regmap, 0xa1, val[DATA]);
    152		regmap_write(regmap, 0xb1, val[DATA]);
    153		regmap_write(regmap, 0xc1, val[DATA]);
    154		regmap_write(regmap, 0xd1, val[DATA]);
    155		break;
    156	case ZERO_TIME:
    157		regmap_write(regmap, 0x33, val[CLK]);
    158		regmap_write(regmap, 0x43, val[DATA]);
    159		regmap_write(regmap, 0x53, val[DATA]);
    160		regmap_write(regmap, 0x63, val[DATA]);
    161		regmap_write(regmap, 0x73, val[DATA]);
    162
    163		regmap_write(regmap, 0x92, val[CLK]);
    164		regmap_write(regmap, 0xa2, val[DATA]);
    165		regmap_write(regmap, 0xb2, val[DATA]);
    166		regmap_write(regmap, 0xc2, val[DATA]);
    167		regmap_write(regmap, 0xd2, val[DATA]);
    168		break;
    169	case TRAIL_TIME:
    170		regmap_write(regmap, 0x34, val[CLK]);
    171		regmap_write(regmap, 0x44, val[DATA]);
    172		regmap_write(regmap, 0x54, val[DATA]);
    173		regmap_write(regmap, 0x64, val[DATA]);
    174		regmap_write(regmap, 0x74, val[DATA]);
    175
    176		regmap_write(regmap, 0x93, val[CLK]);
    177		regmap_write(regmap, 0xa3, val[DATA]);
    178		regmap_write(regmap, 0xb3, val[DATA]);
    179		regmap_write(regmap, 0xc3, val[DATA]);
    180		regmap_write(regmap, 0xd3, val[DATA]);
    181		break;
    182	case EXIT_TIME:
    183		regmap_write(regmap, 0x36, val[CLK]);
    184		regmap_write(regmap, 0x46, val[DATA]);
    185		regmap_write(regmap, 0x56, val[DATA]);
    186		regmap_write(regmap, 0x66, val[DATA]);
    187		regmap_write(regmap, 0x76, val[DATA]);
    188
    189		regmap_write(regmap, 0x95, val[CLK]);
    190		regmap_write(regmap, 0xA5, val[DATA]);
    191		regmap_write(regmap, 0xB5, val[DATA]);
    192		regmap_write(regmap, 0xc5, val[DATA]);
    193		regmap_write(regmap, 0xd5, val[DATA]);
    194		break;
    195	case CLKPOST_TIME:
    196		regmap_write(regmap, 0x35, val[CLK]);
    197		regmap_write(regmap, 0x94, val[CLK]);
    198		break;
    199
    200	/* the following just use default value */
    201	case SETTLE_TIME:
    202		fallthrough;
    203	case TA_GET:
    204		fallthrough;
    205	case TA_GO:
    206		fallthrough;
    207	case TA_SURE:
    208		fallthrough;
    209	default:
    210		break;
    211	}
    212}
    213
    214void dphy_timing_config(struct dsi_context *ctx)
    215{
    216	struct regmap *regmap = ctx->regmap;
    217	struct dphy_pll *pll = &ctx->pll;
    218	const u32 factor = 2;
    219	const u32 scale = 100;
    220	u32 t_ui, t_byteck, t_half_byteck;
    221	u32 range[2], constant;
    222	u8 val[2];
    223	u32 tmp = 0;
    224
    225	/* t_ui: 1 ui, byteck: 8 ui, half byteck: 4 ui */
    226	t_ui = 1000 * scale / (pll->freq / 1000);
    227	t_byteck = t_ui << 3;
    228	t_half_byteck = t_ui << 2;
    229	constant = t_ui << 1;
    230
    231	/* REQUEST_TIME: HS T-LPX: LP-01
    232	 * For T-LPX, mipi spec defined min value is 50ns,
    233	 * but maybe it shouldn't be too small, because BTA,
    234	 * LP-10, LP-00, LP-01, all of this is related to T-LPX.
    235	 */
    236	range[L] = 50 * scale;
    237	range[H] = INFINITY;
    238	val[CLK] = DIV_ROUND_UP(range[L] * (factor << 1), t_byteck) - 2;
    239	val[DATA] = val[CLK];
    240	dphy_set_timing_reg(regmap, REQUEST_TIME, val);
    241
    242	/* PREPARE_TIME: HS sequence: LP-00 */
    243	range[L] = 38 * scale;
    244	range[H] = 95 * scale;
    245	tmp = AVERAGE(range[L], range[H]);
    246	val[CLK] = DIV_ROUND_UP(AVERAGE(range[L], range[H]), t_half_byteck) - 1;
    247	range[L] = 40 * scale + 4 * t_ui;
    248	range[H] = 85 * scale + 6 * t_ui;
    249	tmp |= AVERAGE(range[L], range[H]) << 16;
    250	val[DATA] = DIV_ROUND_UP(AVERAGE(range[L], range[H]), t_half_byteck) - 1;
    251	dphy_set_timing_reg(regmap, PREPARE_TIME, val);
    252
    253	/* ZERO_TIME: HS-ZERO */
    254	range[L] = 300 * scale;
    255	range[H] = INFINITY;
    256	val[CLK] = DIV_ROUND_UP(range[L] * factor + (tmp & 0xffff)
    257			- 525 * t_byteck / 100, t_byteck) - 2;
    258	range[L] = 145 * scale + 10 * t_ui;
    259	val[DATA] = DIV_ROUND_UP(range[L] * factor
    260			+ ((tmp >> 16) & 0xffff) - 525 * t_byteck / 100,
    261			t_byteck) - 2;
    262	dphy_set_timing_reg(regmap, ZERO_TIME, val);
    263
    264	/* TRAIL_TIME: HS-TRAIL */
    265	range[L] = 60 * scale;
    266	range[H] = INFINITY;
    267	val[CLK] = DIV_ROUND_UP(range[L] * factor - constant, t_half_byteck);
    268	range[L] = max(8 * t_ui, 60 * scale + 4 * t_ui);
    269	val[DATA] = DIV_ROUND_UP(range[L] * 3 / 2 - constant, t_half_byteck) - 2;
    270	dphy_set_timing_reg(regmap, TRAIL_TIME, val);
    271
    272	/* EXIT_TIME: */
    273	range[L] = 100 * scale;
    274	range[H] = INFINITY;
    275	val[CLK] = DIV_ROUND_UP(range[L] * factor, t_byteck) - 2;
    276	val[DATA] = val[CLK];
    277	dphy_set_timing_reg(regmap, EXIT_TIME, val);
    278
    279	/* CLKPOST_TIME: */
    280	range[L] = 60 * scale + 52 * t_ui;
    281	range[H] = INFINITY;
    282	val[CLK] = DIV_ROUND_UP(range[L] * factor, t_byteck) - 2;
    283	val[DATA] = val[CLK];
    284	dphy_set_timing_reg(regmap, CLKPOST_TIME, val);
    285
    286	/* SETTLE_TIME:
    287	 * This time is used for receiver. So for transmitter,
    288	 * it can be ignored.
    289	 */
    290
    291	/* TA_GO:
    292	 * transmitter drives bridge state(LP-00) before releasing control,
    293	 * reg 0x1f default value: 0x04, which is good.
    294	 */
    295
    296	/* TA_SURE:
    297	 * After LP-10 state and before bridge state(LP-00),
    298	 * reg 0x20 default value: 0x01, which is good.
    299	 */
    300
    301	/* TA_GET:
    302	 * receiver drives Bridge state(LP-00) before releasing control
    303	 * reg 0x21 default value: 0x03, which is good.
    304	 */
    305}