diff mbox

[2/4] phy: rockchip-typec: support variable phy config value

Message ID 1525421338-1021-2-git-send-email-hl@rock-chips.com (mailing list archive)
State New, archived
Headers show

Commit Message

huang lin May 4, 2018, 8:08 a.m. UTC
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Signed-off-by: Lin Huang <hl@rock-chips.com>
---
 drivers/phy/rockchip/phy-rockchip-typec.c | 286 +++++++++++++++++++-----------
 include/soc/rockchip/rockchip_phy_typec.h |  72 ++++++++
 2 files changed, 259 insertions(+), 99 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

Comments

kernel test robot May 4, 2018, 5:51 p.m. UTC | #1
Hi Lin,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on rockchip/for-next]
[also build test WARNING on v4.17-rc3 next-20180504]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Lin-Huang/drm-rockchip-add-transfer-function-for-cdn-dp/20180504-235745
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All warnings (new ones prefixed by >>):

   drivers/phy/rockchip/phy-rockchip-typec.c: In function 'rockchip_typec_phy_probe':
>> drivers/phy/rockchip/phy-rockchip-typec.c:1227:21: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
       tcphy->port_cfgs = &phy_cfgs[index];
                        ^
   drivers/phy/rockchip/phy-rockchip-typec.c: In function 'tcphy_cfg_dp_pll.isra.2':
>> drivers/phy/rockchip/phy-rockchip-typec.c:512:6: warning: 'clk_ctrl' may be used uninitialized in this function [-Wmaybe-uninitialized]
     u32 clk_ctrl;
         ^~~~~~~~
>> drivers/phy/rockchip/phy-rockchip-typec.c:511:18: warning: 'phy_cfg' may be used uninitialized in this function [-Wmaybe-uninitialized]
     struct phy_reg *phy_cfg;
                     ^~~~~~~

vim +/const +1227 drivers/phy/rockchip/phy-rockchip-typec.c

e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1194  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1195  static int rockchip_typec_phy_probe(struct platform_device *pdev)
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1196  {
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1197  	struct device *dev = &pdev->dev;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1198  	struct device_node *np = dev->of_node;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1199  	struct device_node *child_np;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1200  	struct rockchip_typec_phy *tcphy;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1201  	struct phy_provider *phy_provider;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1202  	struct resource *res;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1203  	const struct rockchip_usb3phy_port_cfg *phy_cfgs;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1204  	const struct of_device_id *match;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1205  	int index, ret;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1206  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1207  	tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1208  	if (!tcphy)
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1209  		return -ENOMEM;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1210  
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1211  	match = of_match_device(dev->driver->of_match_table, dev);
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1212  	if (!match || !match->data) {
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1213  		dev_err(dev, "phy configs are not assigned!\n");
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1214  		return -EINVAL;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1215  	}
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1216  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1217  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1218  	tcphy->base = devm_ioremap_resource(dev, res);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1219  	if (IS_ERR(tcphy->base))
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1220  		return PTR_ERR(tcphy->base);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1221  
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1222  	phy_cfgs = match->data;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1223  	/* find out a proper config which can be matched with dt. */
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1224  	index = 0;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1225  	while (phy_cfgs[index].reg) {
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1226  		if (phy_cfgs[index].reg == res->start) {
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16 @1227  			tcphy->port_cfgs = &phy_cfgs[index];
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1228  			break;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1229  		}
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1230  
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1231  		++index;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1232  	}
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1233  
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1234  	if (!tcphy->port_cfgs) {
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1235  		dev_err(dev, "no phy-config can be matched with %s node\n",
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1236  			np->name);
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1237  		return -EINVAL;
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1238  	}
0fbc47d9 drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-02-16  1239  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1240  	ret = tcphy_parse_dt(tcphy, dev);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1241  	if (ret)
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1242  		return ret;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1243  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1244  	tcphy->dev = dev;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1245  	platform_set_drvdata(pdev, tcphy);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1246  	mutex_init(&tcphy->lock);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1247  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1248  	typec_phy_pre_init(tcphy);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1249  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1250  	tcphy->extcon = extcon_get_edev_by_phandle(dev, 0);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1251  	if (IS_ERR(tcphy->extcon)) {
ec1fcd7b drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-03-01  1252  		if (PTR_ERR(tcphy->extcon) == -ENODEV) {
ec1fcd7b drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-03-01  1253  			tcphy->extcon = NULL;
ec1fcd7b drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-03-01  1254  		} else {
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1255  			if (PTR_ERR(tcphy->extcon) != -EPROBE_DEFER)
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1256  				dev_err(dev, "Invalid or missing extcon\n");
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1257  			return PTR_ERR(tcphy->extcon);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1258  		}
ec1fcd7b drivers/phy/rockchip/phy-rockchip-typec.c Enric Balletbo i Serra 2018-03-01  1259  	}
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1260  
cdb051be drivers/phy/rockchip/phy-rockchip-typec.c Lin Huang              2018-05-04  1261  	tcphy->typec_phy_config = type_c_dp_phy_config;
2a4d5962 drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-09-07  1262  	pm_runtime_enable(dev);
2a4d5962 drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-09-07  1263  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1264  	for_each_available_child_of_node(np, child_np) {
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1265  		struct phy *phy;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1266  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1267  		if (!of_node_cmp(child_np->name, "dp-port"))
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1268  			phy = devm_phy_create(dev, child_np,
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1269  					      &rockchip_dp_phy_ops);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1270  		else if (!of_node_cmp(child_np->name, "usb3-port"))
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1271  			phy = devm_phy_create(dev, child_np,
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1272  					      &rockchip_usb3_phy_ops);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1273  		else
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1274  			continue;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1275  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1276  		if (IS_ERR(phy)) {
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1277  			dev_err(dev, "failed to create phy: %s\n",
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1278  				child_np->name);
3cb0ab6e drivers/phy/rockchip/phy-rockchip-typec.c Chris Zhong            2016-09-08  1279  			pm_runtime_disable(dev);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1280  			return PTR_ERR(phy);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1281  		}
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1282  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1283  		phy_set_drvdata(phy, tcphy);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1284  	}
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1285  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1286  	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1287  	if (IS_ERR(phy_provider)) {
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1288  		dev_err(dev, "Failed to register phy provider\n");
3cb0ab6e drivers/phy/rockchip/phy-rockchip-typec.c Chris Zhong            2016-09-08  1289  		pm_runtime_disable(dev);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1290  		return PTR_ERR(phy_provider);
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1291  	}
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1292  
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1293  	return 0;
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1294  }
e96be45c drivers/phy/phy-rockchip-typec.c          Chris Zhong            2016-08-23  1295  

:::::: The code at line 1227 was first introduced by commit
:::::: 0fbc47d9e426a934668dbfeb0db26da6f0b7f35c phy: rockchip-typec: deprecate some DT properties for various register fields.

:::::: TO: Enric Balletbo i Serra <enric.balletbo@collabora.com>
:::::: CC: Kishon Vijay Abraham I <kishon@ti.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Enric Balletbo Serra May 7, 2018, 1:59 p.m. UTC | #2
Hi Lin,

Thanks for the patch, apart from the new build warnings introduced
some more comments below.

2018-05-04 10:08 GMT+02:00 Lin Huang <hl@rock-chips.com>:
> the phy config values used to fix in dp firmware, but some boards
> need change these values to do training and get the better eye diagram
> result. So support that in phy driver.
>
> Signed-off-by: Chris Zhong <zyw@rock-chips.com>
> Signed-off-by: Lin Huang <hl@rock-chips.com>
> ---
>  drivers/phy/rockchip/phy-rockchip-typec.c | 286 +++++++++++++++++++-----------
>  include/soc/rockchip/rockchip_phy_typec.h |  72 ++++++++
>  2 files changed, 259 insertions(+), 99 deletions(-)
>  create mode 100644 include/soc/rockchip/rockchip_phy_typec.h
>
> diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
> index 76a4b58..831a93b 100644
> --- a/drivers/phy/rockchip/phy-rockchip-typec.c
> +++ b/drivers/phy/rockchip/phy-rockchip-typec.c
> @@ -63,6 +63,7 @@
>
>  #include <linux/mfd/syscon.h>
>  #include <linux/phy/phy.h>
> +#include <soc/rockchip/rockchip_phy_typec.h>
>
>  #define CMN_SSM_BANDGAP                        (0x21 << 2)
>  #define CMN_SSM_BIAS                   (0x22 << 2)
> @@ -323,23 +324,31 @@
>   * clock 0: PLL 0 div 1
>   * clock 1: PLL 1 div 2
>   */
> -#define CLK_PLL_CONFIG                 0X30
> +#define CLK_PLL1_DIV1                  0x20
> +#define CLK_PLL1_DIV2                  0x30
>  #define CLK_PLL_MASK                   0x33
>
>  #define CMN_READY                      BIT(0)
>
> +#define DP_PLL_CLOCK_ENABLE_ACK                BIT(3)
>  #define DP_PLL_CLOCK_ENABLE            BIT(2)
> +#define DP_PLL_ENABLE_ACK              BIT(1)
>  #define DP_PLL_ENABLE                  BIT(0)
>  #define DP_PLL_DATA_RATE_RBR           ((2 << 12) | (4 << 8))
>  #define DP_PLL_DATA_RATE_HBR           ((2 << 12) | (4 << 8))
>  #define DP_PLL_DATA_RATE_HBR2          ((1 << 12) | (2 << 8))
> +#define DP_PLL_DATA_RATE_MASK          0xff00
>
> -#define DP_MODE_A0                     BIT(4)
> -#define DP_MODE_A2                     BIT(6)
> -#define DP_MODE_ENTER_A0               0xc101
> -#define DP_MODE_ENTER_A2               0xc104
> +#define DP_MODE_MASK                   0xf
> +#define DP_MODE_ENTER_A0               BIT(0)
> +#define DP_MODE_ENTER_A2               BIT(2)
> +#define DP_MODE_ENTER_A3               BIT(3)
> +#define DP_MODE_A0_ACK                 BIT(4)
> +#define DP_MODE_A2_ACK                 BIT(6)
> +#define DP_MODE_A3_ACK                 BIT(7)
> +#define DP_LINK_RESET_DEASSERTED       BIT(8)
>
> -#define PHY_MODE_SET_TIMEOUT           100000
> +#define PHY_MODE_SET_TIMEOUT           1000000
>

