162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci * Microchip Sparx5 SerDes driver
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2020 Microchip Technology Inc.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef _SPARX5_SERDES_H_
862306a36Sopenharmony_ci#define _SPARX5_SERDES_H_
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "sparx5_serdes_regs.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define SPX5_SERDES_MAX       33
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cienum sparx5_serdes_type {
1562306a36Sopenharmony_ci	SPX5_SDT_6G  = 6,
1662306a36Sopenharmony_ci	SPX5_SDT_10G = 10,
1762306a36Sopenharmony_ci	SPX5_SDT_25G = 25,
1862306a36Sopenharmony_ci};
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cienum sparx5_serdes_mode {
2162306a36Sopenharmony_ci	SPX5_SD_MODE_NONE,
2262306a36Sopenharmony_ci	SPX5_SD_MODE_2G5,
2362306a36Sopenharmony_ci	SPX5_SD_MODE_QSGMII,
2462306a36Sopenharmony_ci	SPX5_SD_MODE_100FX,
2562306a36Sopenharmony_ci	SPX5_SD_MODE_1000BASEX,
2662306a36Sopenharmony_ci	SPX5_SD_MODE_SFI,
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistruct sparx5_serdes_private {
3062306a36Sopenharmony_ci	struct device *dev;
3162306a36Sopenharmony_ci	void __iomem *regs[NUM_TARGETS];
3262306a36Sopenharmony_ci	struct phy *phys[SPX5_SERDES_MAX];
3362306a36Sopenharmony_ci	unsigned long coreclock;
3462306a36Sopenharmony_ci};
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistruct sparx5_serdes_macro {
3762306a36Sopenharmony_ci	struct sparx5_serdes_private *priv;
3862306a36Sopenharmony_ci	u32 sidx;
3962306a36Sopenharmony_ci	u32 stpidx;
4062306a36Sopenharmony_ci	enum sparx5_serdes_type serdestype;
4162306a36Sopenharmony_ci	enum sparx5_serdes_mode serdesmode;
4262306a36Sopenharmony_ci	phy_interface_t portmode;
4362306a36Sopenharmony_ci	int speed;
4462306a36Sopenharmony_ci	enum phy_media media;
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* Read, Write and modify registers content.
4862306a36Sopenharmony_ci * The register definition macros start at the id
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_cistatic inline void __iomem *sdx5_addr(void __iomem *base[],
5162306a36Sopenharmony_ci				      int id, int tinst, int tcnt,
5262306a36Sopenharmony_ci				      int gbase, int ginst,
5362306a36Sopenharmony_ci				      int gcnt, int gwidth,
5462306a36Sopenharmony_ci				      int raddr, int rinst,
5562306a36Sopenharmony_ci				      int rcnt, int rwidth)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	WARN_ON((tinst) >= tcnt);
5862306a36Sopenharmony_ci	WARN_ON((ginst) >= gcnt);
5962306a36Sopenharmony_ci	WARN_ON((rinst) >= rcnt);
6062306a36Sopenharmony_ci	return base[id + (tinst)] +
6162306a36Sopenharmony_ci		gbase + ((ginst) * gwidth) +
6262306a36Sopenharmony_ci		raddr + ((rinst) * rwidth);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic inline void __iomem *sdx5_inst_baseaddr(void __iomem *base,
6662306a36Sopenharmony_ci					       int gbase, int ginst,
6762306a36Sopenharmony_ci					       int gcnt, int gwidth,
6862306a36Sopenharmony_ci					       int raddr, int rinst,
6962306a36Sopenharmony_ci					       int rcnt, int rwidth)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	WARN_ON((ginst) >= gcnt);
7262306a36Sopenharmony_ci	WARN_ON((rinst) >= rcnt);
7362306a36Sopenharmony_ci	return base +
7462306a36Sopenharmony_ci		gbase + ((ginst) * gwidth) +
7562306a36Sopenharmony_ci		raddr + ((rinst) * rwidth);
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic inline void sdx5_rmw(u32 val, u32 mask, struct sparx5_serdes_private *priv,
7962306a36Sopenharmony_ci			    int id, int tinst, int tcnt,
8062306a36Sopenharmony_ci			    int gbase, int ginst, int gcnt, int gwidth,
8162306a36Sopenharmony_ci			    int raddr, int rinst, int rcnt, int rwidth)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	u32 nval;
8462306a36Sopenharmony_ci	void __iomem *addr =
8562306a36Sopenharmony_ci		sdx5_addr(priv->regs, id, tinst, tcnt,
8662306a36Sopenharmony_ci			  gbase, ginst, gcnt, gwidth,
8762306a36Sopenharmony_ci			  raddr, rinst, rcnt, rwidth);
8862306a36Sopenharmony_ci	nval = readl(addr);
8962306a36Sopenharmony_ci	nval = (nval & ~mask) | (val & mask);
9062306a36Sopenharmony_ci	writel(nval, addr);
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic inline void sdx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem,
9462306a36Sopenharmony_ci				 int id, int tinst, int tcnt,
9562306a36Sopenharmony_ci				 int gbase, int ginst, int gcnt, int gwidth,
9662306a36Sopenharmony_ci				 int raddr, int rinst, int rcnt, int rwidth)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	u32 nval;
9962306a36Sopenharmony_ci	void __iomem *addr =
10062306a36Sopenharmony_ci		sdx5_inst_baseaddr(iomem,
10162306a36Sopenharmony_ci				   gbase, ginst, gcnt, gwidth,
10262306a36Sopenharmony_ci				   raddr, rinst, rcnt, rwidth);
10362306a36Sopenharmony_ci	nval = readl(addr);
10462306a36Sopenharmony_ci	nval = (nval & ~mask) | (val & mask);
10562306a36Sopenharmony_ci	writel(nval, addr);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	u32 nval;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	nval = readl(addr);
11362306a36Sopenharmony_ci	nval = (nval & ~mask) | (val & mask);
11462306a36Sopenharmony_ci	writel(nval, addr);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv,
11862306a36Sopenharmony_ci					  int id, int tinst)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	return priv->regs[id + tinst];
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic inline void __iomem *sdx5_inst_addr(void __iomem *iomem,
12462306a36Sopenharmony_ci					   int id, int tinst, int tcnt,
12562306a36Sopenharmony_ci					   int gbase,
12662306a36Sopenharmony_ci					   int ginst, int gcnt, int gwidth,
12762306a36Sopenharmony_ci					   int raddr,
12862306a36Sopenharmony_ci					   int rinst, int rcnt, int rwidth)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth,
13162306a36Sopenharmony_ci				  raddr, rinst, rcnt, rwidth);
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci#endif /* _SPARX5_SERDES_REGS_H_ */
136