Loading...
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
14enum sparx5_serdes_type {
15 SPX5_SDT_6G = 6,
16 SPX5_SDT_10G = 10,
17 SPX5_SDT_25G = 25,
18};
19
20enum 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
29struct 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
37struct 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 */
51static 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
66static 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
79static 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
94static 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
109static 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
118static 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
124static 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_ */
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
14enum sparx5_serdes_type {
15 SPX5_SDT_6G = 6,
16 SPX5_SDT_10G = 10,
17 SPX5_SDT_25G = 25,
18};
19
20enum 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
29enum 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
37enum sparx5_target {
38 SPX5_TARGET_SPARX5,
39 SPX5_TARGET_LAN969X,
40
41};
42
43struct 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
54struct sparx5_serdes_consts {
55 int sd_max;
56 int cmu_max;
57};
58
59struct 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
64struct 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
73struct 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 */
84static 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
99static 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
112static 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
127static 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
142static 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
151static 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
157static 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_ */