Why do you need to increase this timeout? Is because the software link
training timed out using the old value?


>  #define PIN_ASSIGN_C_E                 0x51d9
>  #define PIN_ASSIGN_D_F                 0x5100
> @@ -349,51 +358,7 @@
>  #define MODE_DFP_USB                   BIT(1)
>  #define MODE_DFP_DP                    BIT(2)
>
> -struct usb3phy_reg {
> -       u32 offset;
> -       u32 enable_bit;
> -       u32 write_enable;
> -};
> -
> -/**
> - * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
> - * @reg: the base address for usb3-phy config.
> - * @typec_conn_dir: the register of type-c connector direction.
> - * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
> - * @external_psm: the register of type-c phy external psm clock.
> - * @pipe_status: the register of type-c phy pipe status.
> - * @usb3_host_disable: the register of type-c usb3 host disable.
> - * @usb3_host_port: the register of type-c usb3 host port.
> - * @uphy_dp_sel: the register of type-c phy DP select control.
> - */
> -struct rockchip_usb3phy_port_cfg {
> -       unsigned int reg;
> -       struct usb3phy_reg typec_conn_dir;
> -       struct usb3phy_reg usb3tousb2_en;
> -       struct usb3phy_reg external_psm;
> -       struct usb3phy_reg pipe_status;
> -       struct usb3phy_reg usb3_host_disable;
> -       struct usb3phy_reg usb3_host_port;
> -       struct usb3phy_reg uphy_dp_sel;
> -};
> -
> -struct rockchip_typec_phy {
> -       struct device *dev;
> -       void __iomem *base;
> -       struct extcon_dev *extcon;
> -       struct regmap *grf_regs;
> -       struct clk *clk_core;
> -       struct clk *clk_ref;
> -       struct reset_control *uphy_rst;
> -       struct reset_control *pipe_rst;
> -       struct reset_control *tcphy_rst;
> -       const struct rockchip_usb3phy_port_cfg *port_cfgs;
> -       /* mutex to protect access to individual PHYs */
> -       struct mutex lock;
> -
> -       bool flip;
> -       u8 mode;
> -};
> +#define DEFAULT_RATE                   162000
>

DEFAULT_RATE seems a very common name for me, maybe add a prefix?


