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	unsigned long coreclock;
34};
35
36struct 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 */
50static 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
65static 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
78static 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
93static 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
108static 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
117static 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
123static 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