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 | */ |
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 | |
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 | |
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(base: 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(val: nval, addr); |
91 | } |
92 | |
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(base: iomem, |
101 | gbase, ginst, gcnt, gwidth, |
102 | raddr, rinst, rcnt, rwidth); |
103 | nval = readl(addr); |
104 | nval = (nval & ~mask) | (val & mask); |
105 | writel(val: nval, addr); |
106 | } |
107 | |
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(val: nval, addr); |
115 | } |
116 | |
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 | |
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(base: iomem, gbase, ginst, gcnt, gwidth, |
131 | raddr, rinst, rcnt, rwidth); |
132 | } |
133 | |
134 | |
135 | #endif /* _SPARX5_SERDES_REGS_H_ */ |
136 | |