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}