>  struct phy_reg {
>         u16 value;
> @@ -417,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
>         { 0x8,          CMN_DIAG_PLL0_LF_PROG },
>  };
>
> -struct phy_reg dp_pll_cfg[] = {
> +struct phy_reg dp_pll_rbr_cfg[] = {
>         { 0xf0,         CMN_PLL1_VCOCAL_INIT },
>         { 0x18,         CMN_PLL1_VCOCAL_ITER },
>         { 0x30b9,       CMN_PLL1_VCOCAL_START },
> -       { 0x21c,        CMN_PLL1_INTDIV },
> +       { 0x87,         CMN_PLL1_INTDIV },
>         { 0,            CMN_PLL1_FRACDIV },
> -       { 0x5,          CMN_PLL1_HIGH_THR },
> -       { 0x35,         CMN_PLL1_SS_CTRL1 },
> -       { 0x7f1e,       CMN_PLL1_SS_CTRL2 },
> +       { 0x22,         CMN_PLL1_HIGH_THR },
> +       { 0x8000,       CMN_PLL1_SS_CTRL1 },
> +       { 0,            CMN_PLL1_SS_CTRL2 },
>         { 0x20,         CMN_PLL1_DSM_DIAG },
>         { 0,            CMN_PLLSM1_USER_DEF_CTRL },
>         { 0,            CMN_DIAG_PLL1_OVRD },
> @@ -436,9 +401,52 @@ struct phy_reg dp_pll_cfg[] = {
>         { 0x8,          CMN_DIAG_PLL1_LF_PROG },
>         { 0x100,        CMN_DIAG_PLL1_PTATIS_TUNE1 },
>         { 0x7,          CMN_DIAG_PLL1_PTATIS_TUNE2 },
> -       { 0x4,          CMN_DIAG_PLL1_INCLK_CTRL },
> +       { 0x1,          CMN_DIAG_PLL1_INCLK_CTRL },
> +};
> +
> +struct phy_reg dp_pll_hbr_cfg[] = {
> +       { 0xf0,         CMN_PLL1_VCOCAL_INIT },
> +       { 0x18,         CMN_PLL1_VCOCAL_ITER },
> +       { 0x30b4,       CMN_PLL1_VCOCAL_START },
> +       { 0xe1,         CMN_PLL1_INTDIV },
> +       { 0,            CMN_PLL1_FRACDIV },
> +       { 0x5,          CMN_PLL1_HIGH_THR },
> +       { 0x8000,       CMN_PLL1_SS_CTRL1 },
> +       { 0,            CMN_PLL1_SS_CTRL2 },
> +       { 0x20,         CMN_PLL1_DSM_DIAG },
> +       { 0x1000,       CMN_PLLSM1_USER_DEF_CTRL },
> +       { 0,            CMN_DIAG_PLL1_OVRD },
> +       { 0,            CMN_DIAG_PLL1_FBH_OVRD },
> +       { 0,            CMN_DIAG_PLL1_FBL_OVRD },
> +       { 0x7,          CMN_DIAG_PLL1_V2I_TUNE },
> +       { 0x45,         CMN_DIAG_PLL1_CP_TUNE },
> +       { 0x8,          CMN_DIAG_PLL1_LF_PROG },
> +       { 0x1,          CMN_DIAG_PLL1_PTATIS_TUNE1 },
> +       { 0x1,          CMN_DIAG_PLL1_PTATIS_TUNE2 },
> +       { 0x1,          CMN_DIAG_PLL1_INCLK_CTRL },
>  };
>
> +struct phy_reg dp_pll_hbr2_cfg[] = {
> +       { 0xf0,         CMN_PLL1_VCOCAL_INIT },
> +       { 0x18,         CMN_PLL1_VCOCAL_ITER },
> +       { 0x30b4,       CMN_PLL1_VCOCAL_START },
> +       { 0xe1,         CMN_PLL1_INTDIV },
> +       { 0,            CMN_PLL1_FRACDIV },
> +       { 0x5,          CMN_PLL1_HIGH_THR },
> +       { 0x8000,       CMN_PLL1_SS_CTRL1 },
> +       { 0,            CMN_PLL1_SS_CTRL2 },
> +       { 0x20,         CMN_PLL1_DSM_DIAG },
> +       { 0x1000,       CMN_PLLSM1_USER_DEF_CTRL },
> +       { 0,            CMN_DIAG_PLL1_OVRD },
> +       { 0,            CMN_DIAG_PLL1_FBH_OVRD },
> +       { 0,            CMN_DIAG_PLL1_FBL_OVRD },
> +       { 0x7,          CMN_DIAG_PLL1_V2I_TUNE },
> +       { 0x45,         CMN_DIAG_PLL1_CP_TUNE },
> +       { 0x8,          CMN_DIAG_PLL1_LF_PROG },
> +       { 0x1,          CMN_DIAG_PLL1_PTATIS_TUNE1 },
> +       { 0x1,          CMN_DIAG_PLL1_PTATIS_TUNE2 },
> +       { 0x1,          CMN_DIAG_PLL1_INCLK_CTRL },
> +};
>  static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
>         {
>                 .reg = 0xff7c0000,
> @@ -484,7 +492,7 @@ static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
>
>         rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
>         rdata &= ~CLK_PLL_MASK;
> -       rdata |= CLK_PLL_CONFIG;
> +       rdata |= CLK_PLL1_DIV2;
>         writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
>  }
>
> @@ -498,17 +506,44 @@ static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy)
>                        tcphy->base + usb3_pll_cfg[i].addr);
>  }
>
> -static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
> +static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy, int link_rate)
>  {
> -       u32 i;
> +       struct phy_reg *phy_cfg;
> +       u32 clk_ctrl;
> +       u32 i, cfg_size, hsclk_sel;
> +
> +       hsclk_sel = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
> +       hsclk_sel &= ~CLK_PLL_MASK;
> +
> +       switch (link_rate) {
> +       case 162000:
> +               clk_ctrl = DP_PLL_DATA_RATE_RBR;
> +               hsclk_sel |= CLK_PLL1_DIV2;
> +               phy_cfg = dp_pll_rbr_cfg;
> +               cfg_size = ARRAY_SIZE(dp_pll_rbr_cfg);
> +               break;
> +       case 270000:
> +               clk_ctrl = DP_PLL_DATA_RATE_HBR;
> +               hsclk_sel |= CLK_PLL1_DIV2;
> +               phy_cfg = dp_pll_hbr_cfg;
> +               cfg_size = ARRAY_SIZE(dp_pll_hbr_cfg);
> +               break;
> +       case 540000:
> +               clk_ctrl = DP_PLL_DATA_RATE_HBR2;
> +               hsclk_sel |= CLK_PLL1_DIV1;
> +               phy_cfg = dp_pll_hbr2_cfg;
> +               cfg_size = ARRAY_SIZE(dp_pll_hbr2_cfg);
> +               break;
> +       }
> +
> +       clk_ctrl |= DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE;
> +       writel(clk_ctrl, tcphy->base + DP_CLK_CTL);
>
> -       /* set the default mode to RBR */
> -       writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR,
> -              tcphy->base + DP_CLK_CTL);
> +       writel(hsclk_sel, tcphy->base + CMN_DIAG_HSCLK_SEL);
>
>         /* load the configuration of PLL1 */
> -       for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++)
> -               writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr);
> +       for (i = 0; i < cfg_size; i++)
> +               writel(phy_cfg[i].value, tcphy->base + phy_cfg[i].addr);
>  }
>
>  static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
> @@ -535,9 +570,10 @@ static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
>         writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
>  }
>
> -static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
> +static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, int link_rate,
> +                             u8 swing, u8 pre_emp, u32 lane)
>  {
> -       u16 rdata;
> +       u16 val;

From what I see you are only renaming rdata to val, there is any reason?

>
>         writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
>         writel(0x6799, tcphy->base + TX_PSC_A0(lane));
> @@ -545,25 +581,31 @@ static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
>         writel(0x98, tcphy->base + TX_PSC_A2(lane));
>         writel(0x98, tcphy->base + TX_PSC_A3(lane));
>
> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
> -       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
> -       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
> -       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
> -       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
> -
> -       writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
> -       writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane));
> -
> -       rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
> -       rdata = (rdata & 0x8fff) | 0x6000;
> -       writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
> +       writel(tcphy->config[swing][pre_emp].swing,
> +              tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
> +       writel(tcphy->config[swing][pre_emp].pe,
> +              tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
> +
> +       if (swing == 2 && pre_emp == 0 && link_rate != 540000) {
> +               writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
> +               writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
> +       } else {
> +               writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
> +               writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
> +       }
> +
> +       val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
> +       val = val & 0x8fff;
> +       switch (link_rate) {
> +       case 162000:
> +       case 270000:
> +               val |= (6 << 12);
> +               break;
> +       case 540000:
> +               val |= (4 << 12);
> +               break;
> +       }
> +       writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
>  }
>
>  static inline int property_enable(struct rockchip_typec_phy *tcphy,
> @@ -754,30 +796,33 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
>         tcphy_cfg_24m(tcphy);
>
>         if (mode == MODE_DFP_DP) {
> -               tcphy_cfg_dp_pll(tcphy);
> +               tcphy_cfg_dp_pll(tcphy, DEFAULT_RATE);
>                 for (i = 0; i < 4; i++)
> -                       tcphy_dp_cfg_lane(tcphy, i);
> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, i);
>
>                 writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG);
>         } else {
>                 tcphy_cfg_usb3_pll(tcphy);
> -               tcphy_cfg_dp_pll(tcphy);
> +               tcphy_cfg_dp_pll(tcphy, DEFAULT_RATE);
>                 if (tcphy->flip) {
>                         tcphy_tx_usb3_cfg_lane(tcphy, 3);
>                         tcphy_rx_usb3_cfg_lane(tcphy, 2);
> -                       tcphy_dp_cfg_lane(tcphy, 0);
> -                       tcphy_dp_cfg_lane(tcphy, 1);
> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 0);
> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 1);
>                 } else {
>                         tcphy_tx_usb3_cfg_lane(tcphy, 0);
>                         tcphy_rx_usb3_cfg_lane(tcphy, 1);
> -                       tcphy_dp_cfg_lane(tcphy, 2);
> -                       tcphy_dp_cfg_lane(tcphy, 3);
> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 2);
> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 3);
>                 }
>
>                 writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG);
>         }
>
> -       writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
> +       val = readl(tcphy->base + DP_MODE_CTL);
> +       val &= ~DP_MODE_MASK;
> +       val |= DP_MODE_ENTER_A2 | DP_LINK_RESET_DEASSERTED;
> +       writel(val, tcphy->base + DP_MODE_CTL);
>
>         reset_control_deassert(tcphy->uphy_rst);
>
> @@ -990,7 +1035,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
>         property_enable(tcphy, &cfg->uphy_dp_sel, 1);
>
>         ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
> -                                val, val & DP_MODE_A2, 1000,
> +                                val, val & DP_MODE_A2_ACK, 1000,
>                                  PHY_MODE_SET_TIMEOUT);
>         if (ret < 0) {
>                 dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n");
> @@ -999,13 +1044,19 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
>
>         tcphy_dp_aux_calibration(tcphy);
>
> -       writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL);
> +       /* enter A0 mode */
> +       val = readl(tcphy->base + DP_MODE_CTL);
> +       val &= ~DP_MODE_MASK;
> +       val |= DP_MODE_ENTER_A0;
> +       writel(val, tcphy->base + DP_MODE_CTL);
>
>         ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
> -                                val, val & DP_MODE_A0, 1000,
> +                                val, val & DP_MODE_A0_ACK, 1000,
>                                  PHY_MODE_SET_TIMEOUT);
>         if (ret < 0) {
> -               writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
> +               val &= ~DP_MODE_MASK;
> +               val |= DP_MODE_ENTER_A2;
> +               writel(val, tcphy->base + DP_MODE_CTL);
>                 dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
>                 goto power_on_finish;
>         }
> @@ -1023,6 +1074,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
>  static int rockchip_dp_phy_power_off(struct phy *phy)
>  {
>         struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
> +       u32 val;
>
>         mutex_lock(&tcphy->lock);
>
> @@ -1031,7 +1083,10 @@ static int rockchip_dp_phy_power_off(struct phy *phy)
>
>         tcphy->mode &= ~MODE_DFP_DP;
>
> -       writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
> +       val = readl(tcphy->base + DP_MODE_CTL);
> +       val &= ~DP_MODE_MASK;
> +       val |= DP_MODE_ENTER_A2;
> +       writel(val, tcphy->base + DP_MODE_CTL);
>
>         if (tcphy->mode == MODE_DISCONNECT)
>                 tcphy_phy_deinit(tcphy);
> @@ -1047,6 +1102,30 @@ static const struct phy_ops rockchip_dp_phy_ops = {
>         .owner          = THIS_MODULE,
>  };
>
> +static int type_c_dp_phy_config(struct phy *phy, int link_rate,

s/type_c/typec/ to be coherent with the rest of the code.

> +                        int lanes, u8 swing, u8 pre_emp)
> +{
> +       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
> +       u8 i;
> +
> +       tcphy_cfg_dp_pll(tcphy, link_rate);
> +
> +       if (tcphy->mode == MODE_DFP_DP) {
> +               for (i = 0; i < 4; i++)
> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, i);
> +       } else {
> +               if (tcphy->flip) {
> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 0);
> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 1);
> +               } else {
> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 2);
> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 3);
> +               }
> +       }
> +
> +       return 0;
> +}
> +
>  static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
>                           struct device *dev)
>  {
> @@ -1087,6 +1166,14 @@ static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
>                 return PTR_ERR(tcphy->tcphy_rst);
>         }
>
> +       /*
> +        * check if phy_config pass from dts, if yes,
> +        * need to use this phy config to do software training later
> +        */
> +       if (!of_property_read_u32_array(dev->of_node, "rockchip,phy_config",
> +               (u32 *)tcphy->config, sizeof(tcphy->config) / sizeof(u32)))
> +               tcphy->need_software_training = 1;
> +
>         return 0;
>  }
>
> @@ -1171,6 +1258,7 @@ static int rockchip_typec_phy_probe(struct platform_device *pdev)
>                 }
>         }
>
> +       tcphy->typec_phy_config = type_c_dp_phy_config;

type_c_dp_phy_config -> typec_dp_phy_config

