GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / phy / microchip / sparx5_serdes.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
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_ */