drivers/phy/rockchip/phy-rockchip-pcie.c

Source file repositories/reference/linux-study-clean/drivers/phy/rockchip/phy-rockchip-pcie.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/rockchip/phy-rockchip-pcie.c
Extension
.c
Size
8811 bytes
Lines
339
Domain
Driver Families
Bucket
drivers/phy
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct rockchip_pcie_data {
	unsigned int pcie_conf;
	unsigned int pcie_status;
	unsigned int pcie_laneoff;
};

struct rockchip_pcie_phy {
	const struct rockchip_pcie_data *phy_data;
	struct regmap *reg_base;
	struct phy_pcie_instance {
		struct phy *phy;
		u32 index;
	} phys[PHY_MAX_LANE_NUM];
	struct mutex pcie_mutex;
	struct reset_control *phy_rst;
	struct clk *clk_pciephy_ref;
	int pwr_cnt;
	int init_cnt;
};

static struct rockchip_pcie_phy *to_pcie_phy(struct phy_pcie_instance *inst)
{
	return container_of(inst, struct rockchip_pcie_phy,
					phys[inst->index]);
}

static struct phy *rockchip_pcie_phy_of_xlate(struct device *dev,
					      const struct of_phandle_args *args)
{
	struct rockchip_pcie_phy *rk_phy = dev_get_drvdata(dev);

	if (args->args_count == 0)
		return rk_phy->phys[0].phy;

	if (WARN_ON(args->args[0] >= PHY_MAX_LANE_NUM))
		return ERR_PTR(-ENODEV);

	return rk_phy->phys[args->args[0]].phy;
}


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,
		     FIELD_PREP_WM16(PHY_CFG_DATA_MASK, data) |
		     FIELD_PREP_WM16(PHY_CFG_ADDR_MASK, addr));
	udelay(1);
	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
		     FIELD_PREP_WM16(PHY_CFG_WR_MASK, PHY_CFG_WR_ENABLE));
	udelay(1);
	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
		     FIELD_PREP_WM16(PHY_CFG_WR_MASK, PHY_CFG_WR_DISABLE));
}

static int rockchip_pcie_phy_power_off(struct phy *phy)
{
	struct phy_pcie_instance *inst = phy_get_drvdata(phy);
	struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
	int err = 0;

	guard(mutex)(&rk_phy->pcie_mutex);

	regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_laneoff,
		     FIELD_PREP_WM16(PHY_LANE_IDLE_MASK,
				     PHY_LANE_IDLE_OFF) << inst->index);

	if (--rk_phy->pwr_cnt) {
		return 0;
	}

	err = reset_control_assert(rk_phy->phy_rst);
	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,
			     FIELD_PREP_WM16(PHY_LANE_IDLE_MASK,
					     !PHY_LANE_IDLE_OFF) << inst->index);
		return err;
	}

	return err;
}

static int rockchip_pcie_phy_power_on(struct phy *phy)
{
	struct phy_pcie_instance *inst = phy_get_drvdata(phy);
	struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
	int err = 0;
	u32 status;

Annotation

Implementation Notes