summaryrefslogtreecommitdiffstats
path: root/drivers/phy/microchip/sparx5_serdes.h
blob: 1beaa3d05a5d528653f311f4ed5e4f24a5d1fcfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* SPDX-License-Identifier: GPL-2.0+
 * Microchip Sparx5 SerDes driver
 *
 * Copyright (c) 2020 Microchip Technology Inc.
 */

#ifndef _SPARX5_SERDES_H_
#define _SPARX5_SERDES_H_

#include "sparx5_serdes_regs.h"

#define SPX5_SERDES_MAX       33

enum sparx5_serdes_type {
	SPX5_SDT_6G  = 6,
	SPX5_SDT_10G = 10,
	SPX5_SDT_25G = 25,
};

enum sparx5_serdes_mode {
	SPX5_SD_MODE_NONE,
	SPX5_SD_MODE_2G5,
	SPX5_SD_MODE_QSGMII,
	SPX5_SD_MODE_100FX,
	SPX5_SD_MODE_1000BASEX,
	SPX5_SD_MODE_SFI,
};

enum sparx5_10g28cmu_mode {
	SPX5_SD10G28_CMU_MAIN = 0,
	SPX5_SD10G28_CMU_AUX1 = 1,
	SPX5_SD10G28_CMU_AUX2 = 3,
	SPX5_SD10G28_CMU_NONE = 4,
	SPX5_SD10G28_CMU_MAX,
};

enum sparx5_target {
	SPX5_TARGET_SPARX5,
};

struct sparx5_serdes_macro {
	struct sparx5_serdes_private *priv;
	u32 sidx;
	u32 stpidx;
	enum sparx5_serdes_type serdestype;
	enum sparx5_serdes_mode serdesmode;
	phy_interface_t portmode;
	int speed;
	enum phy_media media;
};

struct sparx5_serdes_consts {
	int sd_max;
	int cmu_max;
};

struct sparx5_serdes_ops {
	void (*serdes_type_set)(struct sparx5_serdes_macro *macro, int sidx);
	int (*serdes_cmu_get)(enum sparx5_10g28cmu_mode mode, int sd_index);
};

struct sparx5_serdes_match_data {
	enum sparx5_target type;
	const struct sparx5_serdes_consts consts;
	const struct sparx5_serdes_ops ops;
	const struct sparx5_serdes_io_resource *iomap;
	int iomap_size;
	const unsigned int *tsize;
};

struct sparx5_serdes_private {
	struct device *dev;
	void __iomem *regs[NUM_TARGETS];
	struct phy *phys[SPX5_SERDES_MAX];
	unsigned long coreclock;
	const struct sparx5_serdes_match_data *data;
};

/* Read, Write and modify registers content.
 * The register definition macros start at the id
 */
static inline void __iomem *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)
{
	WARN_ON((tinst) >= tcnt);
	WARN_ON((ginst) >= gcnt);
	WARN_ON((rinst) >= rcnt);
	return base[id + (tinst)] +
		gbase + ((ginst) * gwidth) +
		raddr + ((rinst) * rwidth);
}

static inline void __iomem *sdx5_inst_baseaddr(void __iomem *base,
					       int gbase, int ginst,
					       int gcnt, int gwidth,
					       int raddr, int rinst,
					       int rcnt, int rwidth)
{
	WARN_ON((ginst) >= gcnt);
	WARN_ON((rinst) >= rcnt);
	return base +
		gbase + ((ginst) * gwidth) +
		raddr + ((rinst) * rwidth);
}

static inline void 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)
{
	u32 nval;
	void __iomem *addr =
		sdx5_addr(priv->regs, id, tinst, tcnt,
			  gbase, ginst, gcnt, gwidth,
			  raddr, rinst, rcnt, rwidth);
	nval = readl(addr);
	nval = (nval & ~mask) | (val & mask);
	writel(nval, addr);
}

static inline void 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)
{
	u32 nval;
	void __iomem *addr =
		sdx5_inst_baseaddr(iomem,
				   gbase, ginst, gcnt, gwidth,
				   raddr, rinst, rcnt, rwidth);
	nval = readl(addr);
	nval = (nval & ~mask) | (val & mask);
	writel(nval, addr);
}

static inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr)
{
	u32 nval;

	nval = readl(addr);
	nval = (nval & ~mask) | (val & mask);
	writel(nval, addr);
}

static inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv,
					  int id, int tinst)
{
	return priv->regs[id + tinst];
}

static inline void __iomem *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)
{
	return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth,
				  raddr, rinst, rcnt, rwidth);
}


#endif /* _SPARX5_SERDES_REGS_H_ */