>         pm_runtime_enable(dev);
>
>         for_each_available_child_of_node(np, child_np) {
> diff --git a/include/soc/rockchip/rockchip_phy_typec.h b/include/soc/rockchip/rockchip_phy_typec.h
> new file mode 100644
> index 0000000..e25840e
> --- /dev/null
> +++ b/include/soc/rockchip/rockchip_phy_typec.h
> @@ -0,0 +1,72 @@
> +/*

Add the SPDX License identifier ...

> + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd
> + * Author: Lin Huang <hl@rock-chips.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.

... and remove the above notice.

> + */
> +#ifndef __SOC_ROCKCHIP_PHY_TYPEC_H
> +#define __SOC_ROCKCHIP_PHY_TYPEC_H
> +
> +

Remove the extra new line.

> +struct usb3phy_reg {
> +       u32 offset;
> +       u32 enable_bit;
> +       u32 write_enable;
> +};
> +
> +/**
> + * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
> + * @reg: the base address for usb3-phy config.
> + * @typec_conn_dir: the register of type-c connector direction.
> + * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
> + * @external_psm: the register of type-c phy external psm clock.
> + * @pipe_status: the register of type-c phy pipe status.
> + * @usb3_host_disable: the register of type-c usb3 host disable.
> + * @usb3_host_port: the register of type-c usb3 host port.
> + * @uphy_dp_sel: the register of type-c phy DP select control.
> + */
> +struct rockchip_usb3phy_port_cfg {
> +       unsigned int reg;
> +       struct usb3phy_reg typec_conn_dir;
> +       struct usb3phy_reg usb3tousb2_en;
> +       struct usb3phy_reg external_psm;
> +       struct usb3phy_reg pipe_status;
> +       struct usb3phy_reg usb3_host_disable;
> +       struct usb3phy_reg usb3_host_port;
> +       struct usb3phy_reg uphy_dp_sel;
> +};
> +
> +struct phy_config {
> +       int swing;
> +       int pe;
> +};
> +
> +struct rockchip_typec_phy {
> +       struct device *dev;
> +       void __iomem *base;
> +       struct extcon_dev *extcon;
> +       struct regmap *grf_regs;
> +       struct clk *clk_core;
> +       struct clk *clk_ref;
> +       struct reset_control *uphy_rst;
> +       struct reset_control *pipe_rst;
> +       struct reset_control *tcphy_rst;
> +       struct rockchip_usb3phy_port_cfg *port_cfgs;
> +       /* mutex to protect access to individual PHYs */
> +       struct mutex lock;
> +       struct phy_config config[3][4];
> +       u8 need_software_training;
> +       bool flip;
> +       u8 mode;
> +       int (*typec_phy_config)(struct phy *phy, int link_rate,
> +                               int lanes, u8 swing, u8 pre_emp);
> +};
> +
> +#endif

Best regards,
 Enric

> --
> 2.7.4
>
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
huang lin May 9, 2018, 3:39 a.m. UTC | #3
On Monday, May 07, 2018 09:59 PM, Enric Balletbo Serra wrote:
> Hi Lin,
>
> Thanks for the patch, apart from the new build warnings introduced
> some more comments below.
>
> 2018-05-04 10:08 GMT+02:00 Lin Huang <hl@rock-chips.com>:
>> the phy config values used to fix in dp firmware, but some boards
>> need change these values to do training and get the better eye diagram
>> result. So support that in phy driver.
>>
>> Signed-off-by: Chris Zhong <zyw@rock-chips.com>
>> Signed-off-by: Lin Huang <hl@rock-chips.com>
>> ---
>>   drivers/phy/rockchip/phy-rockchip-typec.c | 286 +++++++++++++++++++-----------
>>   include/soc/rockchip/rockchip_phy_typec.h |  72 ++++++++
>>   2 files changed, 259 insertions(+), 99 deletions(-)
>>   create mode 100644 include/soc/rockchip/rockchip_phy_typec.h
>>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
>> index 76a4b58..831a93b 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-typec.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-typec.c
>> @@ -63,6 +63,7 @@
>>
>>   #include <linux/mfd/syscon.h>
>>   #include <linux/phy/phy.h>
>> +#include <soc/rockchip/rockchip_phy_typec.h>
>>
>>   #define CMN_SSM_BANDGAP                        (0x21 << 2)
>>   #define CMN_SSM_BIAS                   (0x22 << 2)
>> @@ -323,23 +324,31 @@
>>    * clock 0: PLL 0 div 1
>>    * clock 1: PLL 1 div 2
>>    */
>> -#define CLK_PLL_CONFIG                 0X30
>> +#define CLK_PLL1_DIV1                  0x20
>> +#define CLK_PLL1_DIV2                  0x30
>>   #define CLK_PLL_MASK                   0x33
>>
>>   #define CMN_READY                      BIT(0)
>>
>> +#define DP_PLL_CLOCK_ENABLE_ACK                BIT(3)
>>   #define DP_PLL_CLOCK_ENABLE            BIT(2)
>> +#define DP_PLL_ENABLE_ACK              BIT(1)
>>   #define DP_PLL_ENABLE                  BIT(0)
>>   #define DP_PLL_DATA_RATE_RBR           ((2 << 12) | (4 << 8))
>>   #define DP_PLL_DATA_RATE_HBR           ((2 << 12) | (4 << 8))
>>   #define DP_PLL_DATA_RATE_HBR2          ((1 << 12) | (2 << 8))
>> +#define DP_PLL_DATA_RATE_MASK          0xff00
>>
>> -#define DP_MODE_A0                     BIT(4)
>> -#define DP_MODE_A2                     BIT(6)
>> -#define DP_MODE_ENTER_A0               0xc101
>> -#define DP_MODE_ENTER_A2               0xc104
>> +#define DP_MODE_MASK                   0xf
>> +#define DP_MODE_ENTER_A0               BIT(0)
>> +#define DP_MODE_ENTER_A2               BIT(2)
>> +#define DP_MODE_ENTER_A3               BIT(3)
>> +#define DP_MODE_A0_ACK                 BIT(4)
>> +#define DP_MODE_A2_ACK                 BIT(6)
>> +#define DP_MODE_A3_ACK                 BIT(7)
>> +#define DP_LINK_RESET_DEASSERTED       BIT(8)
>>
>> -#define PHY_MODE_SET_TIMEOUT           100000
>> +#define PHY_MODE_SET_TIMEOUT           1000000
>>
> Why do you need to increase this timeout? Is because the software link
> training timed out using the old value?
That for debug, will fix it in next version.
>
>
>>   #define PIN_ASSIGN_C_E                 0x51d9
>>   #define PIN_ASSIGN_D_F                 0x5100
>> @@ -349,51 +358,7 @@
>>   #define MODE_DFP_USB                   BIT(1)
>>   #define MODE_DFP_DP                    BIT(2)
>>
>> -struct usb3phy_reg {
>> -       u32 offset;
>> -       u32 enable_bit;
>> -       u32 write_enable;
>> -};
>> -
>> -/**
>> - * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
>> - * @reg: the base address for usb3-phy config.
>> - * @typec_conn_dir: the register of type-c connector direction.
>> - * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
>> - * @external_psm: the register of type-c phy external psm clock.
>> - * @pipe_status: the register of type-c phy pipe status.
>> - * @usb3_host_disable: the register of type-c usb3 host disable.
>> - * @usb3_host_port: the register of type-c usb3 host port.
>> - * @uphy_dp_sel: the register of type-c phy DP select control.
>> - */
>> -struct rockchip_usb3phy_port_cfg {
>> -       unsigned int reg;
>> -       struct usb3phy_reg typec_conn_dir;
>> -       struct usb3phy_reg usb3tousb2_en;
>> -       struct usb3phy_reg external_psm;
>> -       struct usb3phy_reg pipe_status;
>> -       struct usb3phy_reg usb3_host_disable;
>> -       struct usb3phy_reg usb3_host_port;
>> -       struct usb3phy_reg uphy_dp_sel;
>> -};
>> -
>> -struct rockchip_typec_phy {
>> -       struct device *dev;
>> -       void __iomem *base;
>> -       struct extcon_dev *extcon;
>> -       struct regmap *grf_regs;
>> -       struct clk *clk_core;
>> -       struct clk *clk_ref;
>> -       struct reset_control *uphy_rst;
>> -       struct reset_control *pipe_rst;
>> -       struct reset_control *tcphy_rst;
>> -       const struct rockchip_usb3phy_port_cfg *port_cfgs;
>> -       /* mutex to protect access to individual PHYs */
>> -       struct mutex lock;
>> -
>> -       bool flip;
>> -       u8 mode;
>> -};
>> +#define DEFAULT_RATE                   162000
>>
> DEFAULT_RATE seems a very common name for me, maybe add a prefix?
Okay, will fix it.
>
>
>>   struct phy_reg {
>>          u16 value;
>> @@ -417,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
>>          { 0x8,          CMN_DIAG_PLL0_LF_PROG },
>>   };
>>
>> -struct phy_reg dp_pll_cfg[] = {
>> +struct phy_reg dp_pll_rbr_cfg[] = {
>>          { 0xf0,         CMN_PLL1_VCOCAL_INIT },
>>          { 0x18,         CMN_PLL1_VCOCAL_ITER },
>>          { 0x30b9,       CMN_PLL1_VCOCAL_START },
>> -       { 0x21c,        CMN_PLL1_INTDIV },
>> +       { 0x87,         CMN_PLL1_INTDIV },
>>          { 0,            CMN_PLL1_FRACDIV },
>> -       { 0x5,          CMN_PLL1_HIGH_THR },
>> -       { 0x35,         CMN_PLL1_SS_CTRL1 },
>> -       { 0x7f1e,       CMN_PLL1_SS_CTRL2 },
>> +       { 0x22,         CMN_PLL1_HIGH_THR },
>> +       { 0x8000,       CMN_PLL1_SS_CTRL1 },
>> +       { 0,            CMN_PLL1_SS_CTRL2 },
>>          { 0x20,         CMN_PLL1_DSM_DIAG },
>>          { 0,            CMN_PLLSM1_USER_DEF_CTRL },
>>          { 0,            CMN_DIAG_PLL1_OVRD },
>> @@ -436,9 +401,52 @@ struct phy_reg dp_pll_cfg[] = {
>>          { 0x8,          CMN_DIAG_PLL1_LF_PROG },
>>          { 0x100,        CMN_DIAG_PLL1_PTATIS_TUNE1 },
>>          { 0x7,          CMN_DIAG_PLL1_PTATIS_TUNE2 },
>> -       { 0x4,          CMN_DIAG_PLL1_INCLK_CTRL },
>> +       { 0x1,          CMN_DIAG_PLL1_INCLK_CTRL },
>> +};
>> +
>> +struct phy_reg dp_pll_hbr_cfg[] = {
>> +       { 0xf0,         CMN_PLL1_VCOCAL_INIT },
>> +       { 0x18,         CMN_PLL1_VCOCAL_ITER },
>> +       { 0x30b4,       CMN_PLL1_VCOCAL_START },
>> +       { 0xe1,         CMN_PLL1_INTDIV },
>> +       { 0,            CMN_PLL1_FRACDIV },
>> +       { 0x5,          CMN_PLL1_HIGH_THR },
>> +       { 0x8000,       CMN_PLL1_SS_CTRL1 },
>> +       { 0,            CMN_PLL1_SS_CTRL2 },
>> +       { 0x20,         CMN_PLL1_DSM_DIAG },
>> +       { 0x1000,       CMN_PLLSM1_USER_DEF_CTRL },
>> +       { 0,            CMN_DIAG_PLL1_OVRD },
>> +       { 0,            CMN_DIAG_PLL1_FBH_OVRD },
>> +       { 0,            CMN_DIAG_PLL1_FBL_OVRD },
>> +       { 0x7,          CMN_DIAG_PLL1_V2I_TUNE },
>> +       { 0x45,         CMN_DIAG_PLL1_CP_TUNE },
>> +       { 0x8,          CMN_DIAG_PLL1_LF_PROG },
>> +       { 0x1,          CMN_DIAG_PLL1_PTATIS_TUNE1 },
>> +       { 0x1,          CMN_DIAG_PLL1_PTATIS_TUNE2 },
>> +       { 0x1,          CMN_DIAG_PLL1_INCLK_CTRL },
>>   };
>>
>> +struct phy_reg dp_pll_hbr2_cfg[] = {
>> +       { 0xf0,         CMN_PLL1_VCOCAL_INIT },
>> +       { 0x18,         CMN_PLL1_VCOCAL_ITER },
>> +       { 0x30b4,       CMN_PLL1_VCOCAL_START },
>> +       { 0xe1,         CMN_PLL1_INTDIV },
>> +       { 0,            CMN_PLL1_FRACDIV },
>> +       { 0x5,          CMN_PLL1_HIGH_THR },
>> +       { 0x8000,       CMN_PLL1_SS_CTRL1 },
>> +       { 0,            CMN_PLL1_SS_CTRL2 },
>> +       { 0x20,         CMN_PLL1_DSM_DIAG },
>> +       { 0x1000,       CMN_PLLSM1_USER_DEF_CTRL },
>> +       { 0,            CMN_DIAG_PLL1_OVRD },
>> +       { 0,            CMN_DIAG_PLL1_FBH_OVRD },
>> +       { 0,            CMN_DIAG_PLL1_FBL_OVRD },
>> +       { 0x7,          CMN_DIAG_PLL1_V2I_TUNE },
>> +       { 0x45,         CMN_DIAG_PLL1_CP_TUNE },
>> +       { 0x8,          CMN_DIAG_PLL1_LF_PROG },
>> +       { 0x1,          CMN_DIAG_PLL1_PTATIS_TUNE1 },
>> +       { 0x1,          CMN_DIAG_PLL1_PTATIS_TUNE2 },
>> +       { 0x1,          CMN_DIAG_PLL1_INCLK_CTRL },
>> +};
>>   static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
>>          {
>>                  .reg = 0xff7c0000,
>> @@ -484,7 +492,7 @@ static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
>>
>>          rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
>>          rdata &= ~CLK_PLL_MASK;
>> -       rdata |= CLK_PLL_CONFIG;
>> +       rdata |= CLK_PLL1_DIV2;
>>          writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
>>   }
>>
>> @@ -498,17 +506,44 @@ static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy)
>>                         tcphy->base + usb3_pll_cfg[i].addr);
>>   }
>>
>> -static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
>> +static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy, int link_rate)
>>   {
>> -       u32 i;
>> +       struct phy_reg *phy_cfg;
>> +       u32 clk_ctrl;
>> +       u32 i, cfg_size, hsclk_sel;
>> +
>> +       hsclk_sel = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
>> +       hsclk_sel &= ~CLK_PLL_MASK;
>> +
>> +       switch (link_rate) {
>> +       case 162000:
>> +               clk_ctrl = DP_PLL_DATA_RATE_RBR;
>> +               hsclk_sel |= CLK_PLL1_DIV2;
>> +               phy_cfg = dp_pll_rbr_cfg;
>> +               cfg_size = ARRAY_SIZE(dp_pll_rbr_cfg);
>> +               break;
>> +       case 270000:
>> +               clk_ctrl = DP_PLL_DATA_RATE_HBR;
>> +               hsclk_sel |= CLK_PLL1_DIV2;
>> +               phy_cfg = dp_pll_hbr_cfg;
>> +               cfg_size = ARRAY_SIZE(dp_pll_hbr_cfg);
>> +               break;
>> +       case 540000:
>> +               clk_ctrl = DP_PLL_DATA_RATE_HBR2;
>> +               hsclk_sel |= CLK_PLL1_DIV1;
>> +               phy_cfg = dp_pll_hbr2_cfg;
>> +               cfg_size = ARRAY_SIZE(dp_pll_hbr2_cfg);
>> +               break;
>> +       }
>> +
>> +       clk_ctrl |= DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE;
>> +       writel(clk_ctrl, tcphy->base + DP_CLK_CTL);
>>
>> -       /* set the default mode to RBR */
>> -       writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR,
>> -              tcphy->base + DP_CLK_CTL);
>> +       writel(hsclk_sel, tcphy->base + CMN_DIAG_HSCLK_SEL);
>>
>>          /* load the configuration of PLL1 */
>> -       for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++)
>> -               writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr);
>> +       for (i = 0; i < cfg_size; i++)
>> +               writel(phy_cfg[i].value, tcphy->base + phy_cfg[i].addr);
>>   }
>>
>>   static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
>> @@ -535,9 +570,10 @@ static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
>>          writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
>>   }
>>
>> -static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
>> +static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, int link_rate,
>> +                             u8 swing, u8 pre_emp, u32 lane)
>>   {
>> -       u16 rdata;
>> +       u16 val;
> >From what I see you are only renaming rdata to val, there is any reason?
not reason, just rename a new variable :)
>
>>          writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
>>          writel(0x6799, tcphy->base + TX_PSC_A0(lane));
>> @@ -545,25 +581,31 @@ static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
>>          writel(0x98, tcphy->base + TX_PSC_A2(lane));
>>          writel(0x98, tcphy->base + TX_PSC_A3(lane));
>>
>> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
>> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
>> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
>> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
>> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
>> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
>> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
>> -       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
>> -       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
>> -       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
>> -       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
>> -       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
>> -
>> -       writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
>> -       writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane));
>> -
>> -       rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
>> -       rdata = (rdata & 0x8fff) | 0x6000;
>> -       writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
>> +       writel(tcphy->config[swing][pre_emp].swing,
>> +              tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
>> +       writel(tcphy->config[swing][pre_emp].pe,
>> +              tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
>> +
>> +       if (swing == 2 && pre_emp == 0 && link_rate != 540000) {
>> +               writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
>> +               writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
>> +       } else {
>> +               writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
>> +               writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
>> +       }
>> +
>> +       val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
>> +       val = val & 0x8fff;
>> +       switch (link_rate) {
>> +       case 162000:
>> +       case 270000:
>> +               val |= (6 << 12);
>> +               break;
>> +       case 540000:
>> +               val |= (4 << 12);
>> +               break;
>> +       }
>> +       writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
>>   }
>>
>>   static inline int property_enable(struct rockchip_typec_phy *tcphy,
>> @@ -754,30 +796,33 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
>>          tcphy_cfg_24m(tcphy);
>>
>>          if (mode == MODE_DFP_DP) {
>> -               tcphy_cfg_dp_pll(tcphy);
>> +               tcphy_cfg_dp_pll(tcphy, DEFAULT_RATE);
>>                  for (i = 0; i < 4; i++)
>> -                       tcphy_dp_cfg_lane(tcphy, i);
>> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, i);
>>
>>                  writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG);
>>          } else {
>>                  tcphy_cfg_usb3_pll(tcphy);
>> -               tcphy_cfg_dp_pll(tcphy);
>> +               tcphy_cfg_dp_pll(tcphy, DEFAULT_RATE);
>>                  if (tcphy->flip) {
>>                          tcphy_tx_usb3_cfg_lane(tcphy, 3);
>>                          tcphy_rx_usb3_cfg_lane(tcphy, 2);
>> -                       tcphy_dp_cfg_lane(tcphy, 0);
>> -                       tcphy_dp_cfg_lane(tcphy, 1);
>> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 0);
>> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 1);
>>                  } else {
>>                          tcphy_tx_usb3_cfg_lane(tcphy, 0);
>>                          tcphy_rx_usb3_cfg_lane(tcphy, 1);
>> -                       tcphy_dp_cfg_lane(tcphy, 2);
>> -                       tcphy_dp_cfg_lane(tcphy, 3);
>> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 2);
>> +                       tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 3);
>>                  }
>>
>>                  writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG);
>>          }
>>
>> -       writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
>> +       val = readl(tcphy->base + DP_MODE_CTL);
>> +       val &= ~DP_MODE_MASK;
>> +       val |= DP_MODE_ENTER_A2 | DP_LINK_RESET_DEASSERTED;
>> +       writel(val, tcphy->base + DP_MODE_CTL);
>>
>>          reset_control_deassert(tcphy->uphy_rst);
>>
>> @@ -990,7 +1035,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
>>          property_enable(tcphy, &cfg->uphy_dp_sel, 1);
>>
>>          ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
>> -                                val, val & DP_MODE_A2, 1000,
>> +                                val, val & DP_MODE_A2_ACK, 1000,
>>                                   PHY_MODE_SET_TIMEOUT);
>>          if (ret < 0) {
>>                  dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n");
>> @@ -999,13 +1044,19 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
>>
>>          tcphy_dp_aux_calibration(tcphy);
>>
>> -       writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL);
>> +       /* enter A0 mode */
>> +       val = readl(tcphy->base + DP_MODE_CTL);
>> +       val &= ~DP_MODE_MASK;
>> +       val |= DP_MODE_ENTER_A0;
>> +       writel(val, tcphy->base + DP_MODE_CTL);
>>
>>          ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
>> -                                val, val & DP_MODE_A0, 1000,
>> +                                val, val & DP_MODE_A0_ACK, 1000,
>>                                   PHY_MODE_SET_TIMEOUT);
>>          if (ret < 0) {
>> -               writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
>> +               val &= ~DP_MODE_MASK;
>> +               val |= DP_MODE_ENTER_A2;
>> +               writel(val, tcphy->base + DP_MODE_CTL);
>>                  dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
>>                  goto power_on_finish;
>>          }
>> @@ -1023,6 +1074,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
>>   static int rockchip_dp_phy_power_off(struct phy *phy)
>>   {
>>          struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
>> +       u32 val;
>>
>>          mutex_lock(&tcphy->lock);
>>
>> @@ -1031,7 +1083,10 @@ static int rockchip_dp_phy_power_off(struct phy *phy)
>>
>>          tcphy->mode &= ~MODE_DFP_DP;
>>
>> -       writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
>> +       val = readl(tcphy->base + DP_MODE_CTL);
>> +       val &= ~DP_MODE_MASK;
>> +       val |= DP_MODE_ENTER_A2;
>> +       writel(val, tcphy->base + DP_MODE_CTL);
>>
>>          if (tcphy->mode == MODE_DISCONNECT)
>>                  tcphy_phy_deinit(tcphy);
>> @@ -1047,6 +1102,30 @@ static const struct phy_ops rockchip_dp_phy_ops = {
>>          .owner          = THIS_MODULE,
>>   };
>>
>> +static int type_c_dp_phy_config(struct phy *phy, int link_rate,
> s/type_c/typec/ to be coherent with the rest of the code.
>
>> +                        int lanes, u8 swing, u8 pre_emp)
>> +{
>> +       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
>> +       u8 i;
>> +
>> +       tcphy_cfg_dp_pll(tcphy, link_rate);
>> +
>> +       if (tcphy->mode == MODE_DFP_DP) {
>> +               for (i = 0; i < 4; i++)
>> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, i);
>> +       } else {
>> +               if (tcphy->flip) {
>> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 0);
>> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 1);
>> +               } else {
>> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 2);
>> +                       tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 3);
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>>   static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
>>                            struct device *dev)
>>   {
>> @@ -1087,6 +1166,14 @@ static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
>>                  return PTR_ERR(tcphy->tcphy_rst);
>>          }
>>
>> +       /*
>> +        * check if phy_config pass from dts, if yes,
>> +        * need to use this phy config to do software training later
>> +        */
>> +       if (!of_property_read_u32_array(dev->of_node, "rockchip,phy_config",
>> +               (u32 *)tcphy->config, sizeof(tcphy->config) / sizeof(u32)))
>> +               tcphy->need_software_training = 1;
>> +
>>          return 0;
>>   }
>>
>> @@ -1171,6 +1258,7 @@ static int rockchip_typec_phy_probe(struct platform_device *pdev)
>>                  }
>>          }
>>
>> +       tcphy->typec_phy_config = type_c_dp_phy_config;
> type_c_dp_phy_config -> typec_dp_phy_config
>
>>          pm_runtime_enable(dev);
>>
>>          for_each_available_child_of_node(np, child_np) {
>> diff --git a/include/soc/rockchip/rockchip_phy_typec.h b/include/soc/rockchip/rockchip_phy_typec.h
>> new file mode 100644
>> index 0000000..e25840e
>> --- /dev/null
>> +++ b/include/soc/rockchip/rockchip_phy_typec.h
>> @@ -0,0 +1,72 @@
>> +/*
> Add the SPDX License identifier ...
>
>> + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd
>> + * Author: Lin Huang <hl@rock-chips.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
> ... and remove the above notice.
>
>> + */
>> +#ifndef __SOC_ROCKCHIP_PHY_TYPEC_H
>> +#define __SOC_ROCKCHIP_PHY_TYPEC_H
>> +
>> +
> Remove the extra new line.
>
>> +struct usb3phy_reg {
>> +       u32 offset;
>> +       u32 enable_bit;
>> +       u32 write_enable;
>> +};
>> +
>> +/**
>> + * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
>> + * @reg: the base address for usb3-phy config.
>> + * @typec_conn_dir: the register of type-c connector direction.
>> + * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
>> + * @external_psm: the register of type-c phy external psm clock.
>> + * @pipe_status: the register of type-c phy pipe status.
>> + * @usb3_host_disable: the register of type-c usb3 host disable.
>> + * @usb3_host_port: the register of type-c usb3 host port.
>> + * @uphy_dp_sel: the register of type-c phy DP select control.
>> + */
>> +struct rockchip_usb3phy_port_cfg {
>> +       unsigned int reg;
>> +       struct usb3phy_reg typec_conn_dir;
>> +       struct usb3phy_reg usb3tousb2_en;
>> +       struct usb3phy_reg external_psm;
>> +       struct usb3phy_reg pipe_status;
>> +       struct usb3phy_reg usb3_host_disable;
>> +       struct usb3phy_reg usb3_host_port;
>> +       struct usb3phy_reg uphy_dp_sel;
>> +};
>> +
>> +struct phy_config {
>> +       int swing;
>> +       int pe;
>> +};
>> +
>> +struct rockchip_typec_phy {
>> +       struct device *dev;
>> +       void __iomem *base;
>> +       struct extcon_dev *extcon;
>> +       struct regmap *grf_regs;
>> +       struct clk *clk_core;
>> +       struct clk *clk_ref;
>> +       struct reset_control *uphy_rst;
>> +       struct reset_control *pipe_rst;
>> +       struct reset_control *tcphy_rst;
>> +       struct rockchip_usb3phy_port_cfg *port_cfgs;
>> +       /* mutex to protect access to individual PHYs */
>> +       struct mutex lock;
>> +       struct phy_config config[3][4];
>> +       u8 need_software_training;
>> +       bool flip;
>> +       u8 mode;
>> +       int (*typec_phy_config)(struct phy *phy, int link_rate,
>> +                               int lanes, u8 swing, u8 pre_emp);
>> +};
>> +
>> +#endif
> Best regards,
>   Enric
>
>> --
>> 2.7.4
>>
>>
>> _______________________________________________
>> Linux-rockchip mailing list
>> Linux-rockchip@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-rockchip
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>
>
>
diff mbox

Patch

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..831a93b 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@ 
 
 #include <linux/mfd/syscon.h>
 #include <linux/phy/phy.h>
+#include <soc/rockchip/rockchip_phy_typec.h>
 
 #define CMN_SSM_BANDGAP			(0x21 << 2)
 #define CMN_SSM_BIAS			(0x22 << 2)
@@ -323,23 +324,31 @@ 
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG			0X30
+#define CLK_PLL1_DIV1			0x20
+#define CLK_PLL1_DIV2			0x30
 #define CLK_PLL_MASK			0x33
 
 #define CMN_READY			BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACK		BIT(3)
 #define DP_PLL_CLOCK_ENABLE		BIT(2)
+#define DP_PLL_ENABLE_ACK		BIT(1)
 #define DP_PLL_ENABLE			BIT(0)
 #define DP_PLL_DATA_RATE_RBR		((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR		((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2		((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK		0xff00
 
-#define DP_MODE_A0			BIT(4)
-#define DP_MODE_A2			BIT(6)
-#define DP_MODE_ENTER_A0		0xc101
-#define DP_MODE_ENTER_A2		0xc104
+#define DP_MODE_MASK			0xf
+#define DP_MODE_ENTER_A0		BIT(0)
+#define DP_MODE_ENTER_A2		BIT(2)
+#define DP_MODE_ENTER_A3		BIT(3)
+#define DP_MODE_A0_ACK			BIT(4)
+#define DP_MODE_A2_ACK			BIT(6)
+#define DP_MODE_A3_ACK			BIT(7)
+#define DP_LINK_RESET_DEASSERTED	BIT(8)
 
-#define PHY_MODE_SET_TIMEOUT		100000
+#define PHY_MODE_SET_TIMEOUT		1000000
 
 #define PIN_ASSIGN_C_E			0x51d9
 #define PIN_ASSIGN_D_F			0x5100
@@ -349,51 +358,7 @@ 
 #define MODE_DFP_USB			BIT(1)
 #define MODE_DFP_DP			BIT(2)
 
-struct usb3phy_reg {
-	u32 offset;
-	u32 enable_bit;
-	u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-	unsigned int reg;
-	struct usb3phy_reg typec_conn_dir;
-	struct usb3phy_reg usb3tousb2_en;
-	struct usb3phy_reg external_psm;
-	struct usb3phy_reg pipe_status;
-	struct usb3phy_reg usb3_host_disable;
-	struct usb3phy_reg usb3_host_port;
-	struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-	struct device *dev;
-	void __iomem *base;
-	struct extcon_dev *extcon;
-	struct regmap *grf_regs;
-	struct clk *clk_core;
-	struct clk *clk_ref;
-	struct reset_control *uphy_rst;
-	struct reset_control *pipe_rst;
-	struct reset_control *tcphy_rst;
-	const struct rockchip_usb3phy_port_cfg *port_cfgs;
-	/* mutex to protect access to individual PHYs */
-	struct mutex lock;
-
-	bool flip;
-	u8 mode;
-};
+#define DEFAULT_RATE			162000
 
 struct phy_reg {
 	u16 value;
@@ -417,15 +382,15 @@  struct phy_reg usb3_pll_cfg[] = {
 	{ 0x8,		CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
 	{ 0xf0,		CMN_PLL1_VCOCAL_INIT },
 	{ 0x18,		CMN_PLL1_VCOCAL_ITER },
 	{ 0x30b9,	CMN_PLL1_VCOCAL_START },
-	{ 0x21c,	CMN_PLL1_INTDIV },
+	{ 0x87,		CMN_PLL1_INTDIV },
 	{ 0,		CMN_PLL1_FRACDIV },
-	{ 0x5,		CMN_PLL1_HIGH_THR },
-	{ 0x35,		CMN_PLL1_SS_CTRL1 },
-	{ 0x7f1e,	CMN_PLL1_SS_CTRL2 },
+	{ 0x22,		CMN_PLL1_HIGH_THR },
+	{ 0x8000,	CMN_PLL1_SS_CTRL1 },
+	{ 0,		CMN_PLL1_SS_CTRL2 },
 	{ 0x20,		CMN_PLL1_DSM_DIAG },
 	{ 0,		CMN_PLLSM1_USER_DEF_CTRL },
 	{ 0,		CMN_DIAG_PLL1_OVRD },
@@ -436,9 +401,52 @@  struct phy_reg dp_pll_cfg[] = {
 	{ 0x8,		CMN_DIAG_PLL1_LF_PROG },
 	{ 0x100,	CMN_DIAG_PLL1_PTATIS_TUNE1 },
 	{ 0x7,		CMN_DIAG_PLL1_PTATIS_TUNE2 },
-	{ 0x4,		CMN_DIAG_PLL1_INCLK_CTRL },
+	{ 0x1,		CMN_DIAG_PLL1_INCLK_CTRL },
+};
+
+struct phy_reg dp_pll_hbr_cfg[] = {
+	{ 0xf0,		CMN_PLL1_VCOCAL_INIT },
+	{ 0x18,		CMN_PLL1_VCOCAL_ITER },
+	{ 0x30b4,	CMN_PLL1_VCOCAL_START },
+	{ 0xe1,		CMN_PLL1_INTDIV },
+	{ 0,		CMN_PLL1_FRACDIV },
+	{ 0x5,		CMN_PLL1_HIGH_THR },
+	{ 0x8000,	CMN_PLL1_SS_CTRL1 },
+	{ 0,		CMN_PLL1_SS_CTRL2 },
+	{ 0x20,		CMN_PLL1_DSM_DIAG },
+	{ 0x1000,	CMN_PLLSM1_USER_DEF_CTRL },
+	{ 0,		CMN_DIAG_PLL1_OVRD },
+	{ 0,		CMN_DIAG_PLL1_FBH_OVRD },
+	{ 0,		CMN_DIAG_PLL1_FBL_OVRD },
+	{ 0x7,		CMN_DIAG_PLL1_V2I_TUNE },
+	{ 0x45,		CMN_DIAG_PLL1_CP_TUNE },
+	{ 0x8,		CMN_DIAG_PLL1_LF_PROG },
+	{ 0x1,		CMN_DIAG_PLL1_PTATIS_TUNE1 },
+	{ 0x1,		CMN_DIAG_PLL1_PTATIS_TUNE2 },
+	{ 0x1,		CMN_DIAG_PLL1_INCLK_CTRL },
 };
 
+struct phy_reg dp_pll_hbr2_cfg[] = {
+	{ 0xf0,		CMN_PLL1_VCOCAL_INIT },
+	{ 0x18,		CMN_PLL1_VCOCAL_ITER },
+	{ 0x30b4,	CMN_PLL1_VCOCAL_START },
+	{ 0xe1,		CMN_PLL1_INTDIV },
+	{ 0,		CMN_PLL1_FRACDIV },
+	{ 0x5,		CMN_PLL1_HIGH_THR },
+	{ 0x8000,	CMN_PLL1_SS_CTRL1 },
+	{ 0,		CMN_PLL1_SS_CTRL2 },
+	{ 0x20,		CMN_PLL1_DSM_DIAG },
+	{ 0x1000,	CMN_PLLSM1_USER_DEF_CTRL },
+	{ 0,		CMN_DIAG_PLL1_OVRD },
+	{ 0,		CMN_DIAG_PLL1_FBH_OVRD },
+	{ 0,		CMN_DIAG_PLL1_FBL_OVRD },
+	{ 0x7,		CMN_DIAG_PLL1_V2I_TUNE },
+	{ 0x45,		CMN_DIAG_PLL1_CP_TUNE },
+	{ 0x8,		CMN_DIAG_PLL1_LF_PROG },
+	{ 0x1,		CMN_DIAG_PLL1_PTATIS_TUNE1 },
+	{ 0x1,		CMN_DIAG_PLL1_PTATIS_TUNE2 },
+	{ 0x1,		CMN_DIAG_PLL1_INCLK_CTRL },
+};
 static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
 	{
 		.reg = 0xff7c0000,
@@ -484,7 +492,7 @@  static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
 
 	rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
 	rdata &= ~CLK_PLL_MASK;
-	rdata |= CLK_PLL_CONFIG;
+	rdata |= CLK_PLL1_DIV2;
 	writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
 }
 
@@ -498,17 +506,44 @@  static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy)
 		       tcphy->base + usb3_pll_cfg[i].addr);
 }
 
-static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
+static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy, int link_rate)
 {
-	u32 i;
+	struct phy_reg *phy_cfg;
+	u32 clk_ctrl;
+	u32 i, cfg_size, hsclk_sel;
+
+	hsclk_sel = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
+	hsclk_sel &= ~CLK_PLL_MASK;
+
+	switch (link_rate) {
+	case 162000:
+		clk_ctrl = DP_PLL_DATA_RATE_RBR;
+		hsclk_sel |= CLK_PLL1_DIV2;
+		phy_cfg = dp_pll_rbr_cfg;
+		cfg_size = ARRAY_SIZE(dp_pll_rbr_cfg);
+		break;
+	case 270000:
+		clk_ctrl = DP_PLL_DATA_RATE_HBR;
+		hsclk_sel |= CLK_PLL1_DIV2;
+		phy_cfg = dp_pll_hbr_cfg;
+		cfg_size = ARRAY_SIZE(dp_pll_hbr_cfg);
+		break;
+	case 540000:
+		clk_ctrl = DP_PLL_DATA_RATE_HBR2;
+		hsclk_sel |= CLK_PLL1_DIV1;
+		phy_cfg = dp_pll_hbr2_cfg;
+		cfg_size = ARRAY_SIZE(dp_pll_hbr2_cfg);
+		break;
+	}
+
+	clk_ctrl |= DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE;
+	writel(clk_ctrl, tcphy->base + DP_CLK_CTL);
 
-	/* set the default mode to RBR */
-	writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR,
-	       tcphy->base + DP_CLK_CTL);
+	writel(hsclk_sel, tcphy->base + CMN_DIAG_HSCLK_SEL);
 
 	/* load the configuration of PLL1 */
