brintos

brintos / linux-shallow public Read only

0
0
Text · 23.9 KiB · 6405943 Raw
794 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 Rockchip Electronics Co. Ltd.4 *5 * Author: Wyon Bi <bivvy.bi@rock-chips.com>6 */7 8#include <linux/bits.h>9#include <linux/kernel.h>10#include <linux/clk.h>11#include <linux/iopoll.h>12#include <linux/clk-provider.h>13#include <linux/delay.h>14#include <linux/init.h>15#include <linux/mfd/syscon.h>16#include <linux/module.h>17#include <linux/of.h>18#include <linux/platform_device.h>19#include <linux/pm_runtime.h>20#include <linux/reset.h>21#include <linux/time64.h>22 23#include <linux/phy/phy.h>24#include <linux/phy/phy-mipi-dphy.h>25 26#define UPDATE(x, h, l)	(((x) << (l)) & GENMASK((h), (l)))27 28/*29 * The offset address[7:0] is distributed two parts, one from the bit7 to bit530 * is the first address, the other from the bit4 to bit0 is the second address.31 * when you configure the registers, you must set both of them. The Clock Lane32 * and Data Lane use the same registers with the same second address, but the33 * first address is different.34 */35#define FIRST_ADDRESS(x)		(((x) & 0x7) << 5)36#define SECOND_ADDRESS(x)		(((x) & 0x1f) << 0)37#define PHY_REG(first, second)		(FIRST_ADDRESS(first) | \38					 SECOND_ADDRESS(second))39 40/* Analog Register Part: reg00 */41#define BANDGAP_POWER_MASK			BIT(7)42#define BANDGAP_POWER_DOWN			BIT(7)43#define BANDGAP_POWER_ON			044#define LANE_EN_MASK				GENMASK(6, 2)45#define LANE_EN_CK				BIT(6)46#define LANE_EN_3				BIT(5)47#define LANE_EN_2				BIT(4)48#define LANE_EN_1				BIT(3)49#define LANE_EN_0				BIT(2)50#define POWER_WORK_MASK				GENMASK(1, 0)51#define POWER_WORK_ENABLE			UPDATE(1, 1, 0)52#define POWER_WORK_DISABLE			UPDATE(2, 1, 0)53/* Analog Register Part: reg01 */54#define REG_SYNCRST_MASK			BIT(2)55#define REG_SYNCRST_RESET			BIT(2)56#define REG_SYNCRST_NORMAL			057#define REG_LDOPD_MASK				BIT(1)58#define REG_LDOPD_POWER_DOWN			BIT(1)59#define REG_LDOPD_POWER_ON			060#define REG_PLLPD_MASK				BIT(0)61#define REG_PLLPD_POWER_DOWN			BIT(0)62#define REG_PLLPD_POWER_ON			063/* Analog Register Part: reg03 */64#define REG_FBDIV_HI_MASK			BIT(5)65#define REG_FBDIV_HI(x)				UPDATE((x >> 8), 5, 5)66#define REG_PREDIV_MASK				GENMASK(4, 0)67#define REG_PREDIV(x)				UPDATE(x, 4, 0)68/* Analog Register Part: reg04 */69#define REG_FBDIV_LO_MASK			GENMASK(7, 0)70#define REG_FBDIV_LO(x)				UPDATE(x, 7, 0)71/* Analog Register Part: reg05 */72#define SAMPLE_CLOCK_PHASE_MASK			GENMASK(6, 4)73#define SAMPLE_CLOCK_PHASE(x)			UPDATE(x, 6, 4)74#define CLOCK_LANE_SKEW_PHASE_MASK		GENMASK(2, 0)75#define CLOCK_LANE_SKEW_PHASE(x)		UPDATE(x, 2, 0)76/* Analog Register Part: reg06 */77#define DATA_LANE_3_SKEW_PHASE_MASK		GENMASK(6, 4)78#define DATA_LANE_3_SKEW_PHASE(x)		UPDATE(x, 6, 4)79#define DATA_LANE_2_SKEW_PHASE_MASK		GENMASK(2, 0)80#define DATA_LANE_2_SKEW_PHASE(x)		UPDATE(x, 2, 0)81/* Analog Register Part: reg07 */82#define DATA_LANE_1_SKEW_PHASE_MASK		GENMASK(6, 4)83#define DATA_LANE_1_SKEW_PHASE(x)		UPDATE(x, 6, 4)84#define DATA_LANE_0_SKEW_PHASE_MASK		GENMASK(2, 0)85#define DATA_LANE_0_SKEW_PHASE(x)		UPDATE(x, 2, 0)86/* Analog Register Part: reg08 */87#define PLL_POST_DIV_ENABLE_MASK		BIT(5)88#define PLL_POST_DIV_ENABLE			BIT(5)89#define SAMPLE_CLOCK_DIRECTION_MASK		BIT(4)90#define SAMPLE_CLOCK_DIRECTION_REVERSE		BIT(4)91#define SAMPLE_CLOCK_DIRECTION_FORWARD		092#define LOWFRE_EN_MASK				BIT(5)93#define PLL_OUTPUT_FREQUENCY_DIV_BY_1		094#define PLL_OUTPUT_FREQUENCY_DIV_BY_2		195/* Analog Register Part: reg0b */96#define CLOCK_LANE_VOD_RANGE_SET_MASK		GENMASK(3, 0)97#define CLOCK_LANE_VOD_RANGE_SET(x)		UPDATE(x, 3, 0)98#define VOD_MIN_RANGE				0x199#define VOD_MID_RANGE				0x3100#define VOD_BIG_RANGE				0x7101#define VOD_MAX_RANGE				0xf102/* Analog Register Part: reg1E */103#define PLL_MODE_SEL_MASK			GENMASK(6, 5)104#define PLL_MODE_SEL_LVDS_MODE			0105#define PLL_MODE_SEL_MIPI_MODE			BIT(5)106/* Digital Register Part: reg00 */107#define REG_DIG_RSTN_MASK			BIT(0)108#define REG_DIG_RSTN_NORMAL			BIT(0)109#define REG_DIG_RSTN_RESET			0110/* Digital Register Part: reg01 */111#define INVERT_TXCLKESC_MASK			BIT(1)112#define INVERT_TXCLKESC_ENABLE			BIT(1)113#define INVERT_TXCLKESC_DISABLE			0114#define INVERT_TXBYTECLKHS_MASK			BIT(0)115#define INVERT_TXBYTECLKHS_ENABLE		BIT(0)116#define INVERT_TXBYTECLKHS_DISABLE		0117/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg05 */118#define T_LPX_CNT_MASK				GENMASK(5, 0)119#define T_LPX_CNT(x)				UPDATE(x, 5, 0)120/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg06 */121#define T_HS_ZERO_CNT_HI_MASK			BIT(7)122#define T_HS_ZERO_CNT_HI(x)			UPDATE(x, 7, 7)123#define T_HS_PREPARE_CNT_MASK			GENMASK(6, 0)124#define T_HS_PREPARE_CNT(x)			UPDATE(x, 6, 0)125/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg07 */126#define T_HS_ZERO_CNT_LO_MASK			GENMASK(5, 0)127#define T_HS_ZERO_CNT_LO(x)			UPDATE(x, 5, 0)128/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg08 */129#define T_HS_TRAIL_CNT_MASK			GENMASK(6, 0)130#define T_HS_TRAIL_CNT(x)			UPDATE(x, 6, 0)131/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg09 */132#define T_HS_EXIT_CNT_LO_MASK			GENMASK(4, 0)133#define T_HS_EXIT_CNT_LO(x)			UPDATE(x, 4, 0)134/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0a */135#define T_CLK_POST_CNT_LO_MASK			GENMASK(3, 0)136#define T_CLK_POST_CNT_LO(x)			UPDATE(x, 3, 0)137/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0c */138#define LPDT_TX_PPI_SYNC_MASK			BIT(2)139#define LPDT_TX_PPI_SYNC_ENABLE			BIT(2)140#define LPDT_TX_PPI_SYNC_DISABLE		0141#define T_WAKEUP_CNT_HI_MASK			GENMASK(1, 0)142#define T_WAKEUP_CNT_HI(x)			UPDATE(x, 1, 0)143/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0d */144#define T_WAKEUP_CNT_LO_MASK			GENMASK(7, 0)145#define T_WAKEUP_CNT_LO(x)			UPDATE(x, 7, 0)146/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0e */147#define T_CLK_PRE_CNT_MASK			GENMASK(3, 0)148#define T_CLK_PRE_CNT(x)			UPDATE(x, 3, 0)149/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg10 */150#define T_CLK_POST_CNT_HI_MASK			GENMASK(7, 6)151#define T_CLK_POST_CNT_HI(x)			UPDATE(x, 7, 6)152#define T_TA_GO_CNT_MASK			GENMASK(5, 0)153#define T_TA_GO_CNT(x)				UPDATE(x, 5, 0)154/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg11 */155#define T_HS_EXIT_CNT_HI_MASK			BIT(6)156#define T_HS_EXIT_CNT_HI(x)			UPDATE(x, 6, 6)157#define T_TA_SURE_CNT_MASK			GENMASK(5, 0)158#define T_TA_SURE_CNT(x)			UPDATE(x, 5, 0)159/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg12 */160#define T_TA_WAIT_CNT_MASK			GENMASK(5, 0)161#define T_TA_WAIT_CNT(x)			UPDATE(x, 5, 0)162/* LVDS Register Part: reg00 */163#define LVDS_DIGITAL_INTERNAL_RESET_MASK	BIT(2)164#define LVDS_DIGITAL_INTERNAL_RESET_DISABLE	BIT(2)165#define LVDS_DIGITAL_INTERNAL_RESET_ENABLE	0166/* LVDS Register Part: reg01 */167#define LVDS_DIGITAL_INTERNAL_ENABLE_MASK	BIT(7)168#define LVDS_DIGITAL_INTERNAL_ENABLE		BIT(7)169#define LVDS_DIGITAL_INTERNAL_DISABLE		0170/* LVDS Register Part: reg03 */171#define MODE_ENABLE_MASK			GENMASK(2, 0)172#define TTL_MODE_ENABLE				BIT(2)173#define LVDS_MODE_ENABLE			BIT(1)174#define MIPI_MODE_ENABLE			BIT(0)175/* LVDS Register Part: reg0b */176#define LVDS_LANE_EN_MASK			GENMASK(7, 3)177#define LVDS_DATA_LANE0_EN			BIT(7)178#define LVDS_DATA_LANE1_EN			BIT(6)179#define LVDS_DATA_LANE2_EN			BIT(5)180#define LVDS_DATA_LANE3_EN			BIT(4)181#define LVDS_CLK_LANE_EN			BIT(3)182#define LVDS_PLL_POWER_MASK			BIT(2)183#define LVDS_PLL_POWER_OFF			BIT(2)184#define LVDS_PLL_POWER_ON			0185#define LVDS_BANDGAP_POWER_MASK			BIT(0)186#define LVDS_BANDGAP_POWER_DOWN			BIT(0)187#define LVDS_BANDGAP_POWER_ON			0188 189#define DSI_PHY_RSTZ		0xa0190#define PHY_ENABLECLK		BIT(2)191#define DSI_PHY_STATUS		0xb0192#define PHY_LOCK		BIT(0)193 194enum phy_max_rate {195	MAX_1GHZ,196	MAX_2_5GHZ,197};198 199struct inno_video_phy_plat_data {200	const struct inno_mipi_dphy_timing *inno_mipi_dphy_timing_table;201	const unsigned int num_timings;202	enum phy_max_rate max_rate;203};204 205struct inno_dsidphy {206	struct device *dev;207	struct clk *ref_clk;208	struct clk *pclk_phy;209	struct clk *pclk_host;210	const struct inno_video_phy_plat_data *pdata;211	void __iomem *phy_base;212	void __iomem *host_base;213	struct reset_control *rst;214	enum phy_mode mode;215	struct phy_configure_opts_mipi_dphy dphy_cfg;216 217	struct clk *pll_clk;218	struct {219		struct clk_hw hw;220		u8 prediv;221		u16 fbdiv;222		unsigned long rate;223	} pll;224};225 226enum {227	REGISTER_PART_ANALOG,228	REGISTER_PART_DIGITAL,229	REGISTER_PART_CLOCK_LANE,230	REGISTER_PART_DATA0_LANE,231	REGISTER_PART_DATA1_LANE,232	REGISTER_PART_DATA2_LANE,233	REGISTER_PART_DATA3_LANE,234	REGISTER_PART_LVDS,235};236 237struct inno_mipi_dphy_timing {238	unsigned long rate;239	u8 lpx;240	u8 hs_prepare;241	u8 clk_lane_hs_zero;242	u8 data_lane_hs_zero;243	u8 hs_trail;244};245 246static const247struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1ghz[] = {248	{ 110000000, 0x0, 0x20, 0x16, 0x02, 0x22},249	{ 150000000, 0x0, 0x06, 0x16, 0x03, 0x45},250	{ 200000000, 0x0, 0x18, 0x17, 0x04, 0x0b},251	{ 250000000, 0x0, 0x05, 0x17, 0x05, 0x16},252	{ 300000000, 0x0, 0x51, 0x18, 0x06, 0x2c},253	{ 400000000, 0x0, 0x64, 0x19, 0x07, 0x33},254	{ 500000000, 0x0, 0x20, 0x1b, 0x07, 0x4e},255	{ 600000000, 0x0, 0x6a, 0x1d, 0x08, 0x3a},256	{ 700000000, 0x0, 0x3e, 0x1e, 0x08, 0x6a},257	{ 800000000, 0x0, 0x21, 0x1f, 0x09, 0x29},258	{1000000000, 0x0, 0x09, 0x20, 0x09, 0x27},259};260 261static const262struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_2_5ghz[] = {263	{ 110000000, 0x02, 0x7f, 0x16, 0x02, 0x02},264	{ 150000000, 0x02, 0x7f, 0x16, 0x03, 0x02},265	{ 200000000, 0x02, 0x7f, 0x17, 0x04, 0x02},266	{ 250000000, 0x02, 0x7f, 0x17, 0x05, 0x04},267	{ 300000000, 0x02, 0x7f, 0x18, 0x06, 0x04},268	{ 400000000, 0x03, 0x7e, 0x19, 0x07, 0x04},269	{ 500000000, 0x03, 0x7c, 0x1b, 0x07, 0x08},270	{ 600000000, 0x03, 0x70, 0x1d, 0x08, 0x10},271	{ 700000000, 0x05, 0x40, 0x1e, 0x08, 0x30},272	{ 800000000, 0x05, 0x02, 0x1f, 0x09, 0x30},273	{1000000000, 0x05, 0x08, 0x20, 0x09, 0x30},274	{1200000000, 0x06, 0x03, 0x32, 0x14, 0x0f},275	{1400000000, 0x09, 0x03, 0x32, 0x14, 0x0f},276	{1600000000, 0x0d, 0x42, 0x36, 0x0e, 0x0f},277	{1800000000, 0x0e, 0x47, 0x7a, 0x0e, 0x0f},278	{2000000000, 0x11, 0x64, 0x7a, 0x0e, 0x0b},279	{2200000000, 0x13, 0x64, 0x7e, 0x15, 0x0b},280	{2400000000, 0x13, 0x33, 0x7f, 0x15, 0x6a},281	{2500000000, 0x15, 0x54, 0x7f, 0x15, 0x6a},282};283 284static void phy_update_bits(struct inno_dsidphy *inno,285			    u8 first, u8 second, u8 mask, u8 val)286{287	u32 reg = PHY_REG(first, second) << 2;288	unsigned int tmp, orig;289 290	orig = readl(inno->phy_base + reg);291	tmp = orig & ~mask;292	tmp |= val & mask;293	writel(tmp, inno->phy_base + reg);294}295 296static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno,297						unsigned long rate)298{299	unsigned long prate = clk_get_rate(inno->ref_clk);300	unsigned long best_freq = 0;301	unsigned long fref, fout;302	u8 min_prediv, max_prediv;303	u8 _prediv, best_prediv = 1;304	u16 _fbdiv, best_fbdiv = 1;305	u32 min_delta = UINT_MAX;306 307	/*308	 * The PLL output frequency can be calculated using a simple formula:309	 * PLL_Output_Frequency = (FREF / PREDIV * FBDIV) / 2310	 * PLL_Output_Frequency: it is equal to DDR-Clock-Frequency * 2311	 */312	fref = prate / 2;313	if (rate > 1000000000UL)314		fout = 1000000000UL;315	else316		fout = rate;317 318	/* 5Mhz < Fref / prediv < 40MHz */319	min_prediv = DIV_ROUND_UP(fref, 40000000);320	max_prediv = fref / 5000000;321 322	for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {323		u64 tmp;324		u32 delta;325 326		tmp = (u64)fout * _prediv;327		do_div(tmp, fref);328		_fbdiv = tmp;329 330		/*331		 * The possible settings of feedback divider are332		 * 12, 13, 14, 16, ~ 511333		 */334		if (_fbdiv == 15)335			continue;336 337		if (_fbdiv < 12 || _fbdiv > 511)338			continue;339 340		tmp = (u64)_fbdiv * fref;341		do_div(tmp, _prediv);342 343		delta = abs(fout - tmp);344		if (!delta) {345			best_prediv = _prediv;346			best_fbdiv = _fbdiv;347			best_freq = tmp;348			break;349		} else if (delta < min_delta) {350			best_prediv = _prediv;351			best_fbdiv = _fbdiv;352			best_freq = tmp;353			min_delta = delta;354		}355	}356 357	if (best_freq) {358		inno->pll.prediv = best_prediv;359		inno->pll.fbdiv = best_fbdiv;360		inno->pll.rate = best_freq;361	}362 363	return best_freq;364}365 366static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)367{368	struct phy_configure_opts_mipi_dphy *cfg = &inno->dphy_cfg;369	const struct inno_mipi_dphy_timing *timings;370	u32 t_txbyteclkhs, t_txclkesc;371	u32 txbyteclkhs, txclkesc, esc_clk_div;372	u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait;373	u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero;374	unsigned int i;375 376	timings = inno->pdata->inno_mipi_dphy_timing_table;377 378	inno_dsidphy_pll_calc_rate(inno, cfg->hs_clk_rate);379 380	/* Select MIPI mode */381	phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,382			MODE_ENABLE_MASK, MIPI_MODE_ENABLE);383	/* Configure PLL */384	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,385			REG_PREDIV_MASK, REG_PREDIV(inno->pll.prediv));386	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,387			REG_FBDIV_HI_MASK, REG_FBDIV_HI(inno->pll.fbdiv));388	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04,389			REG_FBDIV_LO_MASK, REG_FBDIV_LO(inno->pll.fbdiv));390	if (inno->pdata->max_rate == MAX_2_5GHZ) {391		phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,392				PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);393		phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b,394				CLOCK_LANE_VOD_RANGE_SET_MASK,395				CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));396	}397	/* Enable PLL and LDO */398	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,399			REG_LDOPD_MASK | REG_PLLPD_MASK,400			REG_LDOPD_POWER_ON | REG_PLLPD_POWER_ON);401	/* Reset analog */402	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,403			REG_SYNCRST_MASK, REG_SYNCRST_RESET);404	udelay(1);405	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,406			REG_SYNCRST_MASK, REG_SYNCRST_NORMAL);407	/* Reset digital */408	phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,409			REG_DIG_RSTN_MASK, REG_DIG_RSTN_RESET);410	udelay(1);411	phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,412			REG_DIG_RSTN_MASK, REG_DIG_RSTN_NORMAL);413 414	txbyteclkhs = inno->pll.rate / 8;415	t_txbyteclkhs = div_u64(PSEC_PER_SEC, txbyteclkhs);416 417	esc_clk_div = DIV_ROUND_UP(txbyteclkhs, 20000000);418	txclkesc = txbyteclkhs / esc_clk_div;419	t_txclkesc = div_u64(PSEC_PER_SEC, txclkesc);420 421	/*422	 * The value of counter for HS Ths-exit423	 * Ths-exit = Tpin_txbyteclkhs * value424	 */425	hs_exit = DIV_ROUND_UP(cfg->hs_exit, t_txbyteclkhs);426	/*427	 * The value of counter for HS Tclk-post428	 * Tclk-post = Tpin_txbyteclkhs * value429	 */430	clk_post = DIV_ROUND_UP(cfg->clk_post, t_txbyteclkhs);431	/*432	 * The value of counter for HS Tclk-pre433	 * Tclk-pre = Tpin_txbyteclkhs * value434	 */435	clk_pre = DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE);436 437	/*438	 * The value of counter for HS Tta-go439	 * Tta-go for turnaround440	 * Tta-go = Ttxclkesc * value441	 */442	ta_go = DIV_ROUND_UP(cfg->ta_go, t_txclkesc);443	/*444	 * The value of counter for HS Tta-sure445	 * Tta-sure for turnaround446	 * Tta-sure = Ttxclkesc * value447	 */448	ta_sure = DIV_ROUND_UP(cfg->ta_sure, t_txclkesc);449	/*450	 * The value of counter for HS Tta-wait451	 * Tta-wait for turnaround452	 * Tta-wait = Ttxclkesc * value453	 */454	ta_wait = DIV_ROUND_UP(cfg->ta_get, t_txclkesc);455 456	for (i = 0; i < inno->pdata->num_timings; i++)457		if (inno->pll.rate <= timings[i].rate)458			break;459 460	if (i == inno->pdata->num_timings)461		--i;462 463	/*464	 * The value of counter for HS Tlpx Time465	 * Tlpx = Tpin_txbyteclkhs * (2 + value)466	 */467	if (inno->pdata->max_rate == MAX_1GHZ) {468		lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs);469		if (lpx >= 2)470			lpx -= 2;471	} else472		lpx = timings[i].lpx;473 474	hs_prepare = timings[i].hs_prepare;475	hs_trail = timings[i].hs_trail;476	clk_lane_hs_zero = timings[i].clk_lane_hs_zero;477	data_lane_hs_zero = timings[i].data_lane_hs_zero;478	wakeup = 0x3ff;479 480	for (i = REGISTER_PART_CLOCK_LANE; i <= REGISTER_PART_DATA3_LANE; i++) {481		if (i == REGISTER_PART_CLOCK_LANE)482			hs_zero = clk_lane_hs_zero;483		else484			hs_zero = data_lane_hs_zero;485 486		phy_update_bits(inno, i, 0x05, T_LPX_CNT_MASK,487				T_LPX_CNT(lpx));488		phy_update_bits(inno, i, 0x06, T_HS_PREPARE_CNT_MASK,489				T_HS_PREPARE_CNT(hs_prepare));490		if (inno->pdata->max_rate == MAX_2_5GHZ)491			phy_update_bits(inno, i, 0x06, T_HS_ZERO_CNT_HI_MASK,492					T_HS_ZERO_CNT_HI(hs_zero >> 6));493		phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_LO_MASK,494				T_HS_ZERO_CNT_LO(hs_zero));495		phy_update_bits(inno, i, 0x08, T_HS_TRAIL_CNT_MASK,496				T_HS_TRAIL_CNT(hs_trail));497		if (inno->pdata->max_rate == MAX_2_5GHZ)498			phy_update_bits(inno, i, 0x11, T_HS_EXIT_CNT_HI_MASK,499					T_HS_EXIT_CNT_HI(hs_exit >> 5));500		phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_LO_MASK,501				T_HS_EXIT_CNT_LO(hs_exit));502		if (inno->pdata->max_rate == MAX_2_5GHZ)503			phy_update_bits(inno, i, 0x10, T_CLK_POST_CNT_HI_MASK,504					T_CLK_POST_CNT_HI(clk_post >> 4));505		phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_LO_MASK,506				T_CLK_POST_CNT_LO(clk_post));507		phy_update_bits(inno, i, 0x0e, T_CLK_PRE_CNT_MASK,508				T_CLK_PRE_CNT(clk_pre));509		phy_update_bits(inno, i, 0x0c, T_WAKEUP_CNT_HI_MASK,510				T_WAKEUP_CNT_HI(wakeup >> 8));511		phy_update_bits(inno, i, 0x0d, T_WAKEUP_CNT_LO_MASK,512				T_WAKEUP_CNT_LO(wakeup));513		phy_update_bits(inno, i, 0x10, T_TA_GO_CNT_MASK,514				T_TA_GO_CNT(ta_go));515		phy_update_bits(inno, i, 0x11, T_TA_SURE_CNT_MASK,516				T_TA_SURE_CNT(ta_sure));517		phy_update_bits(inno, i, 0x12, T_TA_WAIT_CNT_MASK,518				T_TA_WAIT_CNT(ta_wait));519	}520 521	/* Enable all lanes on analog part */522	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,523			LANE_EN_MASK, LANE_EN_CK | LANE_EN_3 | LANE_EN_2 |524			LANE_EN_1 | LANE_EN_0);525}526 527static void inno_dsidphy_lvds_mode_enable(struct inno_dsidphy *inno)528{529	u8 prediv = 2;530	u16 fbdiv = 28;531 532	/* Sample clock reverse direction */533	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,534			SAMPLE_CLOCK_DIRECTION_MASK | LOWFRE_EN_MASK,535			SAMPLE_CLOCK_DIRECTION_REVERSE |536			PLL_OUTPUT_FREQUENCY_DIV_BY_1);537 538	/* Select LVDS mode */539	phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,540			MODE_ENABLE_MASK, LVDS_MODE_ENABLE);541	/* Configure PLL */542	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,543			REG_PREDIV_MASK, REG_PREDIV(prediv));544	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,545			REG_FBDIV_HI_MASK, REG_FBDIV_HI(fbdiv));546	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04,547			REG_FBDIV_LO_MASK, REG_FBDIV_LO(fbdiv));548	phy_update_bits(inno, REGISTER_PART_LVDS, 0x08, 0xff, 0xfc);549	/* Enable PLL and Bandgap */550	phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,551			LVDS_PLL_POWER_MASK | LVDS_BANDGAP_POWER_MASK,552			LVDS_PLL_POWER_ON | LVDS_BANDGAP_POWER_ON);553 554	msleep(20);555 556	/* Select PLL mode */557	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x1e,558			PLL_MODE_SEL_MASK, PLL_MODE_SEL_LVDS_MODE);559 560	/* Reset LVDS digital logic */561	phy_update_bits(inno, REGISTER_PART_LVDS, 0x00,562			LVDS_DIGITAL_INTERNAL_RESET_MASK,563			LVDS_DIGITAL_INTERNAL_RESET_ENABLE);564	udelay(1);565	phy_update_bits(inno, REGISTER_PART_LVDS, 0x00,566			LVDS_DIGITAL_INTERNAL_RESET_MASK,567			LVDS_DIGITAL_INTERNAL_RESET_DISABLE);568	/* Enable LVDS digital logic */569	phy_update_bits(inno, REGISTER_PART_LVDS, 0x01,570			LVDS_DIGITAL_INTERNAL_ENABLE_MASK,571			LVDS_DIGITAL_INTERNAL_ENABLE);572	/* Enable LVDS analog driver */573	phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,574			LVDS_LANE_EN_MASK, LVDS_CLK_LANE_EN |575			LVDS_DATA_LANE0_EN | LVDS_DATA_LANE1_EN |576			LVDS_DATA_LANE2_EN | LVDS_DATA_LANE3_EN);577}578 579static int inno_dsidphy_power_on(struct phy *phy)580{581	struct inno_dsidphy *inno = phy_get_drvdata(phy);582 583	clk_prepare_enable(inno->pclk_phy);584	clk_prepare_enable(inno->ref_clk);585	pm_runtime_get_sync(inno->dev);586 587	/* Bandgap power on */588	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,589			BANDGAP_POWER_MASK, BANDGAP_POWER_ON);590	/* Enable power work */591	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,592			POWER_WORK_MASK, POWER_WORK_ENABLE);593 594	switch (inno->mode) {595	case PHY_MODE_MIPI_DPHY:596		inno_dsidphy_mipi_mode_enable(inno);597		break;598	case PHY_MODE_LVDS:599		inno_dsidphy_lvds_mode_enable(inno);600		break;601	default:602		return -EINVAL;603	}604 605	return 0;606}607 608static int inno_dsidphy_power_off(struct phy *phy)609{610	struct inno_dsidphy *inno = phy_get_drvdata(phy);611 612	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00, LANE_EN_MASK, 0);613	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,614			REG_LDOPD_MASK | REG_PLLPD_MASK,615			REG_LDOPD_POWER_DOWN | REG_PLLPD_POWER_DOWN);616	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,617			POWER_WORK_MASK, POWER_WORK_DISABLE);618	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,619			BANDGAP_POWER_MASK, BANDGAP_POWER_DOWN);620 621	phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b, LVDS_LANE_EN_MASK, 0);622	phy_update_bits(inno, REGISTER_PART_LVDS, 0x01,623			LVDS_DIGITAL_INTERNAL_ENABLE_MASK,624			LVDS_DIGITAL_INTERNAL_DISABLE);625	phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,626			LVDS_PLL_POWER_MASK | LVDS_BANDGAP_POWER_MASK,627			LVDS_PLL_POWER_OFF | LVDS_BANDGAP_POWER_DOWN);628 629	pm_runtime_put(inno->dev);630	clk_disable_unprepare(inno->ref_clk);631	clk_disable_unprepare(inno->pclk_phy);632 633	return 0;634}635 636static int inno_dsidphy_set_mode(struct phy *phy, enum phy_mode mode,637				   int submode)638{639	struct inno_dsidphy *inno = phy_get_drvdata(phy);640 641	switch (mode) {642	case PHY_MODE_MIPI_DPHY:643	case PHY_MODE_LVDS:644		inno->mode = mode;645		break;646	default:647		return -EINVAL;648	}649 650	return 0;651}652 653static int inno_dsidphy_configure(struct phy *phy,654				  union phy_configure_opts *opts)655{656	struct inno_dsidphy *inno = phy_get_drvdata(phy);657	int ret;658 659	if (inno->mode != PHY_MODE_MIPI_DPHY)660		return -EINVAL;661 662	ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);663	if (ret)664		return ret;665 666	memcpy(&inno->dphy_cfg, &opts->mipi_dphy, sizeof(inno->dphy_cfg));667 668	return 0;669}670 671static const struct phy_ops inno_dsidphy_ops = {672	.configure = inno_dsidphy_configure,673	.set_mode = inno_dsidphy_set_mode,674	.power_on = inno_dsidphy_power_on,675	.power_off = inno_dsidphy_power_off,676	.owner = THIS_MODULE,677};678 679static const struct inno_video_phy_plat_data max_1ghz_video_phy_plat_data = {680	.inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1ghz,681	.num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1ghz),682	.max_rate = MAX_1GHZ,683};684 685static const struct inno_video_phy_plat_data max_2_5ghz_video_phy_plat_data = {686	.inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_2_5ghz,687	.num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_2_5ghz),688	.max_rate = MAX_2_5GHZ,689};690 691static int inno_dsidphy_probe(struct platform_device *pdev)692{693	struct device *dev = &pdev->dev;694	struct inno_dsidphy *inno;695	struct phy_provider *phy_provider;696	struct phy *phy;697	int ret;698 699	inno = devm_kzalloc(dev, sizeof(*inno), GFP_KERNEL);700	if (!inno)701		return -ENOMEM;702 703	inno->dev = dev;704	inno->pdata = of_device_get_match_data(inno->dev);705	platform_set_drvdata(pdev, inno);706 707	inno->phy_base = devm_platform_ioremap_resource(pdev, 0);708	if (IS_ERR(inno->phy_base))709		return PTR_ERR(inno->phy_base);710 711	inno->ref_clk = devm_clk_get(dev, "ref");712	if (IS_ERR(inno->ref_clk)) {713		ret = PTR_ERR(inno->ref_clk);714		dev_err(dev, "failed to get ref clock: %d\n", ret);715		return ret;716	}717 718	inno->pclk_phy = devm_clk_get(dev, "pclk");719	if (IS_ERR(inno->pclk_phy)) {720		ret = PTR_ERR(inno->pclk_phy);721		dev_err(dev, "failed to get phy pclk: %d\n", ret);722		return ret;723	}724 725	inno->rst = devm_reset_control_get(dev, "apb");726	if (IS_ERR(inno->rst)) {727		ret = PTR_ERR(inno->rst);728		dev_err(dev, "failed to get system reset control: %d\n", ret);729		return ret;730	}731 732	phy = devm_phy_create(dev, NULL, &inno_dsidphy_ops);733	if (IS_ERR(phy)) {734		ret = PTR_ERR(phy);735		dev_err(dev, "failed to create phy: %d\n", ret);736		return ret;737	}738 739	phy_set_drvdata(phy, inno);740 741	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);742	if (IS_ERR(phy_provider)) {743		ret = PTR_ERR(phy_provider);744		dev_err(dev, "failed to register phy provider: %d\n", ret);745		return ret;746	}747 748	pm_runtime_enable(dev);749 750	return 0;751}752 753static void inno_dsidphy_remove(struct platform_device *pdev)754{755	struct inno_dsidphy *inno = platform_get_drvdata(pdev);756 757	pm_runtime_disable(inno->dev);758}759 760static const struct of_device_id inno_dsidphy_of_match[] = {761	{762		.compatible = "rockchip,px30-dsi-dphy",763		.data = &max_1ghz_video_phy_plat_data,764	}, {765		.compatible = "rockchip,rk3128-dsi-dphy",766		.data = &max_1ghz_video_phy_plat_data,767	}, {768		.compatible = "rockchip,rk3368-dsi-dphy",769		.data = &max_1ghz_video_phy_plat_data,770	}, {771		.compatible = "rockchip,rk3568-dsi-dphy",772		.data = &max_2_5ghz_video_phy_plat_data,773	}, {774		.compatible = "rockchip,rv1126-dsi-dphy",775		.data = &max_2_5ghz_video_phy_plat_data,776	},777	{}778};779MODULE_DEVICE_TABLE(of, inno_dsidphy_of_match);780 781static struct platform_driver inno_dsidphy_driver = {782	.driver = {783		.name = "inno-dsidphy",784		.of_match_table	= of_match_ptr(inno_dsidphy_of_match),785	},786	.probe = inno_dsidphy_probe,787	.remove_new = inno_dsidphy_remove,788};789module_platform_driver(inno_dsidphy_driver);790 791MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");792MODULE_DESCRIPTION("Innosilicon MIPI/LVDS/TTL Video Combo PHY driver");793MODULE_LICENSE("GPL v2");794