137 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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_ */
 |