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 enum sparx5_10g28cmu_mode { 30 SPX5_SD10G28_CMU_MAIN = 0, 31 SPX5_SD10G28_CMU_AUX1 = 1, 32 SPX5_SD10G28_CMU_AUX2 = 3, 33 SPX5_SD10G28_CMU_NONE = 4, 34 SPX5_SD10G28_CMU_MAX, 35 }; 36 37 enum sparx5_target { 38 SPX5_TARGET_SPARX5, 39 SPX5_TARGET_LAN969X, 40 41 }; 42 43 struct sparx5_serdes_macro { 44 struct sparx5_serdes_private *priv; 45 u32 sidx; 46 u32 stpidx; 47 enum sparx5_serdes_type serdestype; 48 enum sparx5_serdes_mode serdesmode; 49 phy_interface_t portmode; 50 int speed; 51 enum phy_media media; 52 }; 53 54 struct sparx5_serdes_consts { 55 int sd_max; 56 int cmu_max; 57 }; 58 59 struct sparx5_serdes_ops { 60 void (*serdes_type_set)(struct sparx5_serdes_macro *macro, int sidx); 61 int (*serdes_cmu_get)(enum sparx5_10g28cmu_mode mode, int sd_index); 62 }; 63 64 struct sparx5_serdes_match_data { 65 enum sparx5_target type; 66 const struct sparx5_serdes_consts consts; 67 const struct sparx5_serdes_ops ops; 68 const struct sparx5_serdes_io_resource *iomap; 69 int iomap_size; 70 const unsigned int *tsize; 71 }; 72 73 struct sparx5_serdes_private { 74 struct device *dev; 75 void __iomem *regs[NUM_TARGETS]; 76 struct phy *phys[SPX5_SERDES_MAX]; 77 unsigned long coreclock; 78 const struct sparx5_serdes_match_data *data; 79 }; 80 81 /* Read, Write and modify registers content. 82 * The register definition macros start at the id 83 */ 84 static inline void __iomem *sdx5_addr(void __iomem *base[], 85 int id, int tinst, int tcnt, 86 int gbase, int ginst, 87 int gcnt, int gwidth, 88 int raddr, int rinst, 89 int rcnt, int rwidth) 90 { 91 WARN_ON((tinst) >= tcnt); 92 WARN_ON((ginst) >= gcnt); 93 WARN_ON((rinst) >= rcnt); 94 return base[id + (tinst)] + 95 gbase + ((ginst) * gwidth) + 96 raddr + ((rinst) * rwidth); 97 } 98 99 static inline void __iomem *sdx5_inst_baseaddr(void __iomem *base, 100 int gbase, int ginst, 101 int gcnt, int gwidth, 102 int raddr, int rinst, 103 int rcnt, int rwidth) 104 { 105 WARN_ON((ginst) >= gcnt); 106 WARN_ON((rinst) >= rcnt); 107 return base + 108 gbase + ((ginst) * gwidth) + 109 raddr + ((rinst) * rwidth); 110 } 111 112 static inline void sdx5_rmw(u32 val, u32 mask, struct sparx5_serdes_private *priv, 113 int id, int tinst, int tcnt, 114 int gbase, int ginst, int gcnt, int gwidth, 115 int raddr, int rinst, int rcnt, int rwidth) 116 { 117 u32 nval; 118 void __iomem *addr = 119 sdx5_addr(priv->regs, id, tinst, tcnt, 120 gbase, ginst, gcnt, gwidth, 121 raddr, rinst, rcnt, rwidth); 122 nval = readl(addr); 123 nval = (nval & ~mask) | (val & mask); 124 writel(nval, addr); 125 } 126 127 static inline void sdx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem, 128 int id, int tinst, int tcnt, 129 int gbase, int ginst, int gcnt, int gwidth, 130 int raddr, int rinst, int rcnt, int rwidth) 131 { 132 u32 nval; 133 void __iomem *addr = 134 sdx5_inst_baseaddr(iomem, 135 gbase, ginst, gcnt, gwidth, 136 raddr, rinst, rcnt, rwidth); 137 nval = readl(addr); 138 nval = (nval & ~mask) | (val & mask); 139 writel(nval, addr); 140 } 141 142 static inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr) 143 { 144 u32 nval; 145 146 nval = readl(addr); 147 nval = (nval & ~mask) | (val & mask); 148 writel(nval, addr); 149 } 150 151 static inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv, 152 int id, int tinst) 153 { 154 return priv->regs[id + tinst]; 155 } 156 157 static inline void __iomem *sdx5_inst_addr(void __iomem *iomem, 158 int id, int tinst, int tcnt, 159 int gbase, 160 int ginst, int gcnt, int gwidth, 161 int raddr, 162 int rinst, int rcnt, int rwidth) 163 { 164 return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth, 165 raddr, rinst, rcnt, rwidth); 166 } 167 168 169 #endif /* _SPARX5_SERDES_REGS_H_ */ 170