-	for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++)
-		writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr);
+	for (i = 0; i < cfg_size; i++)
+		writel(phy_cfg[i].value, tcphy->base + phy_cfg[i].addr);
 }
 
 static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
@@ -535,9 +570,10 @@  static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
 	writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
 }
 
-static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
+static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, int link_rate,
+			      u8 swing, u8 pre_emp, u32 lane)
 {
-	u16 rdata;
+	u16 val;
 
 	writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
 	writel(0x6799, tcphy->base + TX_PSC_A0(lane));
@@ -545,25 +581,31 @@  static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
 	writel(0x98, tcphy->base + TX_PSC_A2(lane));
 	writel(0x98, tcphy->base + TX_PSC_A3(lane));
 
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
-	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
-	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
-	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
-	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
-	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
-
-	writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
-	writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane));
-
-	rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
-	rdata = (rdata & 0x8fff) | 0x6000;
-	writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+	writel(tcphy->config[swing][pre_emp].swing,
+	       tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+	writel(tcphy->config[swing][pre_emp].pe,
+	       tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
+
+	if (swing == 2 && pre_emp == 0 && link_rate != 540000) {
+		writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
+		writel(0x13c, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+	} else {
+		writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+		writel(0x0400, tcphy->base + TX_DIAG_TX_DRV(lane));
+	}
+
+	val = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+	val = val & 0x8fff;
+	switch (link_rate) {
+	case 162000:
+	case 270000:
+		val |= (6 << 12);
+		break;
+	case 540000:
+		val |= (4 << 12);
+		break;
+	}
+	writel(val, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
 }
 
 static inline int property_enable(struct rockchip_typec_phy *tcphy,
@@ -754,30 +796,33 @@  static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
 	tcphy_cfg_24m(tcphy);
 
 	if (mode == MODE_DFP_DP) {
-		tcphy_cfg_dp_pll(tcphy);
+		tcphy_cfg_dp_pll(tcphy, DEFAULT_RATE);
 		for (i = 0; i < 4; i++)
-			tcphy_dp_cfg_lane(tcphy, i);
+			tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, i);
 
 		writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG);
 	} else {
 		tcphy_cfg_usb3_pll(tcphy);
-		tcphy_cfg_dp_pll(tcphy);
+		tcphy_cfg_dp_pll(tcphy, DEFAULT_RATE);
 		if (tcphy->flip) {
 			tcphy_tx_usb3_cfg_lane(tcphy, 3);
 			tcphy_rx_usb3_cfg_lane(tcphy, 2);
-			tcphy_dp_cfg_lane(tcphy, 0);
-			tcphy_dp_cfg_lane(tcphy, 1);
+			tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 0);
+			tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 1);
 		} else {
 			tcphy_tx_usb3_cfg_lane(tcphy, 0);
 			tcphy_rx_usb3_cfg_lane(tcphy, 1);
-			tcphy_dp_cfg_lane(tcphy, 2);
-			tcphy_dp_cfg_lane(tcphy, 3);
+			tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 2);
+			tcphy_dp_cfg_lane(tcphy, DEFAULT_RATE, 0, 0, 3);
 		}
 
 		writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG);
 	}
 
