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 bool cmu_enabled; 34 unsigned long coreclock; 35 }; 36 37 struct sparx5_serdes_macro { 38 struct sparx5_serdes_private *priv; 39 u32 sidx; 40 u32 stpidx; 41 enum sparx5_serdes_type serdestype; 42 enum sparx5_serdes_mode serdesmode; 43 phy_interface_t portmode; 44 int speed; 45 enum phy_media media; 46 }; 47 48 /* Read, Write and modify registers content. 49 * The register definition macros start at the id 50 */ 51 static inline void __iomem *sdx5_addr(void __iomem *base[], 52 int id, int tinst, int tcnt, 53 int gbase, int ginst, 54 int gcnt, int gwidth, 55 int raddr, int rinst, 56 int rcnt, int rwidth) 57 { 58 WARN_ON((tinst) >= tcnt); 59 WARN_ON((ginst) >= gcnt); 60 WARN_ON((rinst) >= rcnt); 61 return base[id + (tinst)] + 62 gbase + ((ginst) * gwidth) + 63 raddr + ((rinst) * rwidth); 64 } 65 66 static inline void __iomem *sdx5_inst_baseaddr(void __iomem *base, 67 int gbase, int ginst, 68 int gcnt, int gwidth, 69 int raddr, int rinst, 70 int rcnt, int rwidth) 71 { 72 WARN_ON((ginst) >= gcnt); 73 WARN_ON((rinst) >= rcnt); 74 return base + 75 gbase + ((ginst) * gwidth) + 76 raddr + ((rinst) * rwidth); 77 } 78 79 static inline void sdx5_rmw(u32 val, u32 mask, struct sparx5_serdes_private *priv, 80 int id, int tinst, int tcnt, 81 int gbase, int ginst, int gcnt, int gwidth, 82 int raddr, int rinst, int rcnt, int rwidth) 83 { 84 u32 nval; 85 void __iomem *addr = 86 sdx5_addr(priv->regs, id, tinst, tcnt, 87 gbase, ginst, gcnt, gwidth, 88 raddr, rinst, rcnt, rwidth); 89 nval = readl(addr); 90 nval = (nval & ~mask) | (val & mask); 91 writel(nval, addr); 92 } 93 94 static inline void sdx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem, 95 int id, int tinst, int tcnt, 96 int gbase, int ginst, int gcnt, int gwidth, 97 int raddr, int rinst, int rcnt, int rwidth) 98 { 99 u32 nval; 100 void __iomem *addr = 101 sdx5_inst_baseaddr(iomem, 102 gbase, ginst, gcnt, gwidth, 103 raddr, rinst, rcnt, rwidth); 104 nval = readl(addr); 105 nval = (nval & ~mask) | (val & mask); 106 writel(nval, addr); 107 } 108 109 static inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr) 110 { 111 u32 nval; 112 113 nval = readl(addr); 114 nval = (nval & ~mask) | (val & mask); 115 writel(nval, addr); 116 } 117 118 static inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv, 119 int id, int tinst) 120 { 121 return priv->regs[id + tinst]; 122 } 123 124 static inline void __iomem *sdx5_inst_addr(void __iomem *iomem, 125 int id, int tinst, int tcnt, 126 int gbase, 127 int ginst, int gcnt, int gwidth, 128 int raddr, 129 int rinst, int rcnt, int rwidth) 130 { 131 return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth, 132 raddr, rinst, rcnt, rwidth); 133 } 134 135 136 #endif /* _SPARX5_SERDES_REGS_H_ */ 137