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