[PATCH 20/20] phy: rockchip-pcie: switch to HWORD_UPDATE macro

Nicolas Frattaroli
2025-06-12T20:55:43Z

The era of hand-rolled HIWORD_UPDATE macros is over, at least for those
drivers that use constant masks.

The Rockchip PCIe PHY driver, used on the RK3399, has its own definition
of HIWORD_UPDATE.

Remove it, and replace instances of it with bitfield.h's HWORD_UPDATE.
To achieve this, some mask defines are reshuffled, as HWORD_UPDATE uses
the mask as both the mask of bits to write and to derive the shift
amount from in order to shift the value.

In order to ensure that the mask is always a constant, the inst->index
shift is performed after the HWORD_UPDATE, as this is a runtime value.

From this, we gain compile-time error checking, and in my humble opinion
nicer code, as well as a single definition of this macro across the
entire codebase to aid in code comprehension.

Tested on a RK3399 ROCKPro64, where PCIe still works as expected when
accessing an NVMe drive.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
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