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