-	writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+	val = readl(tcphy->base + DP_MODE_CTL);
+	val &= ~DP_MODE_MASK;
+	val |= DP_MODE_ENTER_A2 | DP_LINK_RESET_DEASSERTED;
+	writel(val, tcphy->base + DP_MODE_CTL);
 
 	reset_control_deassert(tcphy->uphy_rst);
 
@@ -990,7 +1035,7 @@  static int rockchip_dp_phy_power_on(struct phy *phy)
 	property_enable(tcphy, &cfg->uphy_dp_sel, 1);
 
 	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
-				 val, val & DP_MODE_A2, 1000,
+				 val, val & DP_MODE_A2_ACK, 1000,
 				 PHY_MODE_SET_TIMEOUT);
 	if (ret < 0) {
 		dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n");
@@ -999,13 +1044,19 @@  static int rockchip_dp_phy_power_on(struct phy *phy)
 
 	tcphy_dp_aux_calibration(tcphy);
 
-	writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL);
+	/* enter A0 mode */
+	val = readl(tcphy->base + DP_MODE_CTL);
+	val &= ~DP_MODE_MASK;
+	val |= DP_MODE_ENTER_A0;
+	writel(val, tcphy->base + DP_MODE_CTL);
 
 	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
-				 val, val & DP_MODE_A0, 1000,
+				 val, val & DP_MODE_A0_ACK, 1000,
 				 PHY_MODE_SET_TIMEOUT);
 	if (ret < 0) {
-		writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+		val &= ~DP_MODE_MASK;
+		val |= DP_MODE_ENTER_A2;
+		writel(val, tcphy->base + DP_MODE_CTL);
 		dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
 		goto power_on_finish;
 	}
