brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · f4956a4 Raw
188 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * Copyright (C) 2013 NVIDIA Corporation4 * Copyright (C) 2018 Cadence Design Systems Inc.5 */6 7#include <linux/errno.h>8#include <linux/export.h>9#include <linux/kernel.h>10#include <linux/time64.h>11 12#include <linux/phy/phy.h>13#include <linux/phy/phy-mipi-dphy.h>14 15/*16 * Minimum D-PHY timings based on MIPI D-PHY specification. Derived17 * from the valid ranges specified in Section 6.9, Table 14, Page 4118 * of the D-PHY specification (v1.2).19 */20static int phy_mipi_dphy_calc_config(unsigned long pixel_clock,21				     unsigned int bpp,22				     unsigned int lanes,23				     unsigned long long hs_clk_rate,24				     struct phy_configure_opts_mipi_dphy *cfg)25{26	unsigned long long ui;27 28	if (!cfg)29		return -EINVAL;30 31	if (!hs_clk_rate) {32		hs_clk_rate = pixel_clock * bpp;33		do_div(hs_clk_rate, lanes);34	}35 36	ui = ALIGN(PSEC_PER_SEC, hs_clk_rate);37	do_div(ui, hs_clk_rate);38 39	cfg->clk_miss = 0;40	cfg->clk_post = 60000 + 52 * ui;41	cfg->clk_pre = 8;42	cfg->clk_prepare = 38000;43	cfg->clk_settle = 95000;44	cfg->clk_term_en = 0;45	cfg->clk_trail = 60000;46	cfg->clk_zero = 262000;47	cfg->d_term_en = 0;48	cfg->eot = 0;49	cfg->hs_exit = 100000;50	cfg->hs_prepare = 40000 + 4 * ui;51	cfg->hs_zero = 105000 + 6 * ui;52	cfg->hs_settle = 85000 + 6 * ui;53	cfg->hs_skip = 40000;54 55	/*56	 * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40)57	 * contains this formula as:58	 *59	 *     T_HS-TRAIL = max(n * 8 * ui, 60 + n * 4 * ui)60	 *61	 * where n = 1 for forward-direction HS mode and n = 4 for reverse-62	 * direction HS mode. There's only one setting and this function does63	 * not parameterize on anything other that ui, so this code will64	 * assumes that reverse-direction HS mode is supported and uses n = 4.65	 */66	cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);67 68	cfg->init = 100;69	cfg->lpx = 50000;70	cfg->ta_get = 5 * cfg->lpx;71	cfg->ta_go = 4 * cfg->lpx;72	cfg->ta_sure = cfg->lpx;73	cfg->wakeup = 1000;74 75	cfg->hs_clk_rate = hs_clk_rate;76	cfg->lanes = lanes;77 78	return 0;79}80 81int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,82				     unsigned int bpp,83				     unsigned int lanes,84				     struct phy_configure_opts_mipi_dphy *cfg)85{86	return phy_mipi_dphy_calc_config(pixel_clock, bpp, lanes, 0, cfg);87 88}89EXPORT_SYMBOL(phy_mipi_dphy_get_default_config);90 91int phy_mipi_dphy_get_default_config_for_hsclk(unsigned long long hs_clk_rate,92					       unsigned int lanes,93					       struct phy_configure_opts_mipi_dphy *cfg)94{95	if (!hs_clk_rate)96		return -EINVAL;97 98	return phy_mipi_dphy_calc_config(0, 0, lanes, hs_clk_rate, cfg);99 100}101EXPORT_SYMBOL(phy_mipi_dphy_get_default_config_for_hsclk);102 103/*104 * Validate D-PHY configuration according to MIPI D-PHY specification105 * (v1.2, Section Section 6.9 "Global Operation Timing Parameters").106 */107int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg)108{109	unsigned long long ui;110 111	if (!cfg)112		return -EINVAL;113 114	ui = ALIGN(PSEC_PER_SEC, cfg->hs_clk_rate);115	do_div(ui, cfg->hs_clk_rate);116 117	if (cfg->clk_miss > 60000)118		return -EINVAL;119 120	if (cfg->clk_post < (60000 + 52 * ui))121		return -EINVAL;122 123	if (cfg->clk_pre < 8)124		return -EINVAL;125 126	if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000)127		return -EINVAL;128 129	if (cfg->clk_settle < 95000 || cfg->clk_settle > 300000)130		return -EINVAL;131 132	if (cfg->clk_term_en > 38000)133		return -EINVAL;134 135	if (cfg->clk_trail < 60000)136		return -EINVAL;137 138	if ((cfg->clk_prepare + cfg->clk_zero) < 300000)139		return -EINVAL;140 141	if (cfg->d_term_en > (35000 + 4 * ui))142		return -EINVAL;143 144	if (cfg->eot > (105000 + 12 * ui))145		return -EINVAL;146 147	if (cfg->hs_exit < 100000)148		return -EINVAL;149 150	if (cfg->hs_prepare < (40000 + 4 * ui) ||151	    cfg->hs_prepare > (85000 + 6 * ui))152		return -EINVAL;153 154	if ((cfg->hs_prepare + cfg->hs_zero) < (145000 + 10 * ui))155		return -EINVAL;156 157	if ((cfg->hs_settle < (85000 + 6 * ui)) ||158	    (cfg->hs_settle > (145000 + 10 * ui)))159		return -EINVAL;160 161	if (cfg->hs_skip < 40000 || cfg->hs_skip > (55000 + 4 * ui))162		return -EINVAL;163 164	if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui))165		return -EINVAL;166 167	if (cfg->init < 100)168		return -EINVAL;169 170	if (cfg->lpx < 50000)171		return -EINVAL;172 173	if (cfg->ta_get != (5 * cfg->lpx))174		return -EINVAL;175 176	if (cfg->ta_go != (4 * cfg->lpx))177		return -EINVAL;178 179	if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx))180		return -EINVAL;181 182	if (cfg->wakeup < 1000)183		return -EINVAL;184 185	return 0;186}187EXPORT_SYMBOL(phy_mipi_dphy_config_validate);188