aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy/microchip/sparx5_serdes.h
blob: 0a3e496e6210ccbfcdef12d5004ac09b02221c59 (plain) (blame)
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
/* 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,
};

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

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;
};

/* 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_ */