@@ -1023,6 +1074,7 @@  static int rockchip_dp_phy_power_on(struct phy *phy)
 static int rockchip_dp_phy_power_off(struct phy *phy)
 {
 	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+	u32 val;
 
 	mutex_lock(&tcphy->lock);
 
@@ -1031,7 +1083,10 @@  static int rockchip_dp_phy_power_off(struct phy *phy)
 
 	tcphy->mode &= ~MODE_DFP_DP;
 
-	writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+	val = readl(tcphy->base + DP_MODE_CTL);
+	val &= ~DP_MODE_MASK;
+	val |= DP_MODE_ENTER_A2;
+	writel(val, tcphy->base + DP_MODE_CTL);
 
 	if (tcphy->mode == MODE_DISCONNECT)
 		tcphy_phy_deinit(tcphy);
@@ -1047,6 +1102,30 @@  static const struct phy_ops rockchip_dp_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
+static int type_c_dp_phy_config(struct phy *phy, int link_rate,
+			 int lanes, u8 swing, u8 pre_emp)
+{
+	struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+	u8 i;
+
+	tcphy_cfg_dp_pll(tcphy, link_rate);
+
+	if (tcphy->mode == MODE_DFP_DP) {
+		for (i = 0; i < 4; i++)
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, i);
+	} else {
+		if (tcphy->flip) {
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 0);
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 1);
+		} else {
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 2);
+			tcphy_dp_cfg_lane(tcphy, link_rate, swing, pre_emp, 3);
+		}
+	}
+
+	return 0;
+}
+
 static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
 			  struct device *dev)
 {
@@ -1087,6 +1166,14 @@  static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
 		return PTR_ERR(tcphy->tcphy_rst);
 	}
 
