xref: /linux/drivers/phy/microchip/sparx5_serdes.h (revision 04c319e05d0b08cc789db7abccce0fcb13dbab16)
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 enum sparx5_10g28cmu_mode {
30 	SPX5_SD10G28_CMU_MAIN = 0,
31 	SPX5_SD10G28_CMU_AUX1 = 1,
32 	SPX5_SD10G28_CMU_AUX2 = 3,
33 	SPX5_SD10G28_CMU_NONE = 4,
34 	SPX5_SD10G28_CMU_MAX,
35 };
36 
37 enum sparx5_target {
38 	SPX5_TARGET_SPARX5,
39 	SPX5_TARGET_LAN969X,
40 
41 };
42 
43 struct sparx5_serdes_macro {
44 	struct sparx5_serdes_private *priv;
45 	u32 sidx;
46 	u32 stpidx;
47 	enum sparx5_serdes_type serdestype;
48 	enum sparx5_serdes_mode serdesmode;
49 	phy_interface_t portmode;
50 	int speed;
51 	enum phy_media media;
52 };
53 
54 struct sparx5_serdes_consts {
55 	int sd_max;
56 	int cmu_max;
57 };
58 
59 struct sparx5_serdes_ops {
60 	void (*serdes_type_set)(struct sparx5_serdes_macro *macro, int sidx);
61 	int (*serdes_cmu_get)(enum sparx5_10g28cmu_mode mode, int sd_index);
62 };
63 
64 struct sparx5_serdes_match_data {
65 	enum sparx5_target type;
66 	const struct sparx5_serdes_consts consts;
67 	const struct sparx5_serdes_ops ops;
68 	const struct sparx5_serdes_io_resource *iomap;
69 	int iomap_size;
70 	const unsigned int *tsize;
71 };
72 
73 struct sparx5_serdes_private {
74 	struct device *dev;
75 	void __iomem *regs[NUM_TARGETS];
76 	struct phy *phys[SPX5_SERDES_MAX];
77 	unsigned long coreclock;
78 	const struct sparx5_serdes_match_data *data;
79 };
80 
81 /* Read, Write and modify registers content.
82  * The register definition macros start at the id
83  */
84 static inline void __iomem *sdx5_addr(void __iomem *base[],
85 				      int id, int tinst, int tcnt,
86 				      int gbase, int ginst,
87 				      int gcnt, int gwidth,
88 				      int raddr, int rinst,
89 				      int rcnt, int rwidth)
90 {
91 	WARN_ON((tinst) >= tcnt);
92 	WARN_ON((ginst) >= gcnt);
93 	WARN_ON((rinst) >= rcnt);
94 	return base[id + (tinst)] +
95 		gbase + ((ginst) * gwidth) +
96 		raddr + ((rinst) * rwidth);
97 }
98 
99 static inline void __iomem *sdx5_inst_baseaddr(void __iomem *base,
100 					       int gbase, int ginst,
101 					       int gcnt, int gwidth,
102 					       int raddr, int rinst,
103 					       int rcnt, int rwidth)
104 {
105 	WARN_ON((ginst) >= gcnt);
106 	WARN_ON((rinst) >= rcnt);
107 	return base +
108 		gbase + ((ginst) * gwidth) +
109 		raddr + ((rinst) * rwidth);
110 }
111 
112 static inline void sdx5_rmw(u32 val, u32 mask, struct sparx5_serdes_private *priv,
113 			    int id, int tinst, int tcnt,
114 			    int gbase, int ginst, int gcnt, int gwidth,
115 			    int raddr, int rinst, int rcnt, int rwidth)
116 {
117 	u32 nval;
118 	void __iomem *addr =
119 		sdx5_addr(priv->regs, id, tinst, tcnt,
120 			  gbase, ginst, gcnt, gwidth,
121 			  raddr, rinst, rcnt, rwidth);
122 	nval = readl(addr);
123 	nval = (nval & ~mask) | (val & mask);
124 	writel(nval, addr);
125 }
126 
127 static inline void sdx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem,
128 				 int id, int tinst, int tcnt,
129 				 int gbase, int ginst, int gcnt, int gwidth,
130 				 int raddr, int rinst, int rcnt, int rwidth)
131 {
132 	u32 nval;
133 	void __iomem *addr =
134 		sdx5_inst_baseaddr(iomem,
135 				   gbase, ginst, gcnt, gwidth,
136 				   raddr, rinst, rcnt, rwidth);
137 	nval = readl(addr);
138 	nval = (nval & ~mask) | (val & mask);
139 	writel(nval, addr);
140 }
141 
142 static inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr)
143 {
144 	u32 nval;
145 
146 	nval = readl(addr);
147 	nval = (nval & ~mask) | (val & mask);
148 	writel(nval, addr);
149 }
150 
151 static inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv,
152 					  int id, int tinst)
153 {
154 	return priv->regs[id + tinst];
155 }
156 
157 static inline void __iomem *sdx5_inst_addr(void __iomem *iomem,
158 					   int id, int tinst, int tcnt,
159 					   int gbase,
160 					   int ginst, int gcnt, int gwidth,
161 					   int raddr,
162 					   int rinst, int rcnt, int rwidth)
163 {
164 	return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth,
165 				  raddr, rinst, rcnt, rwidth);
166 }
167 
168 
169 #endif /* _SPARX5_SERDES_REGS_H_ */
170