1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* Copyright 2025-2026 NXP */ 3 4 #ifndef _PHY_FSL_LYNX_CORE_H 5 #define _PHY_FSL_LYNX_CORE_H 6 7 #include <linux/phy/phy.h> 8 #include <linux/phy.h> 9 #include <soc/fsl/phy-fsl-lynx.h> 10 11 #define LYNX_NUM_PLL 2 12 #define LYNX_QUIRK_HAS_HARDCODED_USXGMII BIT(0) 13 14 struct lynx_priv; 15 struct lynx_lane; 16 17 struct lynx_pccr { 18 int offset; 19 int width; 20 int shift; 21 }; 22 23 struct lynx_pll { 24 struct lynx_priv *priv; 25 int id; 26 int refclk_sel; 27 int frate_sel; 28 bool enabled; 29 bool locked; 30 DECLARE_BITMAP(supported, LANE_MODE_MAX); 31 }; 32 33 struct lynx_lane { 34 struct lynx_priv *priv; 35 struct phy *phy; 36 bool powered_up; 37 bool init; 38 unsigned int id; 39 enum lynx_lane_mode mode; 40 u32 default_pccr[LANE_MODE_MAX]; 41 }; 42 43 struct lynx_info { 44 int (*get_pccr)(enum lynx_lane_mode lane_mode, int lane, 45 struct lynx_pccr *pccr); 46 int (*get_pcvt_offset)(int lane, enum lynx_lane_mode mode); 47 bool (*lane_supports_mode)(int lane, enum lynx_lane_mode mode); 48 void (*pll_read_configuration)(struct lynx_pll *pll); 49 void (*lane_read_configuration)(struct lynx_lane *lane); 50 void (*cdr_lock_check)(struct lynx_lane *lane); 51 int first_lane; 52 int num_lanes; 53 int index; 54 unsigned long quirks; 55 }; 56 57 struct lynx_priv { 58 void __iomem *base; 59 struct device *dev; 60 const struct lynx_info *info; 61 /* Serialize concurrent access to registers shared between lanes, 62 * like PCCn 63 */ 64 spinlock_t pcc_lock; 65 bool big_endian; 66 struct lynx_pll pll[LYNX_NUM_PLL]; 67 struct lynx_lane *lane; 68 69 struct delayed_work cdr_check; 70 }; 71 72 static inline u32 lynx_read(struct lynx_priv *priv, unsigned long off) 73 { 74 void __iomem *reg = priv->base + off; 75 76 if (priv->big_endian) 77 return ioread32be(reg); 78 79 return ioread32(reg); 80 } 81 82 static inline void lynx_write(struct lynx_priv *priv, unsigned long off, u32 val) 83 { 84 void __iomem *reg = priv->base + off; 85 86 if (priv->big_endian) 87 return iowrite32be(val, reg); 88 89 return iowrite32(val, reg); 90 } 91 92 static inline void lynx_rmw(struct lynx_priv *priv, unsigned long off, u32 val, 93 u32 mask) 94 { 95 u32 orig, tmp; 96 97 orig = lynx_read(priv, off); 98 tmp = orig & ~mask; 99 tmp |= val; 100 if (orig != tmp) 101 lynx_write(priv, off, tmp); 102 } 103 104 #define lynx_lane_rmw(lane, reg, val, mask) \ 105 lynx_rmw((lane)->priv, reg(lane->id), val, mask) 106 #define lynx_lane_read(lane, reg) \ 107 lynx_read((lane)->priv, reg((lane)->id)) 108 #define lynx_lane_write(lane, reg, val) \ 109 lynx_write((lane)->priv, reg((lane)->id), val) 110 #define lynx_pll_read(pll, reg) \ 111 lynx_read((pll)->priv, reg((pll)->id)) 112 113 int lynx_probe(struct platform_device *pdev, const struct lynx_info *info, 114 const struct phy_ops *phy_ops); 115 void lynx_remove(struct platform_device *pdev); 116 117 const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode); 118 enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf); 119 bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode); 120 int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode, 121 int submode, enum lynx_lane_mode *lane_mode); 122 123 struct lynx_pll *lynx_pll_get(struct lynx_priv *priv, enum lynx_lane_mode mode); 124 125 int lynx_pccr_read(struct lynx_lane *lane, enum lynx_lane_mode mode, u32 *val); 126 int lynx_pccr_write(struct lynx_lane *lane, enum lynx_lane_mode mode, u32 val); 127 int lynx_pcvt_read(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, 128 u32 *val); 129 int lynx_pcvt_write(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, 130 u32 val); 131 int lynx_pcvt_rmw(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, 132 u32 val, u32 mask); 133 134 #endif 135