+	/*
+	 * check if phy_config pass from dts, if yes,
+	 * need to use this phy config to do software training later
+	 */
+	if (!of_property_read_u32_array(dev->of_node, "rockchip,phy_config",
+		(u32 *)tcphy->config, sizeof(tcphy->config) / sizeof(u32)))
+		tcphy->need_software_training = 1;
+
 	return 0;
 }
 
@@ -1171,6 +1258,7 @@  static int rockchip_typec_phy_probe(struct platform_device *pdev)
 		}
 	}
 
+	tcphy->typec_phy_config = type_c_dp_phy_config;
 	pm_runtime_enable(dev);
 
 	for_each_available_child_of_node(np, child_np) {
diff --git a/include/soc/rockchip/rockchip_phy_typec.h b/include/soc/rockchip/rockchip_phy_typec.h
new file mode 100644
index 0000000..e25840e
--- /dev/null
+++ b/include/soc/rockchip/rockchip_phy_typec.h
@@ -0,0 +1,72 @@ 
+/*
+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang <hl@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#ifndef __SOC_ROCKCHIP_PHY_TYPEC_H
+#define __SOC_ROCKCHIP_PHY_TYPEC_H
+
+
+struct usb3phy_reg {
+	u32 offset;
+	u32 enable_bit;
+	u32 write_enable;
+};
+
+/**
+ * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
+ * @reg: the base address for usb3-phy config.
+ * @typec_conn_dir: the register of type-c connector direction.
+ * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
+ * @external_psm: the register of type-c phy external psm clock.
+ * @pipe_status: the register of type-c phy pipe status.
+ * @usb3_host_disable: the register of type-c usb3 host disable.
+ * @usb3_host_port: the register of type-c usb3 host port.
+ * @uphy_dp_sel: the register of type-c phy DP select control.
+ */
+struct rockchip_usb3phy_port_cfg {
+	unsigned int reg;
+	struct usb3phy_reg typec_conn_dir;
+	struct usb3phy_reg usb3tousb2_en;
+	struct usb3phy_reg external_psm;
+	struct usb3phy_reg pipe_status;
+	struct usb3phy_reg usb3_host_disable;
+	struct usb3phy_reg usb3_host_port;
+	struct usb3phy_reg uphy_dp_sel;
+};
+
+struct phy_config {
+	int swing;
+	int pe;
+};
+
+struct rockchip_typec_phy {
+	struct device *dev;
+	void __iomem *base;
+	struct extcon_dev *extcon;
+	struct regmap *grf_regs;
+	struct clk *clk_core;
+	struct clk *clk_ref;
+	struct reset_control *uphy_rst;
+	struct reset_control *pipe_rst;
+	struct reset_control *tcphy_rst;
+	struct rockchip_usb3phy_port_cfg *port_cfgs;
+	/* mutex to protect access to individual PHYs */
+	struct mutex lock;
+	struct phy_config config[3][4];
+	u8 need_software_training;
+	bool flip;
+	u8 mode;
+	int (*typec_phy_config)(struct phy *phy, int link_rate,
+				int lanes, u8 swing, u8 pre_emp);
+};
+
+#endif