xref: /linux/drivers/phy/microchip/sparx5_serdes.h (revision 2db7289f)
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 	unsigned long coreclock;
34*2ff8a1eeSSteen Hegelund };
35*2ff8a1eeSSteen Hegelund 
36*2ff8a1eeSSteen Hegelund struct sparx5_serdes_macro {
37*2ff8a1eeSSteen Hegelund 	struct sparx5_serdes_private *priv;
38*2ff8a1eeSSteen Hegelund 	u32 sidx;
39*2ff8a1eeSSteen Hegelund 	u32 stpidx;
40*2ff8a1eeSSteen Hegelund 	enum sparx5_serdes_type serdestype;
41*2ff8a1eeSSteen Hegelund 	enum sparx5_serdes_mode serdesmode;
42*2ff8a1eeSSteen Hegelund 	phy_interface_t portmode;
43*2ff8a1eeSSteen Hegelund 	int speed;
44*2ff8a1eeSSteen Hegelund 	enum phy_media media;
45*2ff8a1eeSSteen Hegelund };
46*2ff8a1eeSSteen Hegelund 
47*2ff8a1eeSSteen Hegelund /* Read, Write and modify registers content.
48*2ff8a1eeSSteen Hegelund  * The register definition macros start at the id
49*2ff8a1eeSSteen Hegelund  */
sdx5_addr(void __iomem * base[],int id,int tinst,int tcnt,int gbase,int ginst,int gcnt,int gwidth,int raddr,int rinst,int rcnt,int rwidth)50*2ff8a1eeSSteen Hegelund static inline void __iomem *sdx5_addr(void __iomem *base[],
51*2ff8a1eeSSteen Hegelund 				      int id, int tinst, int tcnt,
52*2ff8a1eeSSteen Hegelund 				      int gbase, int ginst,
53*2ff8a1eeSSteen Hegelund 				      int gcnt, int gwidth,
54*2ff8a1eeSSteen Hegelund 				      int raddr, int rinst,
55*2ff8a1eeSSteen Hegelund 				      int rcnt, int rwidth)
56*2ff8a1eeSSteen Hegelund {
57*2ff8a1eeSSteen Hegelund 	WARN_ON((tinst) >= tcnt);
58*2ff8a1eeSSteen Hegelund 	WARN_ON((ginst) >= gcnt);
59*2ff8a1eeSSteen Hegelund 	WARN_ON((rinst) >= rcnt);
60*2ff8a1eeSSteen Hegelund 	return base[id + (tinst)] +
61*2ff8a1eeSSteen Hegelund 		gbase + ((ginst) * gwidth) +
62*2ff8a1eeSSteen Hegelund 		raddr + ((rinst) * rwidth);
63*2ff8a1eeSSteen Hegelund }
64*2ff8a1eeSSteen Hegelund 
sdx5_inst_baseaddr(void __iomem * base,int gbase,int ginst,int gcnt,int gwidth,int raddr,int rinst,int rcnt,int rwidth)65*2ff8a1eeSSteen Hegelund static inline void __iomem *sdx5_inst_baseaddr(void __iomem *base,
66*2ff8a1eeSSteen Hegelund 					       int gbase, int ginst,
67*2ff8a1eeSSteen Hegelund 					       int gcnt, int gwidth,
68*2ff8a1eeSSteen Hegelund 					       int raddr, int rinst,
69*2ff8a1eeSSteen Hegelund 					       int rcnt, int rwidth)
70*2ff8a1eeSSteen Hegelund {
71*2ff8a1eeSSteen Hegelund 	WARN_ON((ginst) >= gcnt);
72*2ff8a1eeSSteen Hegelund 	WARN_ON((rinst) >= rcnt);
73*2ff8a1eeSSteen Hegelund 	return base +
74*2ff8a1eeSSteen Hegelund 		gbase + ((ginst) * gwidth) +
75*2ff8a1eeSSteen Hegelund 		raddr + ((rinst) * rwidth);
76*2ff8a1eeSSteen Hegelund }
77*2ff8a1eeSSteen Hegelund 
sdx5_rmw(u32 val,u32 mask,struct sparx5_serdes_private * priv,int id,int tinst,int tcnt,int gbase,int ginst,int gcnt,int gwidth,int raddr,int rinst,int rcnt,int rwidth)78*2ff8a1eeSSteen Hegelund static inline void sdx5_rmw(u32 val, u32 mask, struct sparx5_serdes_private *priv,
79*2ff8a1eeSSteen Hegelund 			    int id, int tinst, int tcnt,
80*2ff8a1eeSSteen Hegelund 			    int gbase, int ginst, int gcnt, int gwidth,
81*2ff8a1eeSSteen Hegelund 			    int raddr, int rinst, int rcnt, int rwidth)
82*2ff8a1eeSSteen Hegelund {
83*2ff8a1eeSSteen Hegelund 	u32 nval;
84*2ff8a1eeSSteen Hegelund 	void __iomem *addr =
85*2ff8a1eeSSteen Hegelund 		sdx5_addr(priv->regs, id, tinst, tcnt,
86*2ff8a1eeSSteen Hegelund 			  gbase, ginst, gcnt, gwidth,
87*2ff8a1eeSSteen Hegelund 			  raddr, rinst, rcnt, rwidth);
88*2ff8a1eeSSteen Hegelund 	nval = readl(addr);
89*2ff8a1eeSSteen Hegelund 	nval = (nval & ~mask) | (val & mask);
90*2ff8a1eeSSteen Hegelund 	writel(nval, addr);
91*2ff8a1eeSSteen Hegelund }
92*2ff8a1eeSSteen Hegelund 
sdx5_inst_rmw(u32 val,u32 mask,void __iomem * iomem,int id,int tinst,int tcnt,int gbase,int ginst,int gcnt,int gwidth,int raddr,int rinst,int rcnt,int rwidth)93*2ff8a1eeSSteen Hegelund static inline void sdx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem,
94*2ff8a1eeSSteen Hegelund 				 int id, int tinst, int tcnt,
95*2ff8a1eeSSteen Hegelund 				 int gbase, int ginst, int gcnt, int gwidth,
96*2ff8a1eeSSteen Hegelund 				 int raddr, int rinst, int rcnt, int rwidth)
97*2ff8a1eeSSteen Hegelund {
98*2ff8a1eeSSteen Hegelund 	u32 nval;
99*2ff8a1eeSSteen Hegelund 	void __iomem *addr =
100*2ff8a1eeSSteen Hegelund 		sdx5_inst_baseaddr(iomem,
101*2ff8a1eeSSteen Hegelund 				   gbase, ginst, gcnt, gwidth,
102*2ff8a1eeSSteen Hegelund 				   raddr, rinst, rcnt, rwidth);
103*2ff8a1eeSSteen Hegelund 	nval = readl(addr);
104*2ff8a1eeSSteen Hegelund 	nval = (nval & ~mask) | (val & mask);
105*2ff8a1eeSSteen Hegelund 	writel(nval, addr);
106*2ff8a1eeSSteen Hegelund }
107*2ff8a1eeSSteen Hegelund 
sdx5_rmw_addr(u32 val,u32 mask,void __iomem * addr)108*2ff8a1eeSSteen Hegelund static inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr)
109*2ff8a1eeSSteen Hegelund {
110*2ff8a1eeSSteen Hegelund 	u32 nval;
111*2ff8a1eeSSteen Hegelund 
112*2ff8a1eeSSteen Hegelund 	nval = readl(addr);
113*2ff8a1eeSSteen Hegelund 	nval = (nval & ~mask) | (val & mask);
114*2ff8a1eeSSteen Hegelund 	writel(nval, addr);
115*2ff8a1eeSSteen Hegelund }
116*2ff8a1eeSSteen Hegelund 
sdx5_inst_get(struct sparx5_serdes_private * priv,int id,int tinst)117*2ff8a1eeSSteen Hegelund static inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv,
118*2ff8a1eeSSteen Hegelund 					  int id, int tinst)
119*2ff8a1eeSSteen Hegelund {
120*2ff8a1eeSSteen Hegelund 	return priv->regs[id + tinst];
121*2ff8a1eeSSteen Hegelund }
122*2ff8a1eeSSteen Hegelund 
sdx5_inst_addr(void __iomem * iomem,int id,int tinst,int tcnt,int gbase,int ginst,int gcnt,int gwidth,int raddr,int rinst,int rcnt,int rwidth)123*2ff8a1eeSSteen Hegelund static inline void __iomem *sdx5_inst_addr(void __iomem *iomem,
124*2ff8a1eeSSteen Hegelund 					   int id, int tinst, int tcnt,
125*2ff8a1eeSSteen Hegelund 					   int gbase,
126*2ff8a1eeSSteen Hegelund 					   int ginst, int gcnt, int gwidth,
127*2ff8a1eeSSteen Hegelund 					   int raddr,
128*2ff8a1eeSSteen Hegelund 					   int rinst, int rcnt, int rwidth)
129*2ff8a1eeSSteen Hegelund {
130*2ff8a1eeSSteen Hegelund 	return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth,
131*2ff8a1eeSSteen Hegelund 				  raddr, rinst, rcnt, rwidth);
132*2ff8a1eeSSteen Hegelund }
133*2ff8a1eeSSteen Hegelund 
134*2ff8a1eeSSteen Hegelund 
135*2ff8a1eeSSteen Hegelund #endif /* _SPARX5_SERDES_REGS_H_ */
136