1 /* SPDX-License-Identifier: GPL-2.0+ 2 * Microchip Sparx5 SerDes driver 3 * 4 * Copyright (c) 2020 Microchip Technology Inc. 5 */ 6 7 #ifndef _SPARX5_SERDES_H_ 8 #define _SPARX5_SERDES_H_ 9 10 #include "sparx5_serdes_regs.h" 11 12 #define SPX5_SERDES_MAX 33 13 14 enum sparx5_serdes_type { 15 SPX5_SDT_6G = 6, 16 SPX5_SDT_10G = 10, 17 SPX5_SDT_25G = 25, 18 }; 19 20 enum sparx5_serdes_mode { 21 SPX5_SD_MODE_NONE, 22 SPX5_SD_MODE_2G5, 23 SPX5_SD_MODE_QSGMII, 24 SPX5_SD_MODE_100FX, 25 SPX5_SD_MODE_1000BASEX, 26 SPX5_SD_MODE_SFI, 27 }; 28 29 struct sparx5_serdes_private { 30 struct device *dev; 31 void __iomem *regs[NUM_TARGETS]; 32 struct phy *phys[SPX5_SERDES_MAX]; 33 unsigned long coreclock; 34 }; 35 36 struct sparx5_serdes_macro { 37 struct sparx5_serdes_private *priv; 38 u32 sidx; 39 u32 stpidx; 40 enum sparx5_serdes_type serdestype; 41 enum sparx5_serdes_mode serdesmode; 42 phy_interface_t portmode; 43 int speed; 44 enum phy_media media; 45 }; 46 47 /* Read, Write and modify registers content. 48 * The register definition macros start at the id 49 */ 50 static inline void __iomem *sdx5_addr(void __iomem *base[], 51 int id, int tinst, int tcnt, 52 int gbase, int ginst, 53 int gcnt, int gwidth, 54 int raddr, int rinst, 55 int rcnt, int rwidth) 56 { 57 WARN_ON((tinst) >= tcnt); 58 WARN_ON((ginst) >= gcnt); 59 WARN_ON((rinst) >= rcnt); 60 return base[id + (tinst)] + 61 gbase + ((ginst) * gwidth) + 62 raddr + ((rinst) * rwidth); 63 } 64 65 static inline void __iomem *sdx5_inst_baseaddr(void __iomem *base, 66 int gbase, int ginst, 67 int gcnt, int gwidth, 68 int raddr, int rinst, 69 int rcnt, int rwidth) 70 { 71 WARN_ON((ginst) >= gcnt); 72 WARN_ON((rinst) >= rcnt); 73 return base + 74 gbase + ((ginst) * gwidth) + 75 raddr + ((rinst) * rwidth); 76 } 77 78 static inline void sdx5_rmw(u32 val, u32 mask, struct sparx5_serdes_private *priv, 79 int id, int tinst, int tcnt, 80 int gbase, int ginst, int gcnt, int gwidth, 81 int raddr, int rinst, int rcnt, int rwidth) 82 { 83 u32 nval; 84 void __iomem *addr = 85 sdx5_addr(priv->regs, id, tinst, tcnt, 86 gbase, ginst, gcnt, gwidth, 87 raddr, rinst, rcnt, rwidth); 88 nval = readl(addr); 89 nval = (nval & ~mask) | (val & mask); 90 writel(nval, addr); 91 } 92 93 static inline void sdx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem, 94 int id, int tinst, int tcnt, 95 int gbase, int ginst, int gcnt, int gwidth, 96 int raddr, int rinst, int rcnt, int rwidth) 97 { 98 u32 nval; 99 void __iomem *addr = 100 sdx5_inst_baseaddr(iomem, 101 gbase, ginst, gcnt, gwidth, 102 raddr, rinst, rcnt, rwidth); 103 nval = readl(addr); 104 nval = (nval & ~mask) | (val & mask); 105 writel(nval, addr); 106 } 107 108 static inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr) 109 { 110 u32 nval; 111 112 nval = readl(addr); 113 nval = (nval & ~mask) | (val & mask); 114 writel(nval, addr); 115 } 116 117 static inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv, 118 int id, int tinst) 119 { 120 return priv->regs[id + tinst]; 121 } 122 123 static inline void __iomem *sdx5_inst_addr(void __iomem *iomem, 124 int id, int tinst, int tcnt, 125 int gbase, 126 int ginst, int gcnt, int gwidth, 127 int raddr, 128 int rinst, int rcnt, int rwidth) 129 { 130 return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth, 131 raddr, rinst, rcnt, rwidth); 132 } 133 134 135 #endif /* _SPARX5_SERDES_REGS_H_ */ 136