xref: /linux/drivers/phy/freescale/phy-fsl-lynx-core.h (revision 62cf248de32f061d99cf7cd1675419d739031c5e)
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