Tested on a RK3399 ROCKPro64, where PCIe still works as expected when accessing an NVMe drive. Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@xxxxxxxxxxxxx> --- drivers/phy/rockchip/phy-rockchip-pcie.c | 72 ++++++++++---------------------- 1 file changed, 21 insertions(+), 51 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-pcie.c b/drivers/phy/rockchip/phy-rockchip-pcie.c index bd44af36c67a5a504801275c1b0384d373fe7ec7..7c486ecb96ffe1589fa077d7d2b079e02f4f6769 100644 --- a/drivers/phy/rockchip/phy-rockchip-pcie.c +++ b/drivers/phy/rockchip/phy-rockchip-pcie.c @@ -6,6 +6,7 @@ * Copyright (C) 2016 ROCKCHIP, Inc. */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/io.h> @@ -18,23 +19,14 @@ #include <linux/regmap.h> #include <linux/reset.h> -/* - * The higher 16-bit of this register is used for write protection - * only if BIT(x + 16) set to 1 the BIT(x) can be written. - */ -#define HIWORD_UPDATE(val, mask, shift) \ - ((val) << (shift) | (mask) << ((shift) + 16)) #define PHY_MAX_LANE_NUM 4 -#define PHY_CFG_DATA_SHIFT 7 -#define PHY_CFG_ADDR_SHIFT 1 -#define PHY_CFG_DATA_MASK 0xf -#define PHY_CFG_ADDR_MASK 0x3f -#define PHY_CFG_RD_MASK 0x3ff +#define PHY_CFG_DATA_MASK GENMASK(10, 7) +#define PHY_CFG_ADDR_MASK GENMASK(6, 1) +#define PHY_CFG_RD_MASK GENMASK(9, 0) #define PHY_CFG_WR_ENABLE 1 #define PHY_CFG_WR_DISABLE 1 -#define PHY_CFG_WR_SHIFT 0 -#define PHY_CFG_WR_MASK 1 +#define PHY_CFG_WR_MASK BIT(0) #define PHY_CFG_PLL_LOCK 0x10 #define PHY_CFG_CLK_TEST 0x10 #define PHY_CFG_CLK_SCC 0x12 @@ -49,11 +41,7 @@ #define PHY_LANE_RX_DET_SHIFT 11 #define PHY_LANE_RX_DET_TH 0x1 #define PHY_LANE_IDLE_OFF 0x1 -#define PHY_LANE_IDLE_MASK 0x1 -#define PHY_LANE_IDLE_A_SHIFT 3 -#define PHY_LANE_IDLE_B_SHIFT 4 -#define PHY_LANE_IDLE_C_SHIFT 5 -#define PHY_LANE_IDLE_D_SHIFT 6 +#define PHY_LANE_IDLE_MASK BIT(3) struct rockchip_pcie_data { unsigned int pcie_conf; @@ -100,22 +88,14 @@ static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy, u32 addr, u32 data) { regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, - HIWORD_UPDATE(data, - PHY_CFG_DATA_MASK, - PHY_CFG_DATA_SHIFT) | - HIWORD_UPDATE(addr, - PHY_CFG_ADDR_MASK, - PHY_CFG_ADDR_SHIFT)); + HWORD_UPDATE(PHY_CFG_DATA_MASK, data) | + HWORD_UPDATE(PHY_CFG_ADDR_MASK, addr)); udelay(1); regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, - HIWORD_UPDATE(PHY_CFG_WR_ENABLE, - PHY_CFG_WR_MASK, - PHY_CFG_WR_SHIFT)); + HWORD_UPDATE(PHY_CFG_WR_MASK, PHY_CFG_WR_ENABLE)); udelay(1); regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, - HIWORD_UPDATE(PHY_CFG_WR_DISABLE, - PHY_CFG_WR_MASK, - PHY_CFG_WR_SHIFT)); + HWORD_UPDATE(PHY_CFG_WR_MASK, PHY_CFG_WR_DISABLE)); } static int rockchip_pcie_phy_power_off(struct phy *phy) @@ -126,11 +106,9 @@ static int rockchip_pcie_phy_power_off(struct phy *phy) guard(mutex)(&rk_phy->pcie_mutex); - regmap_write(rk_phy->reg_base, - rk_phy->phy_data->pcie_laneoff, - HIWORD_UPDATE(PHY_LANE_IDLE_OFF, - PHY_LANE_IDLE_MASK, - PHY_LANE_IDLE_A_SHIFT + inst->index)); + regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_laneoff, + HWORD_UPDATE(PHY_LANE_IDLE_MASK, + PHY_LANE_IDLE_OFF) << inst->index); if (--rk_phy->pwr_cnt) { return 0; @@ -140,11 +118,9 @@ static int rockchip_pcie_phy_power_off(struct phy *phy) if (err) { dev_err(&phy->dev, "assert phy_rst err %d\n", err); rk_phy->pwr_cnt++; - regmap_write(rk_phy->reg_base, - rk_phy->phy_data->pcie_laneoff, - HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, - PHY_LANE_IDLE_MASK, - PHY_LANE_IDLE_A_SHIFT + inst->index)); + regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_laneoff, + HWORD_UPDATE(PHY_LANE_IDLE_MASK, + !PHY_LANE_IDLE_OFF) << inst->index); return err; } @@ -172,15 +148,11 @@ static int rockchip_pcie_phy_power_on(struct phy *phy) } regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, - HIWORD_UPDATE(PHY_CFG_PLL_LOCK, - PHY_CFG_ADDR_MASK, - PHY_CFG_ADDR_SHIFT)); + HWORD_UPDATE(PHY_CFG_ADDR_MASK, PHY_CFG_PLL_LOCK)); - regmap_write(rk_phy->reg_base, - rk_phy->phy_data->pcie_laneoff, - HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, - PHY_LANE_IDLE_MASK, - PHY_LANE_IDLE_A_SHIFT + inst->index)); + regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_laneoff, + HWORD_UPDATE(PHY_LANE_IDLE_MASK, + !PHY_LANE_IDLE_OFF) << inst->index); /* * No documented timeout value for phy operation below, @@ -211,9 +183,7 @@ static int rockchip_pcie_phy_power_on(struct phy *phy) } regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, - HIWORD_UPDATE(PHY_CFG_PLL_LOCK, - PHY_CFG_ADDR_MASK, - PHY_CFG_ADDR_SHIFT)); + HWORD_UPDATE(PHY_CFG_ADDR_MASK, PHY_CFG_PLL_LOCK)); err = regmap_read_poll_timeout(rk_phy->reg_base, rk_phy->phy_data->pcie_status, -- 2.49.0