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