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