xref: /openbmc/linux/drivers/phy/microchip/sparx5_serdes.h (revision 2ff8a1eeb5aa8bb471f3756a695b8b69841eb61f)
1*2ff8a1eeSSteen Hegelund /* SPDX-License-Identifier: GPL-2.0+
2*2ff8a1eeSSteen Hegelund  * Microchip Sparx5 SerDes driver
3*2ff8a1eeSSteen Hegelund  *
4*2ff8a1eeSSteen Hegelund  * Copyright (c) 2020 Microchip Technology Inc.
5*2ff8a1eeSSteen Hegelund  */
6*2ff8a1eeSSteen Hegelund 
7*2ff8a1eeSSteen Hegelund #ifndef _SPARX5_SERDES_H_
8*2ff8a1eeSSteen Hegelund #define _SPARX5_SERDES_H_
9*2ff8a1eeSSteen Hegelund 
10*2ff8a1eeSSteen Hegelund #include "sparx5_serdes_regs.h"
11*2ff8a1eeSSteen Hegelund 
12*2ff8a1eeSSteen Hegelund #define SPX5_SERDES_MAX       33
13*2ff8a1eeSSteen Hegelund 
14*2ff8a1eeSSteen Hegelund enum sparx5_serdes_type {
15*2ff8a1eeSSteen Hegelund 	SPX5_SDT_6G  = 6,
16*2ff8a1eeSSteen Hegelund 	SPX5_SDT_10G = 10,
17*2ff8a1eeSSteen Hegelund 	SPX5_SDT_25G = 25,
18*2ff8a1eeSSteen Hegelund };
19*2ff8a1eeSSteen Hegelund 
20*2ff8a1eeSSteen Hegelund enum sparx5_serdes_mode {
21*2ff8a1eeSSteen Hegelund 	SPX5_SD_MODE_NONE,
22*2ff8a1eeSSteen Hegelund 	SPX5_SD_MODE_2G5,
23*2ff8a1eeSSteen Hegelund 	SPX5_SD_MODE_QSGMII,
24*2ff8a1eeSSteen Hegelund 	SPX5_SD_MODE_100FX,
25*2ff8a1eeSSteen Hegelund 	SPX5_SD_MODE_1000BASEX,
26*2ff8a1eeSSteen Hegelund 	SPX5_SD_MODE_SFI,
27*2ff8a1eeSSteen Hegelund };
28*2ff8a1eeSSteen Hegelund 
29*2ff8a1eeSSteen Hegelund struct sparx5_serdes_private {
30*2ff8a1eeSSteen Hegelund 	struct device *dev;
31*2ff8a1eeSSteen Hegelund 	void __iomem *regs[NUM_TARGETS];
32*2ff8a1eeSSteen Hegelund 	struct phy *phys[SPX5_SERDES_MAX];
33*2ff8a1eeSSteen Hegelund 	bool cmu_enabled;
34*2ff8a1eeSSteen Hegelund 	unsigned long coreclock;
35*2ff8a1eeSSteen Hegelund };
36*2ff8a1eeSSteen Hegelund 
37*2ff8a1eeSSteen Hegelund struct sparx5_serdes_macro {
38*2ff8a1eeSSteen Hegelund 	struct sparx5_serdes_private *priv;
39*2ff8a1eeSSteen Hegelund 	u32 sidx;
40*2ff8a1eeSSteen Hegelund 	u32 stpidx;
41*2ff8a1eeSSteen Hegelund 	enum sparx5_serdes_type serdestype;
42*2ff8a1eeSSteen Hegelund 	enum sparx5_serdes_mode serdesmode;
43*2ff8a1eeSSteen Hegelund 	phy_interface_t portmode;
44*2ff8a1eeSSteen Hegelund 	int speed;
45*2ff8a1eeSSteen Hegelund 	enum phy_media media;
46*2ff8a1eeSSteen Hegelund };
47*2ff8a1eeSSteen Hegelund 
48*2ff8a1eeSSteen Hegelund /* Read, Write and modify registers content.
49*2ff8a1eeSSteen Hegelund  * The register definition macros start at the id
50*2ff8a1eeSSteen Hegelund  */
51*2ff8a1eeSSteen Hegelund static inline void __iomem *sdx5_addr(void __iomem *base[],
52*2ff8a1eeSSteen Hegelund 				      int id, int tinst, int tcnt,
53*2ff8a1eeSSteen Hegelund 				      int gbase, int ginst,
54*2ff8a1eeSSteen Hegelund 				      int gcnt, int gwidth,
55*2ff8a1eeSSteen Hegelund 				      int raddr, int rinst,
56*2ff8a1eeSSteen Hegelund 				      int rcnt, int rwidth)
57*2ff8a1eeSSteen Hegelund {
58*2ff8a1eeSSteen Hegelund 	WARN_ON((tinst) >= tcnt);
59*2ff8a1eeSSteen Hegelund 	WARN_ON((ginst) >= gcnt);
60*2ff8a1eeSSteen Hegelund 	WARN_ON((rinst) >= rcnt);
61*2ff8a1eeSSteen Hegelund 	return base[id + (tinst)] +
62*2ff8a1eeSSteen Hegelund 		gbase + ((ginst) * gwidth) +
63*2ff8a1eeSSteen Hegelund 		raddr + ((rinst) * rwidth);
64*2ff8a1eeSSteen Hegelund }
65*2ff8a1eeSSteen Hegelund 
66*2ff8a1eeSSteen Hegelund static inline void __iomem *sdx5_inst_baseaddr(void __iomem *base,
67*2ff8a1eeSSteen Hegelund 					       int gbase, int ginst,
68*2ff8a1eeSSteen Hegelund 					       int gcnt, int gwidth,
69*2ff8a1eeSSteen Hegelund 					       int raddr, int rinst,
70*2ff8a1eeSSteen Hegelund 					       int rcnt, int rwidth)
71*2ff8a1eeSSteen Hegelund {
72*2ff8a1eeSSteen Hegelund 	WARN_ON((ginst) >= gcnt);
73*2ff8a1eeSSteen Hegelund 	WARN_ON((rinst) >= rcnt);
74*2ff8a1eeSSteen Hegelund 	return base +
75*2ff8a1eeSSteen Hegelund 		gbase + ((ginst) * gwidth) +
76*2ff8a1eeSSteen Hegelund 		raddr + ((rinst) * rwidth);
77*2ff8a1eeSSteen Hegelund }
78*2ff8a1eeSSteen Hegelund 
79*2ff8a1eeSSteen Hegelund static inline void sdx5_rmw(u32 val, u32 mask, struct sparx5_serdes_private *priv,
80*2ff8a1eeSSteen Hegelund 			    int id, int tinst, int tcnt,
81*2ff8a1eeSSteen Hegelund 			    int gbase, int ginst, int gcnt, int gwidth,
82*2ff8a1eeSSteen Hegelund 			    int raddr, int rinst, int rcnt, int rwidth)
83*2ff8a1eeSSteen Hegelund {
84*2ff8a1eeSSteen Hegelund 	u32 nval;
85*2ff8a1eeSSteen Hegelund 	void __iomem *addr =
86*2ff8a1eeSSteen Hegelund 		sdx5_addr(priv->regs, id, tinst, tcnt,
87*2ff8a1eeSSteen Hegelund 			  gbase, ginst, gcnt, gwidth,
88*2ff8a1eeSSteen Hegelund 			  raddr, rinst, rcnt, rwidth);
89*2ff8a1eeSSteen Hegelund 	nval = readl(addr);
90*2ff8a1eeSSteen Hegelund 	nval = (nval & ~mask) | (val & mask);
91*2ff8a1eeSSteen Hegelund 	writel(nval, addr);
92*2ff8a1eeSSteen Hegelund }
93*2ff8a1eeSSteen Hegelund 
94*2ff8a1eeSSteen Hegelund static inline void sdx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem,
95*2ff8a1eeSSteen Hegelund 				 int id, int tinst, int tcnt,
96*2ff8a1eeSSteen Hegelund 				 int gbase, int ginst, int gcnt, int gwidth,
97*2ff8a1eeSSteen Hegelund 				 int raddr, int rinst, int rcnt, int rwidth)
98*2ff8a1eeSSteen Hegelund {
99*2ff8a1eeSSteen Hegelund 	u32 nval;
100*2ff8a1eeSSteen Hegelund 	void __iomem *addr =
101*2ff8a1eeSSteen Hegelund 		sdx5_inst_baseaddr(iomem,
102*2ff8a1eeSSteen Hegelund 				   gbase, ginst, gcnt, gwidth,
103*2ff8a1eeSSteen Hegelund 				   raddr, rinst, rcnt, rwidth);
104*2ff8a1eeSSteen Hegelund 	nval = readl(addr);
105*2ff8a1eeSSteen Hegelund 	nval = (nval & ~mask) | (val & mask);
106*2ff8a1eeSSteen Hegelund 	writel(nval, addr);
107*2ff8a1eeSSteen Hegelund }
108*2ff8a1eeSSteen Hegelund 
109*2ff8a1eeSSteen Hegelund static inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr)
110*2ff8a1eeSSteen Hegelund {
111*2ff8a1eeSSteen Hegelund 	u32 nval;
112*2ff8a1eeSSteen Hegelund 
113*2ff8a1eeSSteen Hegelund 	nval = readl(addr);
114*2ff8a1eeSSteen Hegelund 	nval = (nval & ~mask) | (val & mask);
115*2ff8a1eeSSteen Hegelund 	writel(nval, addr);
116*2ff8a1eeSSteen Hegelund }
117*2ff8a1eeSSteen Hegelund 
118*2ff8a1eeSSteen Hegelund static inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv,
119*2ff8a1eeSSteen Hegelund 					  int id, int tinst)
120*2ff8a1eeSSteen Hegelund {
121*2ff8a1eeSSteen Hegelund 	return priv->regs[id + tinst];
122*2ff8a1eeSSteen Hegelund }
123*2ff8a1eeSSteen Hegelund 
124*2ff8a1eeSSteen Hegelund static inline void __iomem *sdx5_inst_addr(void __iomem *iomem,
125*2ff8a1eeSSteen Hegelund 					   int id, int tinst, int tcnt,
126*2ff8a1eeSSteen Hegelund 					   int gbase,
127*2ff8a1eeSSteen Hegelund 					   int ginst, int gcnt, int gwidth,
128*2ff8a1eeSSteen Hegelund 					   int raddr,
129*2ff8a1eeSSteen Hegelund 					   int rinst, int rcnt, int rwidth)
130*2ff8a1eeSSteen Hegelund {
131*2ff8a1eeSSteen Hegelund 	return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth,
132*2ff8a1eeSSteen Hegelund 				  raddr, rinst, rcnt, rwidth);
133*2ff8a1eeSSteen Hegelund }
134*2ff8a1eeSSteen Hegelund 
135*2ff8a1eeSSteen Hegelund 
136*2ff8a1eeSSteen Hegelund #endif /* _SPARX5_SERDES_REGS_H_ */
137