88 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
 | |
|  *
 | |
|  * Author: Guochun Huang <hero.huang@rock-chips.com>
 | |
|  */
 | |
| 
 | |
| #include <linux/kernel.h>
 | |
| #include "rkx110_x120.h"
 | |
| #include "serdes_combphy.h"
 | |
| 
 | |
| int serdes_combphy_write(struct rk_serdes *serdes, u8 remote_id, u32 reg, u32 val)
 | |
| {
 | |
| 	struct i2c_client *client = serdes->chip[remote_id].client;
 | |
| 
 | |
| 	return serdes->i2c_write_reg(client, reg, val);
 | |
| }
 | |
| 
 | |
| int serdes_combphy_read(struct rk_serdes *serdes, u8 remote_id, u32 reg, u32 *val)
 | |
| {
 | |
| 	struct i2c_client *client = serdes->chip[remote_id].client;
 | |
| 
 | |
| 	return serdes->i2c_read_reg(client, reg, val);
 | |
| }
 | |
| 
 | |
| int serdes_combphy_update_bits(struct rk_serdes *serdes, u8 remote_id,
 | |
| 			       u32 reg, u32 mask, u32 val)
 | |
| {
 | |
| 	struct i2c_client *client = serdes->chip[remote_id].client;
 | |
| 
 | |
| 	return serdes->i2c_update_bits(client, reg, mask, val);
 | |
| }
 | |
| 
 | |
| void serdes_combphy_get_default_config(u64 hs_clk_rate,
 | |
| 				       struct configure_opts_combphy *cfg)
 | |
| {
 | |
| 	unsigned long long ui;
 | |
| 
 | |
| 	ui = ALIGN(NSEC_PER_SEC, hs_clk_rate);
 | |
| 	do_div(ui, hs_clk_rate);
 | |
| 
 | |
| 	cfg->clk_miss = 0;
 | |
| 	cfg->clk_post = 60 + 52 * ui;
 | |
| 	cfg->clk_pre = 8;
 | |
| 	cfg->clk_prepare = 38;
 | |
| 	cfg->clk_settle = 95;
 | |
| 	cfg->clk_term_en = 0;
 | |
| 	cfg->clk_trail = 60;
 | |
| 	cfg->clk_zero = 262;
 | |
| 	cfg->d_term_en = 0;
 | |
| 	cfg->eot = 0;
 | |
| 	cfg->hs_exit = 100;
 | |
| 	cfg->hs_prepare = 40 + 4 * ui;
 | |
| 	cfg->hs_zero = 105 + 6 * ui;
 | |
| 	cfg->hs_settle = 85 + 6 * ui;
 | |
| 	cfg->hs_skip = 40;
 | |
| 
 | |
| 	/*
 | |
| 	 * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40)
 | |
| 	 * contains this formula as:
 | |
| 	 *
 | |
| 	 *     T_HS-TRAIL = max(n * 8 * ui, 60 + n * 4 * ui)
 | |
| 	 *
 | |
| 	 * where n = 1 for forward-direction HS mode and n = 4 for reverse-
 | |
| 	 * direction HS mode. There's only one setting and this function does
 | |
| 	 * not parameterize on anything other that ui, so this code will
 | |
| 	 * assumes that reverse-direction HS mode is supported and uses n = 4.
 | |
| 	 */
 | |
| 	cfg->hs_trail = max(4 * 8 * ui, 60 + 4 * 4 * ui);
 | |
| 
 | |
| 	/*
 | |
| 	 * Note that TINIT is considered a protocol-dependent parameter, and
 | |
| 	 * thus the exact requirements for TINIT,MASTER and TINIT,SLAVE (transmitter
 | |
| 	 * and receiver initialization Stop state lengths, respectively,) are defined
 | |
| 	 * by the protocol layer specification and are outside the scope of this document.
 | |
| 	 * However, the D-PHY specification does place a minimum bound on the lengths of
 | |
| 	 * TINIT,MASTER and TINIT,SLAVE, which each shall be no less than 100 µs. A protocol
 | |
| 	 * layer specification using the D-PHY specification may specify any values greater
 | |
| 	 * than this limit, for example, TINIT,MASTER ≥ 1 ms and TINIT,SLAVE = 500 to 800 µs
 | |
| 	 */
 | |
| 	cfg->init = NSEC_PER_SEC / MSEC_PER_SEC;
 | |
| 	cfg->lpx = 50;
 | |
| 	cfg->ta_get = 5 * cfg->lpx;
 | |
| 	cfg->ta_go = 4 * cfg->lpx;
 | |
| 	cfg->ta_sure = cfg->lpx;
 | |
| 	cfg->wakeup = NSEC_PER_SEC / MSEC_PER_SEC;
 | |
| }
 |