Commit 7d55751a079464c804a174076d816af157f8376b
Committed by
Sekhar Nori
1 parent
42ac1a0330
Exists in
smarct4x-processor-sdk-linux-02.00.01
and in
3 other branches
phy: keystone: rename data structures based on vendor recommendation
The IP is owned by 3rd party and this patch makes updates to the code to change constants and data structures per vendor recommendation. Signed-off-by: Murali Karicheri <m-karicheri2@ti.com> Signed-off-by: WingMan Kwok <w-kwok2@ti.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Showing 1 changed file with 17 additions and 17 deletions Inline Diff
drivers/phy/phy-keystone-serdes.c
1 | /* | 1 | /* |
2 | * Texas Instruments Keystone SerDes driver | 2 | * Texas Instruments Keystone SerDes driver |
3 | * Authors: WingMan Kwok <w-kwok2@ti.com> | 3 | * Authors: WingMan Kwok <w-kwok2@ti.com> |
4 | * | 4 | * |
5 | * This is the SerDes Phy driver for Keystone devices. This is | 5 | * This is the SerDes Phy driver for Keystone devices. This is |
6 | * required to support PCIe RC functionality based on designware | 6 | * required to support PCIe RC functionality based on designware |
7 | * PCIe hardware, gbe and 10gbe found on these devices. | 7 | * PCIe hardware, gbe and 10gbe found on these devices. |
8 | * | 8 | * |
9 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | 9 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License as | 12 | * modify it under the terms of the GNU General Public License as |
13 | * published by the Free Software Foundation version 2. | 13 | * published by the Free Software Foundation version 2. |
14 | * | 14 | * |
15 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | 15 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any |
16 | * kind, whether express or implied; without even the implied warranty | 16 | * kind, whether express or implied; without even the implied warranty |
17 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
19 | * | 19 | * |
20 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ | 20 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ |
21 | * | 21 | * |
22 | * Redistribution and use in source and binary forms, with or without | 22 | * Redistribution and use in source and binary forms, with or without |
23 | * modification, are permitted provided that the following conditions | 23 | * modification, are permitted provided that the following conditions |
24 | * are met: | 24 | * are met: |
25 | * | 25 | * |
26 | * Redistributions of source code must retain the above copyright | 26 | * Redistributions of source code must retain the above copyright |
27 | * notice, this list of conditions and the following disclaimer. | 27 | * notice, this list of conditions and the following disclaimer. |
28 | * | 28 | * |
29 | * Redistributions in binary form must reproduce the above copyright | 29 | * Redistributions in binary form must reproduce the above copyright |
30 | * notice, this list of conditions and the following disclaimer in the | 30 | * notice, this list of conditions and the following disclaimer in the |
31 | * documentation and/or other materials provided with the | 31 | * documentation and/or other materials provided with the |
32 | * distribution. | 32 | * distribution. |
33 | * | 33 | * |
34 | * Neither the name of Texas Instruments Incorporated nor the names of | 34 | * Neither the name of Texas Instruments Incorporated nor the names of |
35 | * its contributors may be used to endorse or promote products derived | 35 | * its contributors may be used to endorse or promote products derived |
36 | * from this software without specific prior written permission. | 36 | * from this software without specific prior written permission. |
37 | * | 37 | * |
38 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 38 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
39 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 39 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
40 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 40 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
41 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 41 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
42 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 42 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
43 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 43 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
44 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 44 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
45 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 45 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
46 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 46 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
47 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 47 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
48 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 48 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
49 | */ | 49 | */ |
50 | #include <linux/module.h> | 50 | #include <linux/module.h> |
51 | #include <linux/io.h> | 51 | #include <linux/io.h> |
52 | #include <linux/mfd/syscon.h> | 52 | #include <linux/mfd/syscon.h> |
53 | #include <linux/delay.h> | 53 | #include <linux/delay.h> |
54 | #include <linux/firmware.h> | 54 | #include <linux/firmware.h> |
55 | #include <linux/of.h> | 55 | #include <linux/of.h> |
56 | #include <linux/of_address.h> | 56 | #include <linux/of_address.h> |
57 | #include <linux/of_platform.h> | 57 | #include <linux/of_platform.h> |
58 | #include <linux/regmap.h> | 58 | #include <linux/regmap.h> |
59 | #include <linux/sizes.h> | 59 | #include <linux/sizes.h> |
60 | #include <linux/phy/phy.h> | 60 | #include <linux/phy/phy.h> |
61 | #include <linux/platform_device.h> | 61 | #include <linux/platform_device.h> |
62 | 62 | ||
63 | /* | 63 | /* |
64 | * Keystone2 SERDES registers | 64 | * Keystone2 SERDES registers |
65 | */ | 65 | */ |
66 | #define KSERDES_SS_OFFSET 0x1fc0 | 66 | #define KSERDES_SS_OFFSET 0x1fc0 |
67 | #define MOD_VER_REG (KSERDES_SS_OFFSET + 0x00) | 67 | #define MOD_VER_REG (KSERDES_SS_OFFSET + 0x00) |
68 | #define MEM_ADR_REG (KSERDES_SS_OFFSET + 0x04) | 68 | #define MEM_ADR_REG (KSERDES_SS_OFFSET + 0x04) |
69 | #define MEM_DAT_REG (KSERDES_SS_OFFSET + 0x08) | 69 | #define MEM_DAT_REG (KSERDES_SS_OFFSET + 0x08) |
70 | #define MEM_DATINC_REG (KSERDES_SS_OFFSET + 0x0c) | 70 | #define MEM_DATINC_REG (KSERDES_SS_OFFSET + 0x0c) |
71 | #define CPU_CTRL_REG (KSERDES_SS_OFFSET + 0x10) | 71 | #define CPU_CTRL_REG (KSERDES_SS_OFFSET + 0x10) |
72 | #define LANE_CTRL_STS_REG(x) (KSERDES_SS_OFFSET + 0x20 + (x * 0x04)) | 72 | #define LANE_CTRL_STS_REG(x) (KSERDES_SS_OFFSET + 0x20 + (x * 0x04)) |
73 | #define LINK_LOSS_WAIT_REG (KSERDES_SS_OFFSET + 0x30) | 73 | #define LINK_LOSS_WAIT_REG (KSERDES_SS_OFFSET + 0x30) |
74 | #define PLL_CTRL_REG (KSERDES_SS_OFFSET + 0x34) | 74 | #define PLL_CTRL_REG (KSERDES_SS_OFFSET + 0x34) |
75 | 75 | ||
76 | #define CMU0_SS_OFFSET 0x0000 | 76 | #define CMU0_SS_OFFSET 0x0000 |
77 | #define CMU0_REG(x) (CMU0_SS_OFFSET + x) | 77 | #define CMU0_REG(x) (CMU0_SS_OFFSET + x) |
78 | 78 | ||
79 | #define LANE0_SS_OFFSET 0x0200 | 79 | #define LANE0_SS_OFFSET 0x0200 |
80 | #define LANEX_SS_OFFSET(x) (LANE0_SS_OFFSET * (x + 1)) | 80 | #define LANEX_SS_OFFSET(x) (LANE0_SS_OFFSET * (x + 1)) |
81 | #define LANEX_REG(x, y) (LANEX_SS_OFFSET(x) + y) | 81 | #define LANEX_REG(x, y) (LANEX_SS_OFFSET(x) + y) |
82 | 82 | ||
83 | #define CML_SS_OFFSET 0x0a00 | 83 | #define CML_SS_OFFSET 0x0a00 |
84 | #define CML_REG(x) (CML_SS_OFFSET + x) | 84 | #define CML_REG(x) (CML_SS_OFFSET + x) |
85 | 85 | ||
86 | #define CMU1_SS_OFFSET 0x0c00 | 86 | #define CMU1_SS_OFFSET 0x0c00 |
87 | #define CMU1_REG(x) (CMU1_SS_OFFSET + x) | 87 | #define CMU1_REG(x) (CMU1_SS_OFFSET + x) |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * XGE PCS-R registers | 90 | * XGE PCS-R registers |
91 | */ | 91 | */ |
92 | #define PCSR_OFFSET(x) (x * 0x80) | 92 | #define PCSR_OFFSET(x) (x * 0x80) |
93 | 93 | ||
94 | #define PCSR_TX_CTL(x) (PCSR_OFFSET(x) + 0x00) | 94 | #define PCSR_TX_CTL(x) (PCSR_OFFSET(x) + 0x00) |
95 | #define PCSR_TX_STATUS(x) (PCSR_OFFSET(x) + 0x04) | 95 | #define PCSR_TX_STATUS(x) (PCSR_OFFSET(x) + 0x04) |
96 | #define PCSR_RX_CTL(x) (PCSR_OFFSET(x) + 0x08) | 96 | #define PCSR_RX_CTL(x) (PCSR_OFFSET(x) + 0x08) |
97 | #define PCSR_RX_STATUS(x) (PCSR_OFFSET(x) + 0x0C) | 97 | #define PCSR_RX_STATUS(x) (PCSR_OFFSET(x) + 0x0C) |
98 | 98 | ||
99 | #define XGE_CTRL_OFFSET 0x0c | 99 | #define XGE_CTRL_OFFSET 0x0c |
100 | #define PCIE_PL_GEN2_OFFSET 0x180c | 100 | #define PCIE_PL_GEN2_OFFSET 0x180c |
101 | 101 | ||
102 | #define reg_rmw(addr, value, mask) \ | 102 | #define reg_rmw(addr, value, mask) \ |
103 | writel(((readl(addr) & (~(mask))) | (value & (mask))), (addr)) | 103 | writel(((readl(addr) & (~(mask))) | (value & (mask))), (addr)) |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * Replaces bit field [msb:lsb] in register located | 106 | * Replaces bit field [msb:lsb] in register located |
107 | * at (base + offset) by val | 107 | * at (base + offset) by val |
108 | */ | 108 | */ |
109 | #define FINSR(base, offset, msb, lsb, val) \ | 109 | #define FINSR(base, offset, msb, lsb, val) \ |
110 | reg_rmw((base) + (offset), ((val) << (lsb)), GENMASK((msb), (lsb))) | 110 | reg_rmw((base) + (offset), ((val) << (lsb)), GENMASK((msb), (lsb))) |
111 | 111 | ||
112 | /* | 112 | /* |
113 | * This version of FEXTR is NOT safe for msb = 31, lsb = 0 | 113 | * This version of FEXTR is NOT safe for msb = 31, lsb = 0 |
114 | * but then why would we need FEXTR for that case. | 114 | * but then why would we need FEXTR for that case. |
115 | */ | 115 | */ |
116 | #define FEXTR(val, msb, lsb) \ | 116 | #define FEXTR(val, msb, lsb) \ |
117 | (((val) >> (lsb)) & ((1 << ((msb) - (lsb) + 1)) - 1)) | 117 | (((val) >> (lsb)) & ((1 << ((msb) - (lsb) + 1)) - 1)) |
118 | 118 | ||
119 | #define MOD_VER(serdes) \ | 119 | #define MOD_VER(serdes) \ |
120 | ((kserdes_readl(serdes, MOD_VER_REG) >> 16) & 0xffff) | 120 | ((kserdes_readl(serdes, MOD_VER_REG) >> 16) & 0xffff) |
121 | 121 | ||
122 | #define PHY_A(serdes) (MOD_VER(serdes) != 0x4eba) | 122 | #define PHY_A(serdes) (MOD_VER(serdes) != 0x4eba) |
123 | 123 | ||
124 | #define FOUR_LANE(serdes) \ | 124 | #define FOUR_LANE(serdes) \ |
125 | ((MOD_VER(serdes) == 0x4eb9) || (MOD_VER(serdes) == 0x4ebd)) | 125 | ((MOD_VER(serdes) == 0x4eb9) || (MOD_VER(serdes) == 0x4ebd)) |
126 | 126 | ||
127 | #define MAX_COMPARATORS 5 | 127 | #define MAX_COMPARATORS 5 |
128 | #define DFE_OFFSET_SAMPLES 100 | 128 | #define OFFSET_SAMPLES 100 |
129 | 129 | ||
130 | /* yes comparator starts from 1 */ | 130 | /* yes comparator starts from 1 */ |
131 | #define for_each_comparator(i) \ | 131 | #define for_each_comparator(i) \ |
132 | for (i = 1; i < MAX_COMPARATORS; i++) | 132 | for (i = 1; i < MAX_COMPARATORS; i++) |
133 | 133 | ||
134 | /* CPU CTRL bits */ | 134 | /* CPU CTRL bits */ |
135 | #define CPU_EN BIT(31) | 135 | #define CPU_EN BIT(31) |
136 | #define CPU_GO BIT(30) | 136 | #define CPU_GO BIT(30) |
137 | #define POR_EN BIT(29) | 137 | #define POR_EN BIT(29) |
138 | #define CPUREG_EN BIT(28) | 138 | #define CPUREG_EN BIT(28) |
139 | #define AUTONEG_CTL BIT(27) | 139 | #define AUTONEG_CTL BIT(27) |
140 | #define DATASPLIT BIT(26) | 140 | #define DATASPLIT BIT(26) |
141 | #define LNKTRN_SIG_DET BIT(8) | 141 | #define LNKTRN_SIG_DET BIT(8) |
142 | 142 | ||
143 | #define PLL_ENABLE_1P25G 0xe0000000 | 143 | #define PLL_ENABLE_1P25G 0xe0000000 |
144 | #define LANE_CTRL_1P25G 0xf800f8c0 | 144 | #define LANE_CTRL_1P25G 0xf800f8c0 |
145 | #define XFM_FLUSH_CMD 0x00009c9c | 145 | #define XFM_FLUSH_CMD 0x00009c9c |
146 | 146 | ||
147 | #define ANEG_LINK_CTL_10GKR_MASK GENMASK(21, 20) | 147 | #define ANEG_LINK_CTL_10GKR_MASK GENMASK(21, 20) |
148 | #define ANEG_LINK_CTL_1GKX_MASK GENMASK(17, 16) | 148 | #define ANEG_LINK_CTL_1GKX_MASK GENMASK(17, 16) |
149 | #define ANEG_LINK_CTL_1G10G_MASK \ | 149 | #define ANEG_LINK_CTL_1G10G_MASK \ |
150 | (ANEG_LINK_CTL_10GKR_MASK | ANEG_LINK_CTL_1GKX_MASK) | 150 | (ANEG_LINK_CTL_10GKR_MASK | ANEG_LINK_CTL_1GKX_MASK) |
151 | 151 | ||
152 | #define ANEG_1G_10G_OPT_MASK GENMASK(7, 5) | 152 | #define ANEG_1G_10G_OPT_MASK GENMASK(7, 5) |
153 | 153 | ||
154 | #define SERDES_REG_INDEX 0 | 154 | #define SERDES_REG_INDEX 0 |
155 | 155 | ||
156 | /* SERDES internal memory */ | 156 | /* SERDES internal memory */ |
157 | #define KSERDES_XFW_MEM_SIZE SZ_64K | 157 | #define KSERDES_XFW_MEM_SIZE SZ_64K |
158 | #define KSERDES_XFW_CONFIG_MEM_SIZE SZ_64 | 158 | #define KSERDES_XFW_CONFIG_MEM_SIZE SZ_64 |
159 | #define KSERDES_XFW_NUM_PARAMS 5 | 159 | #define KSERDES_XFW_NUM_PARAMS 5 |
160 | 160 | ||
161 | /* Last 64B of the 64KB internal mem is for parameters */ | 161 | /* Last 64B of the 64KB internal mem is for parameters */ |
162 | #define KSERDES_XFW_CONFIG_START_ADDR \ | 162 | #define KSERDES_XFW_CONFIG_START_ADDR \ |
163 | (KSERDES_XFW_MEM_SIZE - KSERDES_XFW_CONFIG_MEM_SIZE) | 163 | (KSERDES_XFW_MEM_SIZE - KSERDES_XFW_CONFIG_MEM_SIZE) |
164 | 164 | ||
165 | #define KSERDES_XFW_PARAM_START_ADDR \ | 165 | #define KSERDES_XFW_PARAM_START_ADDR \ |
166 | (KSERDES_XFW_MEM_SIZE - (KSERDES_XFW_NUM_PARAMS * 4)) | 166 | (KSERDES_XFW_MEM_SIZE - (KSERDES_XFW_NUM_PARAMS * 4)) |
167 | 167 | ||
168 | /* | 168 | /* |
169 | * All firmware file names end up here. List the firmware file names below. | 169 | * All firmware file names end up here. List the firmware file names below. |
170 | * Newest first. Search starts from the 0-th array entry until a firmware | 170 | * Newest first. Search starts from the 0-th array entry until a firmware |
171 | * file is found. | 171 | * file is found. |
172 | */ | 172 | */ |
173 | static const char * const ks2_gbe_serdes_firmwares[] = {"ks2_gbe_serdes.bin"}; | 173 | static const char * const ks2_gbe_serdes_firmwares[] = {"ks2_gbe_serdes.bin"}; |
174 | static const char * const ks2_xgbe_serdes_firmwares[] = {"ks2_xgbe_serdes.bin"}; | 174 | static const char * const ks2_xgbe_serdes_firmwares[] = {"ks2_xgbe_serdes.bin"}; |
175 | static const char * const ks2_pcie_serdes_firmwares[] = {"ks2_pcie_serdes.bin"}; | 175 | static const char * const ks2_pcie_serdes_firmwares[] = {"ks2_pcie_serdes.bin"}; |
176 | 176 | ||
177 | /* SERDES Link Rate Kbps */ | 177 | /* SERDES Link Rate Kbps */ |
178 | enum kserdes_link_rate { | 178 | enum kserdes_link_rate { |
179 | KSERDES_LINK_RATE_1P25G = 1250000, | 179 | KSERDES_LINK_RATE_1P25G = 1250000, |
180 | KSERDES_LINK_RATE_3P125G = 3125000, | 180 | KSERDES_LINK_RATE_3P125G = 3125000, |
181 | KSERDES_LINK_RATE_4P9152G = 4915200, | 181 | KSERDES_LINK_RATE_4P9152G = 4915200, |
182 | KSERDES_LINK_RATE_5G = 5000000, | 182 | KSERDES_LINK_RATE_5G = 5000000, |
183 | KSERDES_LINK_RATE_6P144G = 6144000, | 183 | KSERDES_LINK_RATE_6P144G = 6144000, |
184 | KSERDES_LINK_RATE_6P25G = 6250000, | 184 | KSERDES_LINK_RATE_6P25G = 6250000, |
185 | KSERDES_LINK_RATE_7P3728G = 7372800, | 185 | KSERDES_LINK_RATE_7P3728G = 7372800, |
186 | KSERDES_LINK_RATE_9P8304G = 9830400, | 186 | KSERDES_LINK_RATE_9P8304G = 9830400, |
187 | KSERDES_LINK_RATE_10G = 10000000, | 187 | KSERDES_LINK_RATE_10G = 10000000, |
188 | KSERDES_LINK_RATE_10P3125G = 10312500, | 188 | KSERDES_LINK_RATE_10P3125G = 10312500, |
189 | KSERDES_LINK_RATE_12P5G = 12500000, | 189 | KSERDES_LINK_RATE_12P5G = 12500000, |
190 | }; | 190 | }; |
191 | 191 | ||
192 | /* SERDES Lane Control Rate */ | 192 | /* SERDES Lane Control Rate */ |
193 | enum kserdes_lane_ctrl_rate { | 193 | enum kserdes_lane_ctrl_rate { |
194 | KSERDES_FULL_RATE, | 194 | KSERDES_FULL_RATE, |
195 | KSERDES_HALF_RATE, | 195 | KSERDES_HALF_RATE, |
196 | KSERDES_QUARTER_RATE, | 196 | KSERDES_QUARTER_RATE, |
197 | }; | 197 | }; |
198 | 198 | ||
199 | enum kserdes_phy_type { | 199 | enum kserdes_phy_type { |
200 | KSERDES_PHY_SGMII, | 200 | KSERDES_PHY_SGMII, |
201 | KSERDES_PHY_XGE, | 201 | KSERDES_PHY_XGE, |
202 | KSERDES_PHY_PCIE, | 202 | KSERDES_PHY_PCIE, |
203 | KSERDES_PHY_HYPERLINK, | 203 | KSERDES_PHY_HYPERLINK, |
204 | }; | 204 | }; |
205 | 205 | ||
206 | struct kserdes_tx_coeff { | 206 | struct kserdes_tx_coeff { |
207 | u32 c1; | 207 | u32 c1; |
208 | u32 c2; | 208 | u32 c2; |
209 | u32 cm; | 209 | u32 cm; |
210 | u32 att; | 210 | u32 att; |
211 | u32 vreg; | 211 | u32 vreg; |
212 | }; | 212 | }; |
213 | 213 | ||
214 | struct kserdes_equalizer { | 214 | struct kserdes_equalizer { |
215 | u32 att; | 215 | u32 att; |
216 | u32 boost; | 216 | u32 boost; |
217 | }; | 217 | }; |
218 | 218 | ||
219 | struct kserdes_lane_config { | 219 | struct kserdes_lane_config { |
220 | bool enable; | 220 | bool enable; |
221 | u32 ctrl_rate; | 221 | u32 ctrl_rate; |
222 | struct kserdes_tx_coeff tx_coeff; | 222 | struct kserdes_tx_coeff tx_coeff; |
223 | struct kserdes_equalizer rx_start; | 223 | struct kserdes_equalizer rx_start; |
224 | struct kserdes_equalizer rx_force; | 224 | struct kserdes_equalizer rx_force; |
225 | bool loopback; | 225 | bool loopback; |
226 | }; | 226 | }; |
227 | 227 | ||
228 | #define KSERDES_MAX_LANES 4 | 228 | #define KSERDES_MAX_LANES 4 |
229 | 229 | ||
230 | struct kserdes_fw_config { | 230 | struct kserdes_fw_config { |
231 | bool on; | 231 | bool on; |
232 | u32 rate; | 232 | u32 rate; |
233 | u32 link_loss_wait; | 233 | u32 link_loss_wait; |
234 | u32 lane_seeds; | 234 | u32 lane_seeds; |
235 | u32 fast_train; | 235 | u32 fast_train; |
236 | u32 active_lane; | 236 | u32 active_lane; |
237 | u32 c1, c2, cm, attn, boost, dlpf, cdrcal; | 237 | u32 c1, c2, cm, attn, boost, dlpf, rxcal; |
238 | u32 lane_config[KSERDES_MAX_LANES]; | 238 | u32 lane_config[KSERDES_MAX_LANES]; |
239 | }; | 239 | }; |
240 | 240 | ||
241 | struct kserdes_config { | 241 | struct kserdes_config { |
242 | struct device *dev; | 242 | struct device *dev; |
243 | enum kserdes_phy_type phy_type; | 243 | enum kserdes_phy_type phy_type; |
244 | u32 lanes; | 244 | u32 lanes; |
245 | void __iomem *regs; | 245 | void __iomem *regs; |
246 | struct regmap *peripheral_regmap; | 246 | struct regmap *peripheral_regmap; |
247 | struct regmap *pcsr_regmap; | 247 | struct regmap *pcsr_regmap; |
248 | /* non-fw specific */ | 248 | /* non-fw specific */ |
249 | const char *init_fw; | 249 | const char *init_fw; |
250 | struct serdes_cfg *init_cfg; | 250 | struct serdes_cfg *init_cfg; |
251 | int init_cfg_len; | 251 | int init_cfg_len; |
252 | enum kserdes_link_rate link_rate; | 252 | enum kserdes_link_rate link_rate; |
253 | bool rx_force_enable; | 253 | bool rx_force_enable; |
254 | struct kserdes_lane_config lane[KSERDES_MAX_LANES]; | 254 | struct kserdes_lane_config lane[KSERDES_MAX_LANES]; |
255 | /* fw specific */ | 255 | /* fw specific */ |
256 | bool firmware; | 256 | bool firmware; |
257 | struct kserdes_fw_config fw; | 257 | struct kserdes_fw_config fw; |
258 | }; | 258 | }; |
259 | 259 | ||
260 | struct kserdes_dev { | 260 | struct kserdes_dev { |
261 | struct device *dev; | 261 | struct device *dev; |
262 | struct phy *phy; | 262 | struct phy *phy; |
263 | struct kserdes_config sc; | 263 | struct kserdes_config sc; |
264 | }; | 264 | }; |
265 | 265 | ||
266 | struct kserdes_comparator_tap_ofs { | 266 | struct kserdes_cmp_tap_ofs { |
267 | u32 cmp; | 267 | u32 cmp; |
268 | u32 tap1; | 268 | u32 tap1; |
269 | u32 tap2; | 269 | u32 tap2; |
270 | u32 tap3; | 270 | u32 tap3; |
271 | u32 tap4; | 271 | u32 tap4; |
272 | u32 tap5; | 272 | u32 tap5; |
273 | }; | 273 | }; |
274 | 274 | ||
275 | struct kserdes_lane_offsets { | 275 | struct kserdes_lane_offsets { |
276 | struct kserdes_comparator_tap_ofs ct_ofs[MAX_COMPARATORS]; | 276 | struct kserdes_cmp_tap_ofs ct_ofs[MAX_COMPARATORS]; |
277 | }; | 277 | }; |
278 | 278 | ||
279 | struct kserdes_offsets { | 279 | struct kserdes_offsets { |
280 | struct kserdes_lane_offsets lane_ofs[KSERDES_MAX_LANES]; | 280 | struct kserdes_lane_offsets lane_ofs[KSERDES_MAX_LANES]; |
281 | }; | 281 | }; |
282 | 282 | ||
283 | struct serdes_cfg { | 283 | struct serdes_cfg { |
284 | u32 ofs; | 284 | u32 ofs; |
285 | u32 msb; | 285 | u32 msb; |
286 | u32 lsb; | 286 | u32 lsb; |
287 | u32 val; | 287 | u32 val; |
288 | }; | 288 | }; |
289 | 289 | ||
290 | static struct platform_device_id kserdes_devtype[] = { | 290 | static struct platform_device_id kserdes_devtype[] = { |
291 | { | 291 | { |
292 | .name = "kserdes-gbe", | 292 | .name = "kserdes-gbe", |
293 | .driver_data = KSERDES_PHY_SGMII, | 293 | .driver_data = KSERDES_PHY_SGMII, |
294 | }, { | 294 | }, { |
295 | .name = "kserdes-xgbe", | 295 | .name = "kserdes-xgbe", |
296 | .driver_data = KSERDES_PHY_XGE, | 296 | .driver_data = KSERDES_PHY_XGE, |
297 | }, { | 297 | }, { |
298 | .name = "kserdes-pcie", | 298 | .name = "kserdes-pcie", |
299 | .driver_data = KSERDES_PHY_PCIE, | 299 | .driver_data = KSERDES_PHY_PCIE, |
300 | } | 300 | } |
301 | }; | 301 | }; |
302 | 302 | ||
303 | static inline int next_enable_lane(struct kserdes_config *sc, int i) | 303 | static inline int next_enable_lane(struct kserdes_config *sc, int i) |
304 | { | 304 | { |
305 | int j = i; | 305 | int j = i; |
306 | 306 | ||
307 | while (++j < sc->lanes) { | 307 | while (++j < sc->lanes) { |
308 | if (sc->lane[j].enable) | 308 | if (sc->lane[j].enable) |
309 | return j; | 309 | return j; |
310 | } | 310 | } |
311 | return j; | 311 | return j; |
312 | } | 312 | } |
313 | 313 | ||
314 | #define for_each_lane(sc, i) \ | 314 | #define for_each_lane(sc, i) \ |
315 | for (i = 0; i < (sc)->lanes; i++) | 315 | for (i = 0; i < (sc)->lanes; i++) |
316 | 316 | ||
317 | #define for_each_enable_lane(sc, i) \ | 317 | #define for_each_enable_lane(sc, i) \ |
318 | for (i = -1; i = next_enable_lane(sc, i), i < sc->lanes; ) | 318 | for (i = -1; i = next_enable_lane(sc, i), i < sc->lanes; ) |
319 | 319 | ||
320 | static inline u32 kserdes_readl(void __iomem *base, u32 offset) | 320 | static inline u32 kserdes_readl(void __iomem *base, u32 offset) |
321 | { | 321 | { |
322 | return readl(base + offset); | 322 | return readl(base + offset); |
323 | } | 323 | } |
324 | 324 | ||
325 | static inline void kserdes_writel(void __iomem *base, u32 offset, u32 value) | 325 | static inline void kserdes_writel(void __iomem *base, u32 offset, u32 value) |
326 | { | 326 | { |
327 | writel(value, base + offset); | 327 | writel(value, base + offset); |
328 | } | 328 | } |
329 | 329 | ||
330 | static void kserdes_do_config(void __iomem *base, | 330 | static void kserdes_do_config(void __iomem *base, |
331 | struct serdes_cfg *cfg, u32 size) | 331 | struct serdes_cfg *cfg, u32 size) |
332 | { | 332 | { |
333 | u32 i; | 333 | u32 i; |
334 | 334 | ||
335 | for (i = 0; i < size; i++) | 335 | for (i = 0; i < size; i++) |
336 | FINSR(base, cfg[i].ofs, cfg[i].msb, cfg[i].lsb, cfg[i].val); | 336 | FINSR(base, cfg[i].ofs, cfg[i].msb, cfg[i].lsb, cfg[i].val); |
337 | } | 337 | } |
338 | 338 | ||
339 | static int kserdes_load_init_fw(struct kserdes_config *sc, | 339 | static int kserdes_load_init_fw(struct kserdes_config *sc, |
340 | const char * const *a_firmwares, | 340 | const char * const *a_firmwares, |
341 | int n_firmwares) | 341 | int n_firmwares) |
342 | { | 342 | { |
343 | const struct firmware *fw; | 343 | const struct firmware *fw; |
344 | bool found = false; | 344 | bool found = false; |
345 | int ret, i; | 345 | int ret, i; |
346 | 346 | ||
347 | for (i = 0; i < n_firmwares; i++) { | 347 | for (i = 0; i < n_firmwares; i++) { |
348 | if (a_firmwares[i]) { | 348 | if (a_firmwares[i]) { |
349 | ret = request_firmware(&fw, a_firmwares[i], sc->dev); | 349 | ret = request_firmware(&fw, a_firmwares[i], sc->dev); |
350 | if (!ret) { | 350 | if (!ret) { |
351 | found = true; | 351 | found = true; |
352 | break; | 352 | break; |
353 | } | 353 | } |
354 | } | 354 | } |
355 | } | 355 | } |
356 | 356 | ||
357 | if (!found) { | 357 | if (!found) { |
358 | dev_err(sc->dev, "can't get any serdes init fw"); | 358 | dev_err(sc->dev, "can't get any serdes init fw"); |
359 | return -ENODEV; | 359 | return -ENODEV; |
360 | } | 360 | } |
361 | 361 | ||
362 | sc->init_fw = a_firmwares[i]; | 362 | sc->init_fw = a_firmwares[i]; |
363 | sc->init_cfg = devm_kzalloc(sc->dev, fw->size, GFP_KERNEL); | 363 | sc->init_cfg = devm_kzalloc(sc->dev, fw->size, GFP_KERNEL); |
364 | memcpy((void *)sc->init_cfg, fw->data, fw->size); | 364 | memcpy((void *)sc->init_cfg, fw->data, fw->size); |
365 | sc->init_cfg_len = fw->size; | 365 | sc->init_cfg_len = fw->size; |
366 | release_firmware(fw); | 366 | release_firmware(fw); |
367 | 367 | ||
368 | kserdes_do_config(sc->regs, sc->init_cfg, | 368 | kserdes_do_config(sc->regs, sc->init_cfg, |
369 | sc->init_cfg_len / sizeof(struct serdes_cfg)); | 369 | sc->init_cfg_len / sizeof(struct serdes_cfg)); |
370 | 370 | ||
371 | return 0; | 371 | return 0; |
372 | } | 372 | } |
373 | 373 | ||
374 | static inline u32 _kserdes_read_tbus_val(void __iomem *sregs) | 374 | static inline u32 _kserdes_read_tbus_val(void __iomem *sregs) |
375 | { | 375 | { |
376 | u32 tmp; | 376 | u32 tmp; |
377 | 377 | ||
378 | if (PHY_A(sregs)) { | 378 | if (PHY_A(sregs)) { |
379 | tmp = ((kserdes_readl(sregs, CMU0_REG(0xec))) >> 24) & 0x0ff; | 379 | tmp = ((kserdes_readl(sregs, CMU0_REG(0xec))) >> 24) & 0x0ff; |
380 | tmp |= ((kserdes_readl(sregs, CMU0_REG(0xfc))) >> 16) & 0xf00; | 380 | tmp |= ((kserdes_readl(sregs, CMU0_REG(0xfc))) >> 16) & 0xf00; |
381 | } else { | 381 | } else { |
382 | tmp = ((kserdes_readl(sregs, CMU0_REG(0xf8))) >> 16) & 0xfff; | 382 | tmp = ((kserdes_readl(sregs, CMU0_REG(0xf8))) >> 16) & 0xfff; |
383 | } | 383 | } |
384 | 384 | ||
385 | return tmp; | 385 | return tmp; |
386 | } | 386 | } |
387 | 387 | ||
388 | static void _kserdes_write_tbus_addr(void __iomem *sregs, int select, int ofs) | 388 | static void _kserdes_write_tbus_addr(void __iomem *sregs, int select, int ofs) |
389 | { | 389 | { |
390 | if (select && !FOUR_LANE(sregs)) | 390 | if (select && !FOUR_LANE(sregs)) |
391 | ++select; | 391 | ++select; |
392 | 392 | ||
393 | if (PHY_A(sregs)) | 393 | if (PHY_A(sregs)) |
394 | FINSR(sregs, CMU0_REG(0x8), 31, 24, ((select << 5) + ofs)); | 394 | FINSR(sregs, CMU0_REG(0x8), 31, 24, ((select << 5) + ofs)); |
395 | else | 395 | else |
396 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((select << 8) + ofs)); | 396 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((select << 8) + ofs)); |
397 | } | 397 | } |
398 | 398 | ||
399 | static u32 _kserdes_read_select_tbus(void __iomem *sregs, int select, int ofs) | 399 | static u32 _kserdes_read_select_tbus(void __iomem *sregs, int select, int ofs) |
400 | { | 400 | { |
401 | /* set tbus address */ | 401 | /* set tbus address */ |
402 | _kserdes_write_tbus_addr(sregs, select, ofs); | 402 | _kserdes_write_tbus_addr(sregs, select, ofs); |
403 | /* get tbus value */ | 403 | /* get tbus value */ |
404 | return _kserdes_read_tbus_val(sregs); | 404 | return _kserdes_read_tbus_val(sregs); |
405 | } | 405 | } |
406 | 406 | ||
407 | static inline void kserdes_tap1_patch(struct kserdes_config *sc) | 407 | static inline void kserdes_tap1_patch(struct kserdes_config *sc) |
408 | { | 408 | { |
409 | FINSR(sc->regs, CML_REG(0xbc), 28, 24, 0x1e); | 409 | FINSR(sc->regs, CML_REG(0xbc), 28, 24, 0x1e); |
410 | } | 410 | } |
411 | 411 | ||
412 | static inline void kserdes_set_tx_idle(struct kserdes_config *sc, u32 lane) | 412 | static inline void kserdes_set_tx_idle(struct kserdes_config *sc, u32 lane) |
413 | { | 413 | { |
414 | if (sc->phy_type != KSERDES_PHY_XGE) | 414 | if (sc->phy_type != KSERDES_PHY_XGE) |
415 | FINSR(sc->regs, LANEX_REG(lane, 0xb8), 17, 16, 3); | 415 | FINSR(sc->regs, LANEX_REG(lane, 0xb8), 17, 16, 3); |
416 | 416 | ||
417 | FINSR(sc->regs, LANE_CTRL_STS_REG(lane), 25, 24, 3); | 417 | FINSR(sc->regs, LANE_CTRL_STS_REG(lane), 25, 24, 3); |
418 | FINSR(sc->regs, LANEX_REG(lane, 0x28), 21, 20, 0); | 418 | FINSR(sc->regs, LANEX_REG(lane, 0x28), 21, 20, 0); |
419 | } | 419 | } |
420 | 420 | ||
421 | static inline void kserdes_clr_tx_idle(struct kserdes_config *sc, u32 lane) | 421 | static inline void kserdes_clr_tx_idle(struct kserdes_config *sc, u32 lane) |
422 | { | 422 | { |
423 | if (sc->phy_type != KSERDES_PHY_XGE) | 423 | if (sc->phy_type != KSERDES_PHY_XGE) |
424 | FINSR(sc->regs, LANEX_REG(lane, 0xb8), 17, 16, 0); | 424 | FINSR(sc->regs, LANEX_REG(lane, 0xb8), 17, 16, 0); |
425 | 425 | ||
426 | FINSR(sc->regs, LANE_CTRL_STS_REG(lane), 25, 24, 0); | 426 | FINSR(sc->regs, LANE_CTRL_STS_REG(lane), 25, 24, 0); |
427 | FINSR(sc->regs, LANEX_REG(lane, 0x28), 21, 20, 0); | 427 | FINSR(sc->regs, LANEX_REG(lane, 0x28), 21, 20, 0); |
428 | } | 428 | } |
429 | 429 | ||
430 | static inline void kserdes_cdfe_enable(struct kserdes_config *sc, u32 lane) | 430 | static inline void kserdes_cdfe_enable(struct kserdes_config *sc, u32 lane) |
431 | { | 431 | { |
432 | FINSR(sc->regs, LANEX_REG(lane, 0x94), 24, 24, 0x1); | 432 | FINSR(sc->regs, LANEX_REG(lane, 0x94), 24, 24, 0x1); |
433 | } | 433 | } |
434 | 434 | ||
435 | static inline void kserdes_cdfe_force_calibration_enable( | 435 | static inline void kserdes_cdfe_force_calibration_enable( |
436 | struct kserdes_config *sc, u32 lane) | 436 | struct kserdes_config *sc, u32 lane) |
437 | { | 437 | { |
438 | FINSR(sc->regs, LANEX_REG(lane, 0x98), 0, 0, 0x1); | 438 | FINSR(sc->regs, LANEX_REG(lane, 0x98), 0, 0, 0x1); |
439 | } | 439 | } |
440 | 440 | ||
441 | static void kserdes_phyb_patch(struct kserdes_config *sc) | 441 | static void kserdes_phyb_patch(struct kserdes_config *sc) |
442 | { | 442 | { |
443 | int lane; | 443 | int lane; |
444 | 444 | ||
445 | for_each_enable_lane(sc, lane) | 445 | for_each_enable_lane(sc, lane) |
446 | kserdes_cdfe_enable(sc, lane); | 446 | kserdes_cdfe_enable(sc, lane); |
447 | 447 | ||
448 | /* setting initial rx */ | 448 | /* setting initial rx */ |
449 | FINSR(sc->regs, CML_REG(0x108), 23, 16, 0x04); | 449 | FINSR(sc->regs, CML_REG(0x108), 23, 16, 0x04); |
450 | 450 | ||
451 | /* setting rx */ | 451 | /* setting rx */ |
452 | FINSR(sc->regs, CML_REG(0xbc), 28, 24, 0x0); | 452 | FINSR(sc->regs, CML_REG(0xbc), 28, 24, 0x0); |
453 | 453 | ||
454 | for_each_lane(sc, lane) | 454 | for_each_lane(sc, lane) |
455 | kserdes_cdfe_force_calibration_enable(sc, lane); | 455 | kserdes_cdfe_force_calibration_enable(sc, lane); |
456 | } | 456 | } |
457 | 457 | ||
458 | static inline void kserdes_set_lane_starts(struct kserdes_config *sc, u32 lane) | 458 | static inline void kserdes_set_lane_starts(struct kserdes_config *sc, u32 lane) |
459 | { | 459 | { |
460 | /* att start -1 for short channel */ | 460 | /* att start -1 for short channel */ |
461 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 11, 8, | 461 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 11, 8, |
462 | sc->lane[lane].rx_start.att); | 462 | sc->lane[lane].rx_start.att); |
463 | /* boost start -3 for short channel */ | 463 | /* boost start -3 for short channel */ |
464 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 15, 12, | 464 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 15, 12, |
465 | sc->lane[lane].rx_start.boost); | 465 | sc->lane[lane].rx_start.boost); |
466 | } | 466 | } |
467 | 467 | ||
468 | static void kserdes_phy_patch(struct kserdes_config *sc) | 468 | static void kserdes_phy_patch(struct kserdes_config *sc) |
469 | { | 469 | { |
470 | int lane; | 470 | int lane; |
471 | 471 | ||
472 | if (sc->phy_type == KSERDES_PHY_XGE) { | 472 | if (sc->phy_type == KSERDES_PHY_XGE) { |
473 | kserdes_phyb_patch(sc); | 473 | kserdes_phyb_patch(sc); |
474 | } | 474 | } |
475 | 475 | ||
476 | /* Set ATT and BOOST start values for each lane */ | 476 | /* Set ATT and BOOST start values for each lane */ |
477 | for_each_enable_lane(sc, lane) | 477 | for_each_enable_lane(sc, lane) |
478 | kserdes_set_lane_starts(sc, lane); | 478 | kserdes_set_lane_starts(sc, lane); |
479 | } | 479 | } |
480 | 480 | ||
481 | static void kserdes_set_lane_overrides(struct kserdes_config *sc, u32 lane) | 481 | static void kserdes_set_lane_overrides(struct kserdes_config *sc, u32 lane) |
482 | { | 482 | { |
483 | u32 val_0, val_1, val; | 483 | u32 val_0, val_1, val; |
484 | 484 | ||
485 | /* Assert Reset while preserving control bits */ | 485 | /* Assert Reset while preserving control bits */ |
486 | val_0 = _kserdes_read_select_tbus(sc->regs, lane + 1, 0); | 486 | val_0 = _kserdes_read_select_tbus(sc->regs, lane + 1, 0); |
487 | 487 | ||
488 | val_1 = _kserdes_read_select_tbus(sc->regs, lane + 1, 1); | 488 | val_1 = _kserdes_read_select_tbus(sc->regs, lane + 1, 1); |
489 | 489 | ||
490 | val = 0; | 490 | val = 0; |
491 | val |= ((val_1 >> 9) & 0x3) << 1; | 491 | val |= ((val_1 >> 9) & 0x3) << 1; |
492 | val |= (val_0 & 0x3) << 3; | 492 | val |= (val_0 & 0x3) << 3; |
493 | val |= ((val_0 >> 2) & 0x1ff) << 5; | 493 | val |= ((val_0 >> 2) & 0x1ff) << 5; |
494 | val |= (1 << 14); | 494 | val |= (1 << 14); |
495 | val &= ~0x60; | 495 | val &= ~0x60; |
496 | 496 | ||
497 | /* Only modify the reset bit and the overlay bit */ | 497 | /* Only modify the reset bit and the overlay bit */ |
498 | FINSR(sc->regs, LANEX_REG(lane, 0x028), 29, 15, val); | 498 | FINSR(sc->regs, LANEX_REG(lane, 0x028), 29, 15, val); |
499 | } | 499 | } |
500 | 500 | ||
501 | static inline void kserdes_assert_reset(struct kserdes_config *sc) | 501 | static inline void kserdes_assert_reset(struct kserdes_config *sc) |
502 | { | 502 | { |
503 | int lane; | 503 | int lane; |
504 | 504 | ||
505 | for_each_enable_lane(sc, lane) | 505 | for_each_enable_lane(sc, lane) |
506 | kserdes_set_lane_overrides(sc, lane); | 506 | kserdes_set_lane_overrides(sc, lane); |
507 | } | 507 | } |
508 | 508 | ||
509 | static inline void kserdes_config_c1_c2_cm(struct kserdes_config *sc, u32 lane) | 509 | static inline void kserdes_config_c1_c2_cm(struct kserdes_config *sc, u32 lane) |
510 | { | 510 | { |
511 | u32 c1, c2, cm; | 511 | u32 c1, c2, cm; |
512 | 512 | ||
513 | c1 = sc->lane[lane].tx_coeff.c1; | 513 | c1 = sc->lane[lane].tx_coeff.c1; |
514 | c2 = sc->lane[lane].tx_coeff.c2; | 514 | c2 = sc->lane[lane].tx_coeff.c2; |
515 | cm = sc->lane[lane].tx_coeff.cm; | 515 | cm = sc->lane[lane].tx_coeff.cm; |
516 | 516 | ||
517 | if (sc->phy_type == KSERDES_PHY_XGE) { | 517 | if (sc->phy_type == KSERDES_PHY_XGE) { |
518 | /* TX Control override enable */ | 518 | /* TX Control override enable */ |
519 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 11, 8, (cm & 0xf)); | 519 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 11, 8, (cm & 0xf)); |
520 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 4, 0, (c1 & 0x1f)); | 520 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 4, 0, (c1 & 0x1f)); |
521 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 7, 5, (c2 & 0x7)); | 521 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 7, 5, (c2 & 0x7)); |
522 | FINSR(sc->regs, LANEX_REG(lane, 0x4), | 522 | FINSR(sc->regs, LANEX_REG(lane, 0x4), |
523 | 18, 18, ((c2 >> 3) & 0x1)); | 523 | 18, 18, ((c2 >> 3) & 0x1)); |
524 | } else { | 524 | } else { |
525 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 15, 12, (cm & 0xf)); | 525 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 15, 12, (cm & 0xf)); |
526 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 4, 0, (c1 & 0x1f)); | 526 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 4, 0, (c1 & 0x1f)); |
527 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 11, 8, (c2 & 0xf)); | 527 | FINSR(sc->regs, LANEX_REG(lane, 0x8), 11, 8, (c2 & 0xf)); |
528 | } | 528 | } |
529 | } | 529 | } |
530 | 530 | ||
531 | static inline void kserdes_config_att_boost(struct kserdes_config *sc, u32 lane) | 531 | static inline void kserdes_config_att_boost(struct kserdes_config *sc, u32 lane) |
532 | { | 532 | { |
533 | u32 att, boost; | 533 | u32 att, boost; |
534 | 534 | ||
535 | att = sc->lane[lane].rx_force.att; | 535 | att = sc->lane[lane].rx_force.att; |
536 | boost = sc->lane[lane].rx_force.boost; | 536 | boost = sc->lane[lane].rx_force.boost; |
537 | 537 | ||
538 | if (sc->phy_type == KSERDES_PHY_XGE) { | 538 | if (sc->phy_type == KSERDES_PHY_XGE) { |
539 | FINSR(sc->regs, LANEX_REG(lane, 0x98), 13, 13, 0); | 539 | FINSR(sc->regs, LANEX_REG(lane, 0x98), 13, 13, 0); |
540 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 15, 12, boost); | 540 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 15, 12, boost); |
541 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 11, 8, att); | 541 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 11, 8, att); |
542 | } else { | 542 | } else { |
543 | if (att != 1) { | 543 | if (att != 1) { |
544 | FINSR(sc->regs, CML_REG(0x84), 0, 0, 0); | 544 | FINSR(sc->regs, CML_REG(0x84), 0, 0, 0); |
545 | FINSR(sc->regs, CML_REG(0x8c), 24, 24, 0); | 545 | FINSR(sc->regs, CML_REG(0x8c), 24, 24, 0); |
546 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 11, 8, att); | 546 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 11, 8, att); |
547 | } | 547 | } |
548 | if (boost != 1) { | 548 | if (boost != 1) { |
549 | FINSR(sc->regs, CML_REG(0x84), 1, 1, 0); | 549 | FINSR(sc->regs, CML_REG(0x84), 1, 1, 0); |
550 | FINSR(sc->regs, CML_REG(0x8c), 25, 25, 0); | 550 | FINSR(sc->regs, CML_REG(0x8c), 25, 25, 0); |
551 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 15, 12, boost); | 551 | FINSR(sc->regs, LANEX_REG(lane, 0x8c), 15, 12, boost); |
552 | } | 552 | } |
553 | } | 553 | } |
554 | } | 554 | } |
555 | 555 | ||
556 | static void kserdes_set_tx_rx_fir_coeff(struct kserdes_config *sc, u32 lane) | 556 | static void kserdes_set_tx_rx_fir_coeff(struct kserdes_config *sc, u32 lane) |
557 | { | 557 | { |
558 | struct kserdes_tx_coeff *tc = &sc->lane[lane].tx_coeff; | 558 | struct kserdes_tx_coeff *tc = &sc->lane[lane].tx_coeff; |
559 | 559 | ||
560 | if (sc->phy_type == KSERDES_PHY_XGE) { | 560 | if (sc->phy_type == KSERDES_PHY_XGE) { |
561 | /* Tx Swing */ | 561 | /* Tx Swing */ |
562 | FINSR(sc->regs, LANEX_REG(lane, 0x004), 29, 26, tc->att); | 562 | FINSR(sc->regs, LANEX_REG(lane, 0x004), 29, 26, tc->att); |
563 | /* Regulator voltage */ | 563 | /* Regulator voltage */ |
564 | FINSR(sc->regs, LANEX_REG(lane, 0x0a4), 2, 0, tc->vreg); | 564 | FINSR(sc->regs, LANEX_REG(lane, 0x0a4), 2, 0, tc->vreg); |
565 | } else { | 565 | } else { |
566 | /* Tx Swing */ | 566 | /* Tx Swing */ |
567 | FINSR(sc->regs, LANEX_REG(lane, 0x004), 28, 25, tc->att); | 567 | FINSR(sc->regs, LANEX_REG(lane, 0x004), 28, 25, tc->att); |
568 | /* Regulator voltage */ | 568 | /* Regulator voltage */ |
569 | FINSR(sc->regs, LANEX_REG(lane, 0x084), 7, 5, tc->vreg); | 569 | FINSR(sc->regs, LANEX_REG(lane, 0x084), 7, 5, tc->vreg); |
570 | } | 570 | } |
571 | 571 | ||
572 | kserdes_config_c1_c2_cm(sc, lane); | 572 | kserdes_config_c1_c2_cm(sc, lane); |
573 | 573 | ||
574 | if (sc->rx_force_enable) | 574 | if (sc->rx_force_enable) |
575 | kserdes_config_att_boost(sc, lane); | 575 | kserdes_config_att_boost(sc, lane); |
576 | } | 576 | } |
577 | 577 | ||
578 | static inline void _kserdes_force_signal_detect_low( | 578 | static inline void _kserdes_force_signal_detect_low( |
579 | void __iomem *sregs, u32 lane) | 579 | void __iomem *sregs, u32 lane) |
580 | { | 580 | { |
581 | FINSR(sregs, LANEX_REG(lane, 0x004), 2, 1, 0x2); | 581 | FINSR(sregs, LANEX_REG(lane, 0x004), 2, 1, 0x2); |
582 | } | 582 | } |
583 | 583 | ||
584 | static inline void kserdes_force_signal_detect_low( | 584 | static inline void kserdes_force_signal_detect_low( |
585 | struct kserdes_config *sc, u32 lane) | 585 | struct kserdes_config *sc, u32 lane) |
586 | { | 586 | { |
587 | _kserdes_force_signal_detect_low(sc->regs, lane); | 587 | _kserdes_force_signal_detect_low(sc->regs, lane); |
588 | } | 588 | } |
589 | 589 | ||
590 | static inline void _kserdes_force_signal_detect_high( | 590 | static inline void _kserdes_force_signal_detect_high( |
591 | void __iomem *sregs, u32 lane) | 591 | void __iomem *sregs, u32 lane) |
592 | { | 592 | { |
593 | FINSR(sregs, LANEX_REG(lane, 0x004), 2, 1, 0x0); | 593 | FINSR(sregs, LANEX_REG(lane, 0x004), 2, 1, 0x0); |
594 | } | 594 | } |
595 | 595 | ||
596 | static inline void kserdes_force_signal_detect_high( | 596 | static inline void kserdes_force_signal_detect_high( |
597 | struct kserdes_config *sc, u32 lane) | 597 | struct kserdes_config *sc, u32 lane) |
598 | { | 598 | { |
599 | _kserdes_force_signal_detect_high(sc->regs, lane); | 599 | _kserdes_force_signal_detect_high(sc->regs, lane); |
600 | } | 600 | } |
601 | 601 | ||
602 | static int kserdes_deassert_reset_poll_others(struct kserdes_config *sc) | 602 | static int kserdes_deassert_reset_poll_others(struct kserdes_config *sc) |
603 | { | 603 | { |
604 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | 604 | unsigned long timeout = jiffies + msecs_to_jiffies(500); |
605 | unsigned long time_check; | 605 | unsigned long time_check; |
606 | u32 lanes_not_ok = 0; | 606 | u32 lanes_not_ok = 0; |
607 | u32 ofs = 28; | 607 | u32 ofs = 28; |
608 | u32 ret, i; | 608 | u32 ret, i; |
609 | 609 | ||
610 | /* | 610 | /* |
611 | * assume all enable lanes not-ok (1) and all others | 611 | * assume all enable lanes not-ok (1) and all others |
612 | * ok (0) to start | 612 | * ok (0) to start |
613 | */ | 613 | */ |
614 | for_each_enable_lane(sc, i) | 614 | for_each_enable_lane(sc, i) |
615 | lanes_not_ok |= (1 << i); | 615 | lanes_not_ok |= (1 << i); |
616 | 616 | ||
617 | /* | 617 | /* |
618 | * This is not a mistake. For 2-laner, we | 618 | * This is not a mistake. For 2-laner, we |
619 | * check bit 29 and 30, NOT 28 and 29. | 619 | * check bit 29 and 30, NOT 28 and 29. |
620 | */ | 620 | */ |
621 | if (!FOUR_LANE(sc->regs)) | 621 | if (!FOUR_LANE(sc->regs)) |
622 | ofs = 29; | 622 | ofs = 29; |
623 | 623 | ||
624 | do { | 624 | do { |
625 | time_check = jiffies; | 625 | time_check = jiffies; |
626 | for_each_enable_lane(sc, i) { | 626 | for_each_enable_lane(sc, i) { |
627 | /* | 627 | /* |
628 | * no need to check again if this lane's status | 628 | * no need to check again if this lane's status |
629 | * is already good | 629 | * is already good |
630 | */ | 630 | */ |
631 | if (!(lanes_not_ok & (1 << i))) | 631 | if (!(lanes_not_ok & (1 << i))) |
632 | continue; | 632 | continue; |
633 | 633 | ||
634 | ret = kserdes_readl(sc->regs, CML_REG(0x1f8)); | 634 | ret = kserdes_readl(sc->regs, CML_REG(0x1f8)); |
635 | 635 | ||
636 | /* | 636 | /* |
637 | * clear corresponding lane_not_ok bit if | 637 | * clear corresponding lane_not_ok bit if |
638 | * status is good (1) | 638 | * status is good (1) |
639 | */ | 639 | */ |
640 | if (ret & BIT(ofs + i)) | 640 | if (ret & BIT(ofs + i)) |
641 | lanes_not_ok &= ~(1 << i); | 641 | lanes_not_ok &= ~(1 << i); |
642 | } | 642 | } |
643 | 643 | ||
644 | /* get out if all lanes are good to go */ | 644 | /* get out if all lanes are good to go */ |
645 | if (!lanes_not_ok) | 645 | if (!lanes_not_ok) |
646 | return 0; | 646 | return 0; |
647 | 647 | ||
648 | if (time_after(time_check, timeout)) | 648 | if (time_after(time_check, timeout)) |
649 | return -ETIMEDOUT; | 649 | return -ETIMEDOUT; |
650 | 650 | ||
651 | cpu_relax(); | 651 | cpu_relax(); |
652 | } while (true); | 652 | } while (true); |
653 | } | 653 | } |
654 | 654 | ||
655 | static int kserdes_deassert_reset_poll_pcie(struct kserdes_config *sc) | 655 | static int kserdes_deassert_reset_poll_pcie(struct kserdes_config *sc) |
656 | { | 656 | { |
657 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | 657 | unsigned long timeout = jiffies + msecs_to_jiffies(500); |
658 | unsigned long time_check; | 658 | unsigned long time_check; |
659 | u32 lanes_not_ok = 0; | 659 | u32 lanes_not_ok = 0; |
660 | u32 ret, i; | 660 | u32 ret, i; |
661 | 661 | ||
662 | /* | 662 | /* |
663 | * assume all enable lanes not-ok (1) and all others | 663 | * assume all enable lanes not-ok (1) and all others |
664 | * ok (0) to start | 664 | * ok (0) to start |
665 | */ | 665 | */ |
666 | for_each_enable_lane(sc, i) | 666 | for_each_enable_lane(sc, i) |
667 | lanes_not_ok |= (1 << i); | 667 | lanes_not_ok |= (1 << i); |
668 | 668 | ||
669 | do { | 669 | do { |
670 | time_check = jiffies; | 670 | time_check = jiffies; |
671 | for_each_enable_lane(sc, i) { | 671 | for_each_enable_lane(sc, i) { |
672 | /* | 672 | /* |
673 | * no need to check again if this lane's status | 673 | * no need to check again if this lane's status |
674 | * is already good | 674 | * is already good |
675 | */ | 675 | */ |
676 | if (!(lanes_not_ok & (1 << i))) | 676 | if (!(lanes_not_ok & (1 << i))) |
677 | continue; | 677 | continue; |
678 | 678 | ||
679 | ret = _kserdes_read_select_tbus(sc->regs, i + 1, 0x02); | 679 | ret = _kserdes_read_select_tbus(sc->regs, i + 1, 0x02); |
680 | 680 | ||
681 | /* | 681 | /* |
682 | * clear corresponding lane_not_ok bit if | 682 | * clear corresponding lane_not_ok bit if |
683 | * status is good (0) | 683 | * status is good (0) |
684 | */ | 684 | */ |
685 | if (!(ret & BIT(4))) | 685 | if (!(ret & BIT(4))) |
686 | lanes_not_ok &= ~(1 << i); | 686 | lanes_not_ok &= ~(1 << i); |
687 | } | 687 | } |
688 | 688 | ||
689 | /* get out if all lanes are good to go */ | 689 | /* get out if all lanes are good to go */ |
690 | if (!lanes_not_ok) | 690 | if (!lanes_not_ok) |
691 | return 0; | 691 | return 0; |
692 | 692 | ||
693 | if (time_after(time_check, timeout)) | 693 | if (time_after(time_check, timeout)) |
694 | return -ETIMEDOUT; | 694 | return -ETIMEDOUT; |
695 | 695 | ||
696 | cpu_relax(); | 696 | cpu_relax(); |
697 | } while (true); | 697 | } while (true); |
698 | } | 698 | } |
699 | 699 | ||
700 | static inline void _kserdes_lane_reset(void __iomem *serdes, | 700 | static inline void _kserdes_lane_reset(void __iomem *serdes, |
701 | u32 lane, u32 reset) | 701 | u32 lane, u32 reset) |
702 | { | 702 | { |
703 | FINSR(serdes, LANEX_REG(lane, 0x28), 29, 29, !!reset); | 703 | FINSR(serdes, LANEX_REG(lane, 0x28), 29, 29, !!reset); |
704 | } | 704 | } |
705 | 705 | ||
706 | static inline void kserdes_release_reset(struct kserdes_config *sc, u32 lane) | 706 | static inline void kserdes_release_reset(struct kserdes_config *sc, u32 lane) |
707 | { | 707 | { |
708 | if (sc->phy_type == KSERDES_PHY_XGE) { | 708 | if (sc->phy_type == KSERDES_PHY_XGE) { |
709 | FINSR(sc->regs, LANEX_REG(lane, 0x60), 0, 0, 0x1); | 709 | FINSR(sc->regs, LANEX_REG(lane, 0x60), 0, 0, 0x1); |
710 | } | 710 | } |
711 | /* release reset */ | 711 | /* release reset */ |
712 | _kserdes_lane_reset(sc->regs, lane, 0); | 712 | _kserdes_lane_reset(sc->regs, lane, 0); |
713 | } | 713 | } |
714 | 714 | ||
715 | static int kserdes_deassert_reset(struct kserdes_config *sc, u32 poll) | 715 | static int kserdes_deassert_reset(struct kserdes_config *sc, u32 poll) |
716 | { | 716 | { |
717 | int ret = 0, lane; | 717 | int ret = 0, lane; |
718 | 718 | ||
719 | for_each_enable_lane(sc, lane) | 719 | for_each_enable_lane(sc, lane) |
720 | kserdes_release_reset(sc, lane); | 720 | kserdes_release_reset(sc, lane); |
721 | 721 | ||
722 | if (!poll) | 722 | if (!poll) |
723 | goto done; | 723 | goto done; |
724 | 724 | ||
725 | /* Check Lane OK */ | 725 | /* Check Lane OK */ |
726 | if (sc->phy_type == KSERDES_PHY_PCIE) | 726 | if (sc->phy_type == KSERDES_PHY_PCIE) |
727 | ret = kserdes_deassert_reset_poll_pcie(sc); | 727 | ret = kserdes_deassert_reset_poll_pcie(sc); |
728 | else | 728 | else |
729 | ret = kserdes_deassert_reset_poll_others(sc); | 729 | ret = kserdes_deassert_reset_poll_others(sc); |
730 | 730 | ||
731 | done: | 731 | done: |
732 | return ret; | 732 | return ret; |
733 | } | 733 | } |
734 | 734 | ||
735 | static inline void kserdes_lane_disable(struct kserdes_config *sc, u32 lane) | 735 | static inline void kserdes_lane_disable(struct kserdes_config *sc, u32 lane) |
736 | { | 736 | { |
737 | FINSR(sc->regs, LANE_CTRL_STS_REG(lane), 31, 29, 0x4); | 737 | FINSR(sc->regs, LANE_CTRL_STS_REG(lane), 31, 29, 0x4); |
738 | FINSR(sc->regs, LANE_CTRL_STS_REG(lane), 15, 13, 0x4); | 738 | FINSR(sc->regs, LANE_CTRL_STS_REG(lane), 15, 13, 0x4); |
739 | } | 739 | } |
740 | 740 | ||
741 | static inline void _kserdes_lane_enable(void __iomem *sregs, u32 lane) | 741 | static inline void _kserdes_lane_enable(void __iomem *sregs, u32 lane) |
742 | { | 742 | { |
743 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 31, 29, 0x7); | 743 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 31, 29, 0x7); |
744 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 15, 13, 0x7); | 744 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 15, 13, 0x7); |
745 | } | 745 | } |
746 | 746 | ||
747 | /* Caller should make sure sgmii cannot be fullrate */ | 747 | /* Caller should make sure sgmii cannot be fullrate */ |
748 | static inline int _kserdes_set_lane_ctrl_rate(void __iomem *sregs, u32 lane, | 748 | static inline int _kserdes_set_lane_ctrl_rate(void __iomem *sregs, u32 lane, |
749 | enum kserdes_lane_ctrl_rate rate) | 749 | enum kserdes_lane_ctrl_rate rate) |
750 | { | 750 | { |
751 | u32 rate_mode; | 751 | u32 rate_mode; |
752 | 752 | ||
753 | switch (rate) { | 753 | switch (rate) { |
754 | case KSERDES_FULL_RATE: | 754 | case KSERDES_FULL_RATE: |
755 | rate_mode = 0x4; | 755 | rate_mode = 0x4; |
756 | break; | 756 | break; |
757 | case KSERDES_QUARTER_RATE: | 757 | case KSERDES_QUARTER_RATE: |
758 | rate_mode = 0x6; | 758 | rate_mode = 0x6; |
759 | break; | 759 | break; |
760 | case KSERDES_HALF_RATE: | 760 | case KSERDES_HALF_RATE: |
761 | rate_mode = 0x5; | 761 | rate_mode = 0x5; |
762 | break; | 762 | break; |
763 | default: | 763 | default: |
764 | return -EINVAL; | 764 | return -EINVAL; |
765 | } | 765 | } |
766 | 766 | ||
767 | /* Tx */ | 767 | /* Tx */ |
768 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 28, 26, rate_mode); | 768 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 28, 26, rate_mode); |
769 | /* Rx */ | 769 | /* Rx */ |
770 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 12, 10, rate_mode); | 770 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 12, 10, rate_mode); |
771 | return 0; | 771 | return 0; |
772 | } | 772 | } |
773 | 773 | ||
774 | static inline void _kserdes_set_lane_loopback(void __iomem *sregs, u32 lane, | 774 | static inline void _kserdes_set_lane_loopback(void __iomem *sregs, u32 lane, |
775 | enum kserdes_link_rate link_rate) | 775 | enum kserdes_link_rate link_rate) |
776 | { | 776 | { |
777 | if (link_rate == KSERDES_LINK_RATE_10P3125G) { | 777 | if (link_rate == KSERDES_LINK_RATE_10P3125G) { |
778 | FINSR(sregs, LANEX_REG(lane, 0x0), 7, 0, 0x4); | 778 | FINSR(sregs, LANEX_REG(lane, 0x0), 7, 0, 0x4); |
779 | FINSR(sregs, LANEX_REG(lane, 0x4), 2, 1, 0x3); | 779 | FINSR(sregs, LANEX_REG(lane, 0x4), 2, 1, 0x3); |
780 | } else { | 780 | } else { |
781 | FINSR(sregs, LANEX_REG(lane, 0x0), 31, 24, 0x40); | 781 | FINSR(sregs, LANEX_REG(lane, 0x0), 31, 24, 0x40); |
782 | } | 782 | } |
783 | } | 783 | } |
784 | 784 | ||
785 | static void kserdes_set_lane_rate(struct kserdes_config *sc, u32 lane) | 785 | static void kserdes_set_lane_rate(struct kserdes_config *sc, u32 lane) |
786 | { | 786 | { |
787 | int ret; | 787 | int ret; |
788 | 788 | ||
789 | ret = _kserdes_set_lane_ctrl_rate(sc->regs, lane, | 789 | ret = _kserdes_set_lane_ctrl_rate(sc->regs, lane, |
790 | sc->lane[lane].ctrl_rate); | 790 | sc->lane[lane].ctrl_rate); |
791 | if (ret) { | 791 | if (ret) { |
792 | dev_err(sc->dev, "set_lane_rate FAILED: lane = %d err = %d\n", | 792 | dev_err(sc->dev, "set_lane_rate FAILED: lane = %d err = %d\n", |
793 | lane, ret); | 793 | lane, ret); |
794 | return; | 794 | return; |
795 | } | 795 | } |
796 | 796 | ||
797 | /* Config RXEQ Gain for all lanes */ | 797 | /* Config RXEQ Gain for all lanes */ |
798 | FINSR(sc->regs, LANEX_REG(lane, 0x30), 11, 11, 0x1); | 798 | FINSR(sc->regs, LANEX_REG(lane, 0x30), 11, 11, 0x1); |
799 | FINSR(sc->regs, LANEX_REG(lane, 0x30), 13, 12, 0x0); | 799 | FINSR(sc->regs, LANEX_REG(lane, 0x30), 13, 12, 0x0); |
800 | 800 | ||
801 | /* set NES bit if loopback enabled */ | 801 | /* set NES bit if loopback enabled */ |
802 | if (sc->lane[lane].loopback) | 802 | if (sc->lane[lane].loopback) |
803 | _kserdes_set_lane_loopback(sc->regs, lane, sc->link_rate); | 803 | _kserdes_set_lane_loopback(sc->regs, lane, sc->link_rate); |
804 | 804 | ||
805 | _kserdes_lane_enable(sc->regs, lane); | 805 | _kserdes_lane_enable(sc->regs, lane); |
806 | } | 806 | } |
807 | 807 | ||
808 | static inline void _kserdes_set_wait_after(void __iomem *sregs) | 808 | static inline void _kserdes_set_wait_after(void __iomem *sregs) |
809 | { | 809 | { |
810 | FINSR(sregs, PLL_CTRL_REG, 17, 16, 0x3); | 810 | FINSR(sregs, PLL_CTRL_REG, 17, 16, 0x3); |
811 | } | 811 | } |
812 | 812 | ||
813 | static inline void _kserdes_clear_wait_after(void __iomem *sregs) | 813 | static inline void _kserdes_clear_wait_after(void __iomem *sregs) |
814 | { | 814 | { |
815 | FINSR(sregs, PLL_CTRL_REG, 17, 16, 0); | 815 | FINSR(sregs, PLL_CTRL_REG, 17, 16, 0); |
816 | } | 816 | } |
817 | 817 | ||
818 | static inline void _kserdes_pll_enable(void __iomem *sregs) | 818 | static inline void _kserdes_pll_enable(void __iomem *sregs) |
819 | { | 819 | { |
820 | FINSR(sregs, PLL_CTRL_REG, 31, 29, 0x7); | 820 | FINSR(sregs, PLL_CTRL_REG, 31, 29, 0x7); |
821 | } | 821 | } |
822 | 822 | ||
823 | static inline void _kserdes_pll2_enable(void __iomem *sregs) | 823 | static inline void _kserdes_pll2_enable(void __iomem *sregs) |
824 | { | 824 | { |
825 | FINSR(sregs, PLL_CTRL_REG, 27, 25, 0x7); | 825 | FINSR(sregs, PLL_CTRL_REG, 27, 25, 0x7); |
826 | } | 826 | } |
827 | 827 | ||
828 | static inline void _kserdes_pll_disable(void __iomem *sregs) | 828 | static inline void _kserdes_pll_disable(void __iomem *sregs) |
829 | { | 829 | { |
830 | FINSR(sregs, PLL_CTRL_REG, 31, 29, 0x4); | 830 | FINSR(sregs, PLL_CTRL_REG, 31, 29, 0x4); |
831 | } | 831 | } |
832 | 832 | ||
833 | static inline void _kserdes_pll2_disable(void __iomem *sregs) | 833 | static inline void _kserdes_pll2_disable(void __iomem *sregs) |
834 | { | 834 | { |
835 | FINSR(sregs, PLL_CTRL_REG, 27, 25, 0x4); | 835 | FINSR(sregs, PLL_CTRL_REG, 27, 25, 0x4); |
836 | } | 836 | } |
837 | 837 | ||
838 | static inline u32 _kserdes_get_pll_status(void __iomem *sregs) | 838 | static inline u32 _kserdes_get_pll_status(void __iomem *sregs) |
839 | { | 839 | { |
840 | return FEXTR(kserdes_readl(sregs, PLL_CTRL_REG), 28, 28); | 840 | return FEXTR(kserdes_readl(sregs, PLL_CTRL_REG), 28, 28); |
841 | } | 841 | } |
842 | 842 | ||
843 | static inline u32 _kserdes_get_pll2_status(void __iomem *sregs) | 843 | static inline u32 _kserdes_get_pll2_status(void __iomem *sregs) |
844 | { | 844 | { |
845 | return FEXTR(kserdes_readl(sregs, PLL_CTRL_REG), 24, 24); | 845 | return FEXTR(kserdes_readl(sregs, PLL_CTRL_REG), 24, 24); |
846 | } | 846 | } |
847 | 847 | ||
848 | static inline void kserdes_lane_enable_loopback(void __iomem *serdes, u32 lane) | 848 | static inline void kserdes_lane_enable_loopback(void __iomem *serdes, u32 lane) |
849 | { | 849 | { |
850 | FINSR(serdes, LANEX_REG(lane, 0), 31, 24, 0x40); | 850 | FINSR(serdes, LANEX_REG(lane, 0), 31, 24, 0x40); |
851 | } | 851 | } |
852 | 852 | ||
853 | static inline u32 _kserdes_get_lane_status(void __iomem *sregs, u32 lane, | 853 | static inline u32 _kserdes_get_lane_status(void __iomem *sregs, u32 lane, |
854 | enum kserdes_phy_type phy_type) | 854 | enum kserdes_phy_type phy_type) |
855 | { | 855 | { |
856 | switch (phy_type) { | 856 | switch (phy_type) { |
857 | case KSERDES_PHY_PCIE: | 857 | case KSERDES_PHY_PCIE: |
858 | return FEXTR(kserdes_readl(sregs, PLL_CTRL_REG), lane, lane); | 858 | return FEXTR(kserdes_readl(sregs, PLL_CTRL_REG), lane, lane); |
859 | case KSERDES_PHY_XGE: | 859 | case KSERDES_PHY_XGE: |
860 | return FEXTR(kserdes_readl(sregs, CML_REG(0x1f8)), | 860 | return FEXTR(kserdes_readl(sregs, CML_REG(0x1f8)), |
861 | (29 + lane), (29 + lane)); | 861 | (29 + lane), (29 + lane)); |
862 | default: | 862 | default: |
863 | return FEXTR(kserdes_readl(sregs, PLL_CTRL_REG), | 863 | return FEXTR(kserdes_readl(sregs, PLL_CTRL_REG), |
864 | (8 + lane), (8 + lane)); | 864 | (8 + lane), (8 + lane)); |
865 | } | 865 | } |
866 | } | 866 | } |
867 | 867 | ||
868 | static u32 kserdes_get_pll_lanes_status(struct kserdes_config *sc) | 868 | static u32 kserdes_get_pll_lanes_status(struct kserdes_config *sc) |
869 | { | 869 | { |
870 | u32 val, i; | 870 | u32 val, i; |
871 | 871 | ||
872 | /* Check PLL OK Status Bit */ | 872 | /* Check PLL OK Status Bit */ |
873 | val = _kserdes_get_pll_status(sc->regs); | 873 | val = _kserdes_get_pll_status(sc->regs); |
874 | if (!val) { | 874 | if (!val) { |
875 | /* pll is not ready */ | 875 | /* pll is not ready */ |
876 | goto done; | 876 | goto done; |
877 | } | 877 | } |
878 | 878 | ||
879 | if (sc->phy_type == KSERDES_PHY_XGE) { | 879 | if (sc->phy_type == KSERDES_PHY_XGE) { |
880 | val = _kserdes_get_pll2_status(sc->regs); | 880 | val = _kserdes_get_pll2_status(sc->regs); |
881 | if (!val) | 881 | if (!val) |
882 | goto done; | 882 | goto done; |
883 | } | 883 | } |
884 | 884 | ||
885 | /* Check Lane OK Status Bits */ | 885 | /* Check Lane OK Status Bits */ |
886 | for_each_enable_lane(sc, i) | 886 | for_each_enable_lane(sc, i) |
887 | val &= _kserdes_get_lane_status(sc->regs, i, sc->phy_type); | 887 | val &= _kserdes_get_lane_status(sc->regs, i, sc->phy_type); |
888 | 888 | ||
889 | done: | 889 | done: |
890 | /* | 890 | /* |
891 | * if any of the status is 0, this is 0 | 891 | * if any of the status is 0, this is 0 |
892 | * i.e. serdes status is not good | 892 | * i.e. serdes status is not good |
893 | */ | 893 | */ |
894 | return val; | 894 | return val; |
895 | } | 895 | } |
896 | 896 | ||
897 | static int kserdes_get_status(struct kserdes_config *sc) | 897 | static int kserdes_get_status(struct kserdes_config *sc) |
898 | { | 898 | { |
899 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | 899 | unsigned long timeout = jiffies + msecs_to_jiffies(500); |
900 | unsigned long time_check; | 900 | unsigned long time_check; |
901 | 901 | ||
902 | do { | 902 | do { |
903 | time_check = jiffies; | 903 | time_check = jiffies; |
904 | if (kserdes_get_pll_lanes_status(sc)) | 904 | if (kserdes_get_pll_lanes_status(sc)) |
905 | break; | 905 | break; |
906 | 906 | ||
907 | if (time_after(time_check, timeout)) | 907 | if (time_after(time_check, timeout)) |
908 | return -ETIMEDOUT; | 908 | return -ETIMEDOUT; |
909 | 909 | ||
910 | cpu_relax(); | 910 | cpu_relax(); |
911 | } while (true); | 911 | } while (true); |
912 | 912 | ||
913 | return 0; | 913 | return 0; |
914 | } | 914 | } |
915 | 915 | ||
916 | static inline u32 _kserdes_get_tx_termination(void __iomem *sregs, u32 lane, | 916 | static inline u32 _kserdes_get_tx_termination(void __iomem *sregs, u32 lane, |
917 | enum kserdes_phy_type phy_type) | 917 | enum kserdes_phy_type phy_type) |
918 | { | 918 | { |
919 | return (_kserdes_read_select_tbus(sregs, lane + 1, | 919 | return (_kserdes_read_select_tbus(sregs, lane + 1, |
920 | ((phy_type == KSERDES_PHY_XGE) ? | 920 | ((phy_type == KSERDES_PHY_XGE) ? |
921 | 0x1a : 0x1b)) & 0xff); | 921 | 0x1a : 0x1b)) & 0xff); |
922 | } | 922 | } |
923 | 923 | ||
924 | static void kserdes_set_tx_terminations(struct kserdes_config *sc, u32 term) | 924 | static void kserdes_set_tx_terminations(struct kserdes_config *sc, u32 term) |
925 | { | 925 | { |
926 | u32 i; | 926 | u32 i; |
927 | 927 | ||
928 | for_each_lane(sc, i) { | 928 | for_each_lane(sc, i) { |
929 | FINSR(sc->regs, LANEX_REG(i, 0x7c), 31, 24, term); | 929 | FINSR(sc->regs, LANEX_REG(i, 0x7c), 31, 24, term); |
930 | FINSR(sc->regs, LANEX_REG(i, 0x7c), 20, 20, 0x1); | 930 | FINSR(sc->regs, LANEX_REG(i, 0x7c), 20, 20, 0x1); |
931 | } | 931 | } |
932 | } | 932 | } |
933 | 933 | ||
934 | /* lane is 0-based */ | 934 | /* lane is 0-based */ |
935 | static void | 935 | static void |
936 | _kserdes_get_cmp_tap_offsets_xge(void __iomem *sregs, u32 lane, u32 cmp, | 936 | _kserdes_get_cmp_tap_offsets_xge(void __iomem *sregs, u32 lane, u32 cmp, |
937 | struct kserdes_comparator_tap_ofs *ofs) | 937 | struct kserdes_cmp_tap_ofs *ofs) |
938 | { | 938 | { |
939 | /* set comparator number */ | 939 | /* set comparator number */ |
940 | FINSR(sregs, CML_REG(0x8c), 23, 21, cmp); | 940 | FINSR(sregs, CML_REG(0x8c), 23, 21, cmp); |
941 | 941 | ||
942 | /* read offsets */ | 942 | /* read offsets */ |
943 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x11); | 943 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x11); |
944 | ofs->cmp = (_kserdes_read_tbus_val(sregs) & 0x0ff0) >> 4; | 944 | ofs->cmp = (_kserdes_read_tbus_val(sregs) & 0x0ff0) >> 4; |
945 | 945 | ||
946 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x11); | 946 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x11); |
947 | ofs->tap1 = (_kserdes_read_tbus_val(sregs) & 0x000f) << 3; | 947 | ofs->tap1 = (_kserdes_read_tbus_val(sregs) & 0x000f) << 3; |
948 | 948 | ||
949 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x12); | 949 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x12); |
950 | ofs->tap1 |= (_kserdes_read_tbus_val(sregs) & 0x0e00) >> 9; | 950 | ofs->tap1 |= (_kserdes_read_tbus_val(sregs) & 0x0e00) >> 9; |
951 | ofs->tap2 = (_kserdes_read_tbus_val(sregs) & 0x01f8) >> 3; | 951 | ofs->tap2 = (_kserdes_read_tbus_val(sregs) & 0x01f8) >> 3; |
952 | ofs->tap3 = (_kserdes_read_tbus_val(sregs) & 0x0007) << 3; | 952 | ofs->tap3 = (_kserdes_read_tbus_val(sregs) & 0x0007) << 3; |
953 | 953 | ||
954 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x13); | 954 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x13); |
955 | ofs->tap3 |= (_kserdes_read_tbus_val(sregs) & 0x0e00) >> 9; | 955 | ofs->tap3 |= (_kserdes_read_tbus_val(sregs) & 0x0e00) >> 9; |
956 | ofs->tap4 = (_kserdes_read_tbus_val(sregs) & 0x01f8) >> 3; | 956 | ofs->tap4 = (_kserdes_read_tbus_val(sregs) & 0x01f8) >> 3; |
957 | ofs->tap5 = (_kserdes_read_tbus_val(sregs) & 0x0007) << 3; | 957 | ofs->tap5 = (_kserdes_read_tbus_val(sregs) & 0x0007) << 3; |
958 | 958 | ||
959 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x14); | 959 | FINSR(sregs, CMU0_REG(0xfc), 26, 16, ((lane + 2) << 8) + 0x14); |
960 | ofs->tap5 |= (_kserdes_read_tbus_val(sregs) & 0x0e00) >> 9; | 960 | ofs->tap5 |= (_kserdes_read_tbus_val(sregs) & 0x0e00) >> 9; |
961 | } | 961 | } |
962 | 962 | ||
963 | static void kserdes_add_offsets_xge(struct kserdes_config *sc, | 963 | static void kserdes_add_offsets_xge(struct kserdes_config *sc, |
964 | struct kserdes_offsets *sofs) | 964 | struct kserdes_offsets *sofs) |
965 | { | 965 | { |
966 | struct kserdes_comparator_tap_ofs *ctofs; | 966 | struct kserdes_cmp_tap_ofs *ctofs; |
967 | struct kserdes_comparator_tap_ofs sample; | 967 | struct kserdes_cmp_tap_ofs sample; |
968 | struct kserdes_lane_offsets *lofs; | 968 | struct kserdes_lane_offsets *lofs; |
969 | u32 lane, cmp; | 969 | u32 lane, cmp; |
970 | 970 | ||
971 | for_each_lane(sc, lane) { | 971 | for_each_lane(sc, lane) { |
972 | lofs = &sofs->lane_ofs[lane]; | 972 | lofs = &sofs->lane_ofs[lane]; |
973 | for_each_comparator(cmp) { | 973 | for_each_comparator(cmp) { |
974 | ctofs = &lofs->ct_ofs[cmp]; | 974 | ctofs = &lofs->ct_ofs[cmp]; |
975 | 975 | ||
976 | _kserdes_get_cmp_tap_offsets_xge(sc->regs, lane, | 976 | _kserdes_get_cmp_tap_offsets_xge(sc->regs, lane, |
977 | cmp, &sample); | 977 | cmp, &sample); |
978 | 978 | ||
979 | ctofs->cmp += sample.cmp; | 979 | ctofs->cmp += sample.cmp; |
980 | ctofs->tap1 += sample.tap1; | 980 | ctofs->tap1 += sample.tap1; |
981 | ctofs->tap2 += sample.tap2; | 981 | ctofs->tap2 += sample.tap2; |
982 | ctofs->tap3 += sample.tap3; | 982 | ctofs->tap3 += sample.tap3; |
983 | ctofs->tap4 += sample.tap4; | 983 | ctofs->tap4 += sample.tap4; |
984 | ctofs->tap5 += sample.tap5; | 984 | ctofs->tap5 += sample.tap5; |
985 | } | 985 | } |
986 | } | 986 | } |
987 | } | 987 | } |
988 | 988 | ||
989 | /* lane is 0-based */ | 989 | /* lane is 0-based */ |
990 | static void | 990 | static void |
991 | kserdes_get_cmp_tap_offsets_non_xge(void __iomem *sregs, u32 lane, u32 cmp, | 991 | kserdes_get_cmp_tap_offsets_non_xge(void __iomem *sregs, u32 lane, u32 cmp, |
992 | struct kserdes_comparator_tap_ofs *ofs) | 992 | struct kserdes_cmp_tap_ofs *ofs) |
993 | { | 993 | { |
994 | /* set comparator number */ | 994 | /* set comparator number */ |
995 | FINSR(sregs, CML_REG(0x8c), 23, 21, cmp); | 995 | FINSR(sregs, CML_REG(0x8c), 23, 21, cmp); |
996 | 996 | ||
997 | /* read offsets */ | 997 | /* read offsets */ |
998 | FINSR(sregs, CMU0_REG(0x8), 31, 24, ((lane + 1) << 5) + 0x12); | 998 | FINSR(sregs, CMU0_REG(0x8), 31, 24, ((lane + 1) << 5) + 0x12); |
999 | ofs->cmp = (_kserdes_read_tbus_val(sregs) & 0x0ff0) >> 4; | 999 | ofs->cmp = (_kserdes_read_tbus_val(sregs) & 0x0ff0) >> 4; |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | static void kserdes_add_offsets_non_xge(struct kserdes_config *sc, | 1002 | static void kserdes_add_offsets_non_xge(struct kserdes_config *sc, |
1003 | struct kserdes_offsets *sofs) | 1003 | struct kserdes_offsets *sofs) |
1004 | { | 1004 | { |
1005 | struct kserdes_comparator_tap_ofs *ctofs; | 1005 | struct kserdes_cmp_tap_ofs *ctofs; |
1006 | struct kserdes_comparator_tap_ofs sample; | 1006 | struct kserdes_cmp_tap_ofs sample; |
1007 | struct kserdes_lane_offsets *lofs; | 1007 | struct kserdes_lane_offsets *lofs; |
1008 | u32 lane, cmp; | 1008 | u32 lane, cmp; |
1009 | 1009 | ||
1010 | for_each_lane(sc, lane) { | 1010 | for_each_lane(sc, lane) { |
1011 | lofs = &sofs->lane_ofs[lane]; | 1011 | lofs = &sofs->lane_ofs[lane]; |
1012 | for_each_comparator(cmp) { | 1012 | for_each_comparator(cmp) { |
1013 | ctofs = &lofs->ct_ofs[cmp]; | 1013 | ctofs = &lofs->ct_ofs[cmp]; |
1014 | 1014 | ||
1015 | kserdes_get_cmp_tap_offsets_non_xge(sc->regs, lane, | 1015 | kserdes_get_cmp_tap_offsets_non_xge(sc->regs, lane, |
1016 | cmp, &sample); | 1016 | cmp, &sample); |
1017 | 1017 | ||
1018 | ctofs->cmp += sample.cmp; | 1018 | ctofs->cmp += sample.cmp; |
1019 | } | 1019 | } |
1020 | } | 1020 | } |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | static void kserdes_get_average_offsets(struct kserdes_config *sc, u32 samples, | 1023 | static void kserdes_get_average_offsets(struct kserdes_config *sc, u32 samples, |
1024 | struct kserdes_offsets *sofs) | 1024 | struct kserdes_offsets *sofs) |
1025 | { | 1025 | { |
1026 | struct kserdes_comparator_tap_ofs *ctofs; | 1026 | struct kserdes_cmp_tap_ofs *ctofs; |
1027 | struct kserdes_lane_offsets *lofs; | 1027 | struct kserdes_lane_offsets *lofs; |
1028 | u32 i, lane, cmp; | 1028 | u32 i, lane, cmp; |
1029 | int ret; | 1029 | int ret; |
1030 | 1030 | ||
1031 | memset(sofs, 0, sizeof(*sofs)); | 1031 | memset(sofs, 0, sizeof(*sofs)); |
1032 | 1032 | ||
1033 | for (i = 0; i < samples; i++) { | 1033 | for (i = 0; i < samples; i++) { |
1034 | kserdes_assert_reset(sc); | 1034 | kserdes_assert_reset(sc); |
1035 | ret = kserdes_deassert_reset(sc, 1); | 1035 | ret = kserdes_deassert_reset(sc, 1); |
1036 | if (ret) { | 1036 | if (ret) { |
1037 | dev_err(sc->dev, | 1037 | dev_err(sc->dev, |
1038 | "kserdes_get_average_offsets: reset failed %d\n", | 1038 | "kserdes_get_average_offsets: reset failed %d\n", |
1039 | ret); | 1039 | ret); |
1040 | return; | 1040 | return; |
1041 | } | 1041 | } |
1042 | 1042 | ||
1043 | if (sc->phy_type == KSERDES_PHY_XGE) | 1043 | if (sc->phy_type == KSERDES_PHY_XGE) |
1044 | kserdes_add_offsets_xge(sc, sofs); | 1044 | kserdes_add_offsets_xge(sc, sofs); |
1045 | else | 1045 | else |
1046 | kserdes_add_offsets_non_xge(sc, sofs); | 1046 | kserdes_add_offsets_non_xge(sc, sofs); |
1047 | } | 1047 | } |
1048 | 1048 | ||
1049 | /* take the average */ | 1049 | /* take the average */ |
1050 | for_each_lane(sc, lane) { | 1050 | for_each_lane(sc, lane) { |
1051 | lofs = &sofs->lane_ofs[lane]; | 1051 | lofs = &sofs->lane_ofs[lane]; |
1052 | for_each_comparator(cmp) { | 1052 | for_each_comparator(cmp) { |
1053 | ctofs = &lofs->ct_ofs[cmp]; | 1053 | ctofs = &lofs->ct_ofs[cmp]; |
1054 | if (sc->phy_type == KSERDES_PHY_XGE) { | 1054 | if (sc->phy_type == KSERDES_PHY_XGE) { |
1055 | ctofs->cmp /= samples; | 1055 | ctofs->cmp /= samples; |
1056 | ctofs->tap1 /= samples; | 1056 | ctofs->tap1 /= samples; |
1057 | ctofs->tap2 /= samples; | 1057 | ctofs->tap2 /= samples; |
1058 | ctofs->tap3 /= samples; | 1058 | ctofs->tap3 /= samples; |
1059 | ctofs->tap4 /= samples; | 1059 | ctofs->tap4 /= samples; |
1060 | ctofs->tap5 /= samples; | 1060 | ctofs->tap5 /= samples; |
1061 | } else { | 1061 | } else { |
1062 | ctofs->cmp /= samples; | 1062 | ctofs->cmp /= samples; |
1063 | } | 1063 | } |
1064 | } | 1064 | } |
1065 | } | 1065 | } |
1066 | } | 1066 | } |
1067 | 1067 | ||
1068 | static void | 1068 | static void |
1069 | _kserdes_override_cmp_tap_offsets(void __iomem *sregs, u32 lane, u32 cmp, | 1069 | _kserdes_override_cmp_tap_offsets(void __iomem *sregs, u32 lane, u32 cmp, |
1070 | struct kserdes_comparator_tap_ofs *ofs) | 1070 | struct kserdes_cmp_tap_ofs *ofs) |
1071 | { | 1071 | { |
1072 | FINSR(sregs, CML_REG(0xf0), 27, 26, (lane + 1)); | 1072 | FINSR(sregs, CML_REG(0xf0), 27, 26, (lane + 1)); |
1073 | 1073 | ||
1074 | FINSR(sregs, CML_REG(0x98), 24, 24, 0x1); | 1074 | FINSR(sregs, CML_REG(0x98), 24, 24, 0x1); |
1075 | 1075 | ||
1076 | FINSR(sregs, LANEX_REG(lane, 0x2c), 2, 2, 0x1); | 1076 | FINSR(sregs, LANEX_REG(lane, 0x2c), 2, 2, 0x1); |
1077 | 1077 | ||
1078 | FINSR(sregs, LANEX_REG(lane, 0x30), 7, 5, cmp); | 1078 | FINSR(sregs, LANEX_REG(lane, 0x30), 7, 5, cmp); |
1079 | 1079 | ||
1080 | FINSR(sregs, LANEX_REG(lane, 0x5c), 31, 31, 0x1); | 1080 | FINSR(sregs, LANEX_REG(lane, 0x5c), 31, 31, 0x1); |
1081 | 1081 | ||
1082 | FINSR(sregs, CML_REG(0x9c), 7, 0, ofs->cmp); | 1082 | FINSR(sregs, CML_REG(0x9c), 7, 0, ofs->cmp); |
1083 | FINSR(sregs, LANEX_REG(lane, 0x58), 30, 24, ofs->tap1); | 1083 | FINSR(sregs, LANEX_REG(lane, 0x58), 30, 24, ofs->tap1); |
1084 | FINSR(sregs, LANEX_REG(lane, 0x5c), 5, 0, ofs->tap2); | 1084 | FINSR(sregs, LANEX_REG(lane, 0x5c), 5, 0, ofs->tap2); |
1085 | FINSR(sregs, LANEX_REG(lane, 0x5c), 13, 8, ofs->tap3); | 1085 | FINSR(sregs, LANEX_REG(lane, 0x5c), 13, 8, ofs->tap3); |
1086 | FINSR(sregs, LANEX_REG(lane, 0x5c), 21, 16, ofs->tap4); | 1086 | FINSR(sregs, LANEX_REG(lane, 0x5c), 21, 16, ofs->tap4); |
1087 | FINSR(sregs, LANEX_REG(lane, 0x5c), 29, 24, ofs->tap5); | 1087 | FINSR(sregs, LANEX_REG(lane, 0x5c), 29, 24, ofs->tap5); |
1088 | 1088 | ||
1089 | FINSR(sregs, LANEX_REG(lane, 0x2c), 10, 10, 0x1); | 1089 | FINSR(sregs, LANEX_REG(lane, 0x2c), 10, 10, 0x1); |
1090 | FINSR(sregs, LANEX_REG(lane, 0x2c), 10, 10, 0x0); | 1090 | FINSR(sregs, LANEX_REG(lane, 0x2c), 10, 10, 0x0); |
1091 | 1091 | ||
1092 | FINSR(sregs, CML_REG(0x98), 24, 24, 0x0); | 1092 | FINSR(sregs, CML_REG(0x98), 24, 24, 0x0); |
1093 | FINSR(sregs, LANEX_REG(lane, 0x2c), 2, 2, 0x0); | 1093 | FINSR(sregs, LANEX_REG(lane, 0x2c), 2, 2, 0x0); |
1094 | FINSR(sregs, LANEX_REG(lane, 0x5c), 31, 31, 0x0); | 1094 | FINSR(sregs, LANEX_REG(lane, 0x5c), 31, 31, 0x0); |
1095 | } | 1095 | } |
1096 | 1096 | ||
1097 | static inline void | 1097 | static inline void |
1098 | _kserdes_override_cmp_offset_cdfe(void __iomem *sregs, u32 lane, | 1098 | _kserdes_override_cmp_offset_cdfe(void __iomem *sregs, u32 lane, |
1099 | u32 cmp, u32 cmp_offset) | 1099 | u32 cmp, u32 cmp_offset) |
1100 | { | 1100 | { |
1101 | FINSR(sregs, LANEX_REG(lane, 0x58), 18, 18, 0x1); | 1101 | FINSR(sregs, LANEX_REG(lane, 0x58), 18, 18, 0x1); |
1102 | 1102 | ||
1103 | FINSR(sregs, LANEX_REG(lane, 0x4c), 5, 2, (0x1 << (cmp - 1))); | 1103 | FINSR(sregs, LANEX_REG(lane, 0x4c), 5, 2, (0x1 << (cmp - 1))); |
1104 | FINSR(sregs, LANEX_REG(lane, 0x48), 24, 17, cmp_offset); | 1104 | FINSR(sregs, LANEX_REG(lane, 0x48), 24, 17, cmp_offset); |
1105 | FINSR(sregs, LANEX_REG(lane, 0x48), 29, 29, 0x1); | 1105 | FINSR(sregs, LANEX_REG(lane, 0x48), 29, 29, 0x1); |
1106 | FINSR(sregs, LANEX_REG(lane, 0x48), 29, 29, 0x0); | 1106 | FINSR(sregs, LANEX_REG(lane, 0x48), 29, 29, 0x0); |
1107 | 1107 | ||
1108 | FINSR(sregs, LANEX_REG(lane, 0x58), 18, 18, 0x0); | 1108 | FINSR(sregs, LANEX_REG(lane, 0x58), 18, 18, 0x0); |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | static inline void | 1111 | static inline void |
1112 | _kserdes_override_tap_offset_cdfe(void __iomem *sregs, u32 lane, | 1112 | _kserdes_override_tap_offset_cdfe(void __iomem *sregs, u32 lane, |
1113 | u32 tap, u32 width, u32 tap_offset) | 1113 | u32 tap, u32 width, u32 tap_offset) |
1114 | { | 1114 | { |
1115 | FINSR(sregs, LANEX_REG(lane, 0x58), 23, 19, BIT(tap - 1)); | 1115 | FINSR(sregs, LANEX_REG(lane, 0x58), 23, 19, BIT(tap - 1)); |
1116 | FINSR(sregs, LANEX_REG(lane, 0x48), 17 + (width - 1), 17, tap_offset); | 1116 | FINSR(sregs, LANEX_REG(lane, 0x48), 17 + (width - 1), 17, tap_offset); |
1117 | FINSR(sregs, LANEX_REG(lane, 0x48), 29, 29, 0x1); | 1117 | FINSR(sregs, LANEX_REG(lane, 0x48), 29, 29, 0x1); |
1118 | FINSR(sregs, LANEX_REG(lane, 0x48), 29, 29, 0x0); | 1118 | FINSR(sregs, LANEX_REG(lane, 0x48), 29, 29, 0x0); |
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | static void | 1121 | static void |
1122 | _kserdes_override_cmp_tap_offsets_cdfe(void __iomem *sregs, u32 lane, u32 cmp, | 1122 | _kserdes_override_cmp_tap_offsets_cdfe(void __iomem *sregs, u32 lane, u32 cmp, |
1123 | struct kserdes_comparator_tap_ofs *ofs) | 1123 | struct kserdes_cmp_tap_ofs *ofs) |
1124 | { | 1124 | { |
1125 | FINSR(sregs, LANEX_REG(lane, 0x58), 16, 16, 0x1); | 1125 | FINSR(sregs, LANEX_REG(lane, 0x58), 16, 16, 0x1); |
1126 | FINSR(sregs, LANEX_REG(lane, 0x48), 16, 16, 0x1); | 1126 | FINSR(sregs, LANEX_REG(lane, 0x48), 16, 16, 0x1); |
1127 | 1127 | ||
1128 | _kserdes_override_cmp_offset_cdfe(sregs, lane, cmp, ofs->cmp); | 1128 | _kserdes_override_cmp_offset_cdfe(sregs, lane, cmp, ofs->cmp); |
1129 | 1129 | ||
1130 | FINSR(sregs, LANEX_REG(lane, 0x58), 17, 17, 0x1); | 1130 | FINSR(sregs, LANEX_REG(lane, 0x58), 17, 17, 0x1); |
1131 | 1131 | ||
1132 | _kserdes_override_tap_offset_cdfe(sregs, lane, 1, 7, ofs->tap1); | 1132 | _kserdes_override_tap_offset_cdfe(sregs, lane, 1, 7, ofs->tap1); |
1133 | _kserdes_override_tap_offset_cdfe(sregs, lane, 2, 6, ofs->tap2); | 1133 | _kserdes_override_tap_offset_cdfe(sregs, lane, 2, 6, ofs->tap2); |
1134 | _kserdes_override_tap_offset_cdfe(sregs, lane, 3, 6, ofs->tap3); | 1134 | _kserdes_override_tap_offset_cdfe(sregs, lane, 3, 6, ofs->tap3); |
1135 | _kserdes_override_tap_offset_cdfe(sregs, lane, 4, 6, ofs->tap4); | 1135 | _kserdes_override_tap_offset_cdfe(sregs, lane, 4, 6, ofs->tap4); |
1136 | _kserdes_override_tap_offset_cdfe(sregs, lane, 5, 6, ofs->tap5); | 1136 | _kserdes_override_tap_offset_cdfe(sregs, lane, 5, 6, ofs->tap5); |
1137 | 1137 | ||
1138 | FINSR(sregs, LANEX_REG(lane, 0x58), 16, 16, 0x0); | 1138 | FINSR(sregs, LANEX_REG(lane, 0x58), 16, 16, 0x0); |
1139 | FINSR(sregs, LANEX_REG(lane, 0x48), 16, 16, 0x0); | 1139 | FINSR(sregs, LANEX_REG(lane, 0x48), 16, 16, 0x0); |
1140 | FINSR(sregs, LANEX_REG(lane, 0x58), 18, 18, 0x0); | 1140 | FINSR(sregs, LANEX_REG(lane, 0x58), 18, 18, 0x0); |
1141 | FINSR(sregs, LANEX_REG(lane, 0x58), 17, 17, 0x0); | 1141 | FINSR(sregs, LANEX_REG(lane, 0x58), 17, 17, 0x0); |
1142 | } | 1142 | } |
1143 | 1143 | ||
1144 | static void kserdes_set_offsets_xge(struct kserdes_config *sc, | 1144 | static void kserdes_set_offsets_xge(struct kserdes_config *sc, |
1145 | struct kserdes_offsets *sofs) | 1145 | struct kserdes_offsets *sofs) |
1146 | { | 1146 | { |
1147 | struct kserdes_comparator_tap_ofs *ctofs; | 1147 | struct kserdes_cmp_tap_ofs *ctofs; |
1148 | struct kserdes_lane_offsets *lofs; | 1148 | struct kserdes_lane_offsets *lofs; |
1149 | u32 lane, cmp; | 1149 | u32 lane, cmp; |
1150 | 1150 | ||
1151 | for_each_lane(sc, lane) { | 1151 | for_each_lane(sc, lane) { |
1152 | lofs = &sofs->lane_ofs[lane]; | 1152 | lofs = &sofs->lane_ofs[lane]; |
1153 | for_each_comparator(cmp) { | 1153 | for_each_comparator(cmp) { |
1154 | ctofs = &lofs->ct_ofs[cmp]; | 1154 | ctofs = &lofs->ct_ofs[cmp]; |
1155 | _kserdes_override_cmp_tap_offsets(sc->regs, lane, | 1155 | _kserdes_override_cmp_tap_offsets(sc->regs, lane, |
1156 | cmp, ctofs); | 1156 | cmp, ctofs); |
1157 | _kserdes_override_cmp_tap_offsets_cdfe(sc->regs, lane, | 1157 | _kserdes_override_cmp_tap_offsets_cdfe(sc->regs, lane, |
1158 | cmp, ctofs); | 1158 | cmp, ctofs); |
1159 | } | 1159 | } |
1160 | } | 1160 | } |
1161 | } | 1161 | } |
1162 | 1162 | ||
1163 | static void kserdes_set_offsets_non_xge(struct kserdes_config *sc, | 1163 | static void kserdes_set_offsets_non_xge(struct kserdes_config *sc, |
1164 | struct kserdes_offsets *sofs) | 1164 | struct kserdes_offsets *sofs) |
1165 | { | 1165 | { |
1166 | struct kserdes_comparator_tap_ofs *ctofs; | 1166 | struct kserdes_cmp_tap_ofs *ctofs; |
1167 | struct kserdes_lane_offsets *lofs; | 1167 | struct kserdes_lane_offsets *lofs; |
1168 | u32 lane, cmp; | 1168 | u32 lane, cmp; |
1169 | 1169 | ||
1170 | for_each_lane(sc, lane) { | 1170 | for_each_lane(sc, lane) { |
1171 | lofs = &sofs->lane_ofs[lane]; | 1171 | lofs = &sofs->lane_ofs[lane]; |
1172 | for_each_comparator(cmp) { | 1172 | for_each_comparator(cmp) { |
1173 | ctofs = &lofs->ct_ofs[cmp]; | 1173 | ctofs = &lofs->ct_ofs[cmp]; |
1174 | _kserdes_override_cmp_tap_offsets(sc->regs, lane, | 1174 | _kserdes_override_cmp_tap_offsets(sc->regs, lane, |
1175 | cmp, ctofs); | 1175 | cmp, ctofs); |
1176 | } | 1176 | } |
1177 | } | 1177 | } |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | static void kserdes_set_offsets(struct kserdes_config *sc, | 1180 | static void kserdes_set_offsets(struct kserdes_config *sc, |
1181 | struct kserdes_offsets *sofs) | 1181 | struct kserdes_offsets *sofs) |
1182 | { | 1182 | { |
1183 | if (sc->phy_type == KSERDES_PHY_XGE) | 1183 | if (sc->phy_type == KSERDES_PHY_XGE) |
1184 | kserdes_set_offsets_xge(sc, sofs); | 1184 | kserdes_set_offsets_xge(sc, sofs); |
1185 | else | 1185 | else |
1186 | kserdes_set_offsets_non_xge(sc, sofs); | 1186 | kserdes_set_offsets_non_xge(sc, sofs); |
1187 | } | 1187 | } |
1188 | 1188 | ||
1189 | static void kserdes_dfe_offset_calibration(struct kserdes_config *sc, | 1189 | static void kserdes_dfe_offset_calibration(struct kserdes_config *sc, |
1190 | struct kserdes_offsets *sofs) | 1190 | struct kserdes_offsets *sofs) |
1191 | { | 1191 | { |
1192 | int lane; | 1192 | int lane; |
1193 | 1193 | ||
1194 | for_each_enable_lane(sc, lane) | 1194 | for_each_enable_lane(sc, lane) |
1195 | kserdes_force_signal_detect_low(sc, lane); | 1195 | kserdes_force_signal_detect_low(sc, lane); |
1196 | 1196 | ||
1197 | /* amount of time to sleep is by experiment */ | 1197 | /* amount of time to sleep is by experiment */ |
1198 | usleep_range(10, 20); | 1198 | usleep_range(10, 20); |
1199 | 1199 | ||
1200 | /* Get offset */ | 1200 | /* Get offset */ |
1201 | kserdes_get_average_offsets(sc, DFE_OFFSET_SAMPLES, sofs); | 1201 | kserdes_get_average_offsets(sc, OFFSET_SAMPLES, sofs); |
1202 | kserdes_set_offsets(sc, sofs); | 1202 | kserdes_set_offsets(sc, sofs); |
1203 | /* amount of time to sleep is by experiment */ | 1203 | /* amount of time to sleep is by experiment */ |
1204 | usleep_range(10, 20); | 1204 | usleep_range(10, 20); |
1205 | 1205 | ||
1206 | /* re-acquire signal detect */ | 1206 | /* re-acquire signal detect */ |
1207 | for_each_lane(sc, lane) | 1207 | for_each_lane(sc, lane) |
1208 | kserdes_force_signal_detect_high(sc, lane); | 1208 | kserdes_force_signal_detect_high(sc, lane); |
1209 | 1209 | ||
1210 | /* amount of time to sleep is by experiment */ | 1210 | /* amount of time to sleep is by experiment */ |
1211 | usleep_range(10, 20); | 1211 | usleep_range(10, 20); |
1212 | } | 1212 | } |
1213 | 1213 | ||
1214 | static int kserdes_wait_lane_rx_valid(struct kserdes_config *sc, u32 lane) | 1214 | static int kserdes_wait_lane_rx_valid(struct kserdes_config *sc, u32 lane) |
1215 | { | 1215 | { |
1216 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | 1216 | unsigned long timeout = jiffies + msecs_to_jiffies(500); |
1217 | unsigned long time_check; | 1217 | unsigned long time_check; |
1218 | u32 status; | 1218 | u32 status; |
1219 | 1219 | ||
1220 | do { | 1220 | do { |
1221 | time_check = jiffies; | 1221 | time_check = jiffies; |
1222 | status = _kserdes_read_select_tbus(sc->regs, lane + 1, 0x02); | 1222 | status = _kserdes_read_select_tbus(sc->regs, lane + 1, 0x02); |
1223 | 1223 | ||
1224 | if (status & 0x20) | 1224 | if (status & 0x20) |
1225 | return 0; | 1225 | return 0; |
1226 | 1226 | ||
1227 | if (time_after(time_check, timeout)) | 1227 | if (time_after(time_check, timeout)) |
1228 | return -ETIMEDOUT; | 1228 | return -ETIMEDOUT; |
1229 | 1229 | ||
1230 | cpu_relax(); | 1230 | cpu_relax(); |
1231 | } while (true); | 1231 | } while (true); |
1232 | } | 1232 | } |
1233 | 1233 | ||
1234 | static int kserdes_att_boost_phya_macro_patch(struct kserdes_config *sc) | 1234 | static int kserdes_att_boost_phya_macro_patch(struct kserdes_config *sc) |
1235 | { | 1235 | { |
1236 | u32 i, att_read[KSERDES_MAX_LANES], att_start[KSERDES_MAX_LANES]; | 1236 | u32 i, att_read[KSERDES_MAX_LANES], att_start[KSERDES_MAX_LANES]; |
1237 | int ret; | 1237 | int ret; |
1238 | 1238 | ||
1239 | /* First read initial att start value */ | 1239 | /* First read initial att start value */ |
1240 | for_each_lane(sc, i) { | 1240 | for_each_lane(sc, i) { |
1241 | att_start[i] = kserdes_readl(sc->regs, LANEX_REG(i, 0x8c)); | 1241 | att_start[i] = kserdes_readl(sc->regs, LANEX_REG(i, 0x8c)); |
1242 | att_start[i] = (att_start[i] >> 8) & 0xf; | 1242 | att_start[i] = (att_start[i] >> 8) & 0xf; |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | for_each_lane(sc, i) { | 1245 | for_each_lane(sc, i) { |
1246 | att_read[i] = _kserdes_read_select_tbus( | 1246 | att_read[i] = _kserdes_read_select_tbus( |
1247 | sc->regs, i + 1, | 1247 | sc->regs, i + 1, |
1248 | (sc->phy_type == KSERDES_PHY_XGE) ? | 1248 | (sc->phy_type == KSERDES_PHY_XGE) ? |
1249 | 0x10 : 0x11); | 1249 | 0x10 : 0x11); |
1250 | att_read[i] = (att_read[i] >> 4) & 0xf; | 1250 | att_read[i] = (att_read[i] >> 4) & 0xf; |
1251 | } | 1251 | } |
1252 | 1252 | ||
1253 | for_each_lane(sc, i) { | 1253 | for_each_lane(sc, i) { |
1254 | FINSR(sc->regs, LANEX_REG(i, 0x8c), 11, 8, att_read[i]); | 1254 | FINSR(sc->regs, LANEX_REG(i, 0x8c), 11, 8, att_read[i]); |
1255 | } | 1255 | } |
1256 | 1256 | ||
1257 | FINSR(sc->regs, CML_REG(0x84), 0, 0, 0x0); | 1257 | FINSR(sc->regs, CML_REG(0x84), 0, 0, 0x0); |
1258 | FINSR(sc->regs, CML_REG(0x8c), 24, 24, 0x0); | 1258 | FINSR(sc->regs, CML_REG(0x8c), 24, 24, 0x0); |
1259 | 1259 | ||
1260 | FINSR(sc->regs, CML_REG(0x98), 7, 7, 0x1); | 1260 | FINSR(sc->regs, CML_REG(0x98), 7, 7, 0x1); |
1261 | FINSR(sc->regs, CML_REG(0x98), 7, 7, 0x0); | 1261 | FINSR(sc->regs, CML_REG(0x98), 7, 7, 0x0); |
1262 | usleep_range(300, 400); | 1262 | usleep_range(300, 400); |
1263 | 1263 | ||
1264 | for_each_enable_lane(sc, i) { | 1264 | for_each_enable_lane(sc, i) { |
1265 | ret = kserdes_wait_lane_rx_valid(sc, i); | 1265 | ret = kserdes_wait_lane_rx_valid(sc, i); |
1266 | if (ret) { | 1266 | if (ret) { |
1267 | dev_err(sc->dev, "lane %d wait rx valid failed: %d\n", | 1267 | dev_err(sc->dev, "lane %d wait rx valid failed: %d\n", |
1268 | i, ret); | 1268 | i, ret); |
1269 | return ret; | 1269 | return ret; |
1270 | } | 1270 | } |
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | /* write back initial att start value */ | 1273 | /* write back initial att start value */ |
1274 | for_each_lane(sc, i) | 1274 | for_each_lane(sc, i) |
1275 | FINSR(sc->regs, LANEX_REG(i, 0x8c), 11, 8, att_start[i]); | 1275 | FINSR(sc->regs, LANEX_REG(i, 0x8c), 11, 8, att_start[i]); |
1276 | 1276 | ||
1277 | FINSR(sc->regs, CML_REG(0x84), 0, 0, 0x1); | 1277 | FINSR(sc->regs, CML_REG(0x84), 0, 0, 0x1); |
1278 | FINSR(sc->regs, CML_REG(0x8c), 24, 24, 0x1); | 1278 | FINSR(sc->regs, CML_REG(0x8c), 24, 24, 0x1); |
1279 | 1279 | ||
1280 | return 0; | 1280 | return 0; |
1281 | } | 1281 | } |
1282 | 1282 | ||
1283 | static int kserdes_att_boost_phya_lane_patch(struct kserdes_config *sc, | 1283 | static int kserdes_att_boost_phya_lane_patch(struct kserdes_config *sc, |
1284 | u32 lane) | 1284 | u32 lane) |
1285 | { | 1285 | { |
1286 | u32 boost_read; | 1286 | u32 boost_read; |
1287 | int ret; | 1287 | int ret; |
1288 | 1288 | ||
1289 | /* check lane rx valid */ | 1289 | /* check lane rx valid */ |
1290 | ret = kserdes_wait_lane_rx_valid(sc, lane); | 1290 | ret = kserdes_wait_lane_rx_valid(sc, lane); |
1291 | if (ret) { | 1291 | if (ret) { |
1292 | dev_err(sc->dev, "lane %d wait rx valid failed: %d\n", | 1292 | dev_err(sc->dev, "lane %d wait rx valid failed: %d\n", |
1293 | lane, ret); | 1293 | lane, ret); |
1294 | return ret; | 1294 | return ret; |
1295 | } | 1295 | } |
1296 | 1296 | ||
1297 | /* check boost value */ | 1297 | /* check boost value */ |
1298 | boost_read = _kserdes_read_select_tbus( | 1298 | boost_read = _kserdes_read_select_tbus( |
1299 | sc->regs, lane + 1, | 1299 | sc->regs, lane + 1, |
1300 | (sc->phy_type == KSERDES_PHY_XGE) ? | 1300 | (sc->phy_type == KSERDES_PHY_XGE) ? |
1301 | 0x10 : 0x11); | 1301 | 0x10 : 0x11); |
1302 | boost_read = (boost_read >> 8) & 0xf; | 1302 | boost_read = (boost_read >> 8) & 0xf; |
1303 | 1303 | ||
1304 | /* if boost = 0, increment by 1 */ | 1304 | /* if boost = 0, increment by 1 */ |
1305 | if (!boost_read) { | 1305 | if (!boost_read) { |
1306 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 2, 2, 0x1); | 1306 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 2, 2, 0x1); |
1307 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 18, 12, 0x2); | 1307 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 18, 12, 0x2); |
1308 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 9, 3, 0x1); | 1308 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 9, 3, 0x1); |
1309 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 10, 10, 0x1); | 1309 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 10, 10, 0x1); |
1310 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 10, 10, 0x0); | 1310 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 10, 10, 0x0); |
1311 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 2, 2, 0x0); | 1311 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 2, 2, 0x0); |
1312 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 18, 12, 0x0); | 1312 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 18, 12, 0x0); |
1313 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 9, 3, 0x0); | 1313 | FINSR(sc->regs, LANEX_REG(lane, 0x2c), 9, 3, 0x0); |
1314 | } | 1314 | } |
1315 | return 0; | 1315 | return 0; |
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | static inline void kserdes_att_boost_phya_patch(struct kserdes_config *sc) | 1318 | static inline void kserdes_att_boost_phya_patch(struct kserdes_config *sc) |
1319 | { | 1319 | { |
1320 | int lane; | 1320 | int lane; |
1321 | 1321 | ||
1322 | kserdes_att_boost_phya_macro_patch(sc); | 1322 | kserdes_att_boost_phya_macro_patch(sc); |
1323 | 1323 | ||
1324 | for_each_enable_lane(sc, lane) | 1324 | for_each_enable_lane(sc, lane) |
1325 | kserdes_att_boost_phya_lane_patch(sc, lane); | 1325 | kserdes_att_boost_phya_lane_patch(sc, lane); |
1326 | } | 1326 | } |
1327 | 1327 | ||
1328 | static void kserdes_att_boost_phyb_lane_patch(struct kserdes_config *sc, | 1328 | static void kserdes_att_boost_phyb_lane_patch(struct kserdes_config *sc, |
1329 | u32 lane) | 1329 | u32 lane) |
1330 | { | 1330 | { |
1331 | u32 tbus_ofs, rxeq_init_reg_ofs, rxeq_ln_reg_ofs, rxeq_ln_force_bit; | 1331 | u32 tbus_ofs, rxeq_init_reg_ofs, rxeq_ln_reg_ofs, rxeq_ln_force_bit; |
1332 | void __iomem *sregs = sc->regs; | 1332 | void __iomem *sregs = sc->regs; |
1333 | u32 att_start, att_read, boost_read; | 1333 | u32 att_start, att_read, boost_read; |
1334 | int ret; | 1334 | int ret; |
1335 | 1335 | ||
1336 | /* some setups */ | 1336 | /* some setups */ |
1337 | if (sc->phy_type == KSERDES_PHY_XGE) { | 1337 | if (sc->phy_type == KSERDES_PHY_XGE) { |
1338 | tbus_ofs = 0x10; | 1338 | tbus_ofs = 0x10; |
1339 | rxeq_init_reg_ofs = 0x9c; | 1339 | rxeq_init_reg_ofs = 0x9c; |
1340 | rxeq_ln_reg_ofs = 0x98; | 1340 | rxeq_ln_reg_ofs = 0x98; |
1341 | rxeq_ln_force_bit = 14; | 1341 | rxeq_ln_force_bit = 14; |
1342 | } else { | 1342 | } else { |
1343 | tbus_ofs = 0x11; | 1343 | tbus_ofs = 0x11; |
1344 | rxeq_init_reg_ofs = 0x84; | 1344 | rxeq_init_reg_ofs = 0x84; |
1345 | rxeq_ln_reg_ofs = 0xac; | 1345 | rxeq_ln_reg_ofs = 0xac; |
1346 | rxeq_ln_force_bit = 11; | 1346 | rxeq_ln_force_bit = 11; |
1347 | } | 1347 | } |
1348 | 1348 | ||
1349 | /* First save a copy of initial att start value */ | 1349 | /* First save a copy of initial att start value */ |
1350 | att_start = kserdes_readl(sregs, LANEX_REG(lane, 0x8c)); | 1350 | att_start = kserdes_readl(sregs, LANEX_REG(lane, 0x8c)); |
1351 | att_start = (att_start >> 8) & 0xf; | 1351 | att_start = (att_start >> 8) & 0xf; |
1352 | 1352 | ||
1353 | att_read = _kserdes_read_select_tbus(sregs, lane + 1, tbus_ofs); | 1353 | att_read = _kserdes_read_select_tbus(sregs, lane + 1, tbus_ofs); |
1354 | att_read = (att_read >> 4) & 0xf; | 1354 | att_read = (att_read >> 4) & 0xf; |
1355 | 1355 | ||
1356 | FINSR(sregs, LANEX_REG(lane, 0x8c), 11, 8, att_read); | 1356 | FINSR(sregs, LANEX_REG(lane, 0x8c), 11, 8, att_read); |
1357 | FINSR(sregs, LANEX_REG(lane, rxeq_init_reg_ofs), 0, 0, 0x0); | 1357 | FINSR(sregs, LANEX_REG(lane, rxeq_init_reg_ofs), 0, 0, 0x0); |
1358 | FINSR(sregs, CML_REG(0x8c), 24, 24, 0x0); | 1358 | FINSR(sregs, CML_REG(0x8c), 24, 24, 0x0); |
1359 | 1359 | ||
1360 | FINSR(sregs, LANEX_REG(lane, rxeq_ln_reg_ofs), | 1360 | FINSR(sregs, LANEX_REG(lane, rxeq_ln_reg_ofs), |
1361 | rxeq_ln_force_bit, rxeq_ln_force_bit, 0x1); | 1361 | rxeq_ln_force_bit, rxeq_ln_force_bit, 0x1); |
1362 | FINSR(sregs, LANEX_REG(lane, rxeq_ln_reg_ofs), | 1362 | FINSR(sregs, LANEX_REG(lane, rxeq_ln_reg_ofs), |
1363 | rxeq_ln_force_bit, rxeq_ln_force_bit, 0x0); | 1363 | rxeq_ln_force_bit, rxeq_ln_force_bit, 0x0); |
1364 | 1364 | ||
1365 | /* check lane rx valid */ | 1365 | /* check lane rx valid */ |
1366 | ret = kserdes_wait_lane_rx_valid(sc, lane); | 1366 | ret = kserdes_wait_lane_rx_valid(sc, lane); |
1367 | if (ret) { | 1367 | if (ret) { |
1368 | dev_err(sc->dev, "lane %d wait rx valid failed: %d\n", | 1368 | dev_err(sc->dev, "lane %d wait rx valid failed: %d\n", |
1369 | lane, ret); | 1369 | lane, ret); |
1370 | } | 1370 | } |
1371 | /* amount of time to sleep is by experiment */ | 1371 | /* amount of time to sleep is by experiment */ |
1372 | usleep_range(300, 400); | 1372 | usleep_range(300, 400); |
1373 | 1373 | ||
1374 | /* check boost value */ | 1374 | /* check boost value */ |
1375 | boost_read = _kserdes_read_select_tbus(sregs, lane + 1, tbus_ofs); | 1375 | boost_read = _kserdes_read_select_tbus(sregs, lane + 1, tbus_ofs); |
1376 | boost_read = (boost_read >> 8) & 0xf; | 1376 | boost_read = (boost_read >> 8) & 0xf; |
1377 | 1377 | ||
1378 | /* increment boost by 1 if it's 0 */ | 1378 | /* increment boost by 1 if it's 0 */ |
1379 | if (!boost_read) { | 1379 | if (!boost_read) { |
1380 | FINSR(sregs, LANEX_REG(lane, 0x2c), 2, 2, 0x1); | 1380 | FINSR(sregs, LANEX_REG(lane, 0x2c), 2, 2, 0x1); |
1381 | FINSR(sregs, LANEX_REG(lane, 0x2c), 18, 12, 0x2); | 1381 | FINSR(sregs, LANEX_REG(lane, 0x2c), 18, 12, 0x2); |
1382 | FINSR(sregs, LANEX_REG(lane, 0x2c), 9, 3, 0x1); | 1382 | FINSR(sregs, LANEX_REG(lane, 0x2c), 9, 3, 0x1); |
1383 | FINSR(sregs, LANEX_REG(lane, 0x2c), 10, 10, 0x1); | 1383 | FINSR(sregs, LANEX_REG(lane, 0x2c), 10, 10, 0x1); |
1384 | FINSR(sregs, LANEX_REG(lane, 0x2c), 10, 10, 0x0); | 1384 | FINSR(sregs, LANEX_REG(lane, 0x2c), 10, 10, 0x0); |
1385 | FINSR(sregs, LANEX_REG(lane, 0x2c), 2, 2, 0x0); | 1385 | FINSR(sregs, LANEX_REG(lane, 0x2c), 2, 2, 0x0); |
1386 | FINSR(sregs, LANEX_REG(lane, 0x2c), 18, 12, 0x0); | 1386 | FINSR(sregs, LANEX_REG(lane, 0x2c), 18, 12, 0x0); |
1387 | FINSR(sregs, LANEX_REG(lane, 0x2c), 9, 3, 0x0); | 1387 | FINSR(sregs, LANEX_REG(lane, 0x2c), 9, 3, 0x0); |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | FINSR(sregs, LANEX_REG(lane, 0x8c), 11, 8, att_start); | 1390 | FINSR(sregs, LANEX_REG(lane, 0x8c), 11, 8, att_start); |
1391 | FINSR(sregs, LANEX_REG(lane, rxeq_init_reg_ofs), 0, 0, 0x1); | 1391 | FINSR(sregs, LANEX_REG(lane, rxeq_init_reg_ofs), 0, 0, 0x1); |
1392 | FINSR(sregs, CML_REG(0x8c), 24, 24, 0x1); | 1392 | FINSR(sregs, CML_REG(0x8c), 24, 24, 0x1); |
1393 | } | 1393 | } |
1394 | 1394 | ||
1395 | static void kserdes_att_boost_phy_patch(struct kserdes_config *sc) | 1395 | static void kserdes_att_boost_phy_patch(struct kserdes_config *sc) |
1396 | { | 1396 | { |
1397 | int lane; | 1397 | int lane; |
1398 | 1398 | ||
1399 | if (sc->phy_type != KSERDES_PHY_XGE) { | 1399 | if (sc->phy_type != KSERDES_PHY_XGE) { |
1400 | kserdes_att_boost_phya_patch(sc); | 1400 | kserdes_att_boost_phya_patch(sc); |
1401 | } else { | 1401 | } else { |
1402 | for_each_lane(sc, lane) | 1402 | for_each_lane(sc, lane) |
1403 | kserdes_att_boost_phyb_lane_patch(sc, lane); | 1403 | kserdes_att_boost_phyb_lane_patch(sc, lane); |
1404 | } | 1404 | } |
1405 | } | 1405 | } |
1406 | 1406 | ||
1407 | static int kserdes_sgmii_lanes_enable(struct kserdes_config *sc) | 1407 | static int kserdes_sgmii_lanes_enable(struct kserdes_config *sc) |
1408 | { | 1408 | { |
1409 | int ret, i; | 1409 | int ret, i; |
1410 | u32 val, lanes_enable = 0; | 1410 | u32 val, lanes_enable = 0; |
1411 | 1411 | ||
1412 | for_each_enable_lane(sc, i) | 1412 | for_each_enable_lane(sc, i) |
1413 | lanes_enable |= (1 << i); | 1413 | lanes_enable |= (1 << i); |
1414 | 1414 | ||
1415 | /* | 1415 | /* |
1416 | * disable transmitter on all lanes to prevent | 1416 | * disable transmitter on all lanes to prevent |
1417 | * receiver from adapting | 1417 | * receiver from adapting |
1418 | */ | 1418 | */ |
1419 | for_each_lane(sc, i) | 1419 | for_each_lane(sc, i) |
1420 | kserdes_set_tx_idle(sc, i); | 1420 | kserdes_set_tx_idle(sc, i); |
1421 | 1421 | ||
1422 | /* apply highspeed config for link rates greater than 8Gbaud */ | 1422 | /* apply highspeed config for link rates greater than 8Gbaud */ |
1423 | kserdes_phy_patch(sc); | 1423 | kserdes_phy_patch(sc); |
1424 | 1424 | ||
1425 | /* assert serdes reset */ | 1425 | /* assert serdes reset */ |
1426 | kserdes_assert_reset(sc); | 1426 | kserdes_assert_reset(sc); |
1427 | 1427 | ||
1428 | /* apply the TX and RX FIR coefficients to the lanes */ | 1428 | /* apply the TX and RX FIR coefficients to the lanes */ |
1429 | for_each_enable_lane(sc, i) | 1429 | for_each_enable_lane(sc, i) |
1430 | kserdes_set_tx_rx_fir_coeff(sc, i); | 1430 | kserdes_set_tx_rx_fir_coeff(sc, i); |
1431 | 1431 | ||
1432 | /* Force Signal Detect Low. This resets the RX */ | 1432 | /* Force Signal Detect Low. This resets the RX */ |
1433 | for_each_enable_lane(sc, i) | 1433 | for_each_enable_lane(sc, i) |
1434 | kserdes_force_signal_detect_low(sc, i); | 1434 | kserdes_force_signal_detect_low(sc, i); |
1435 | 1435 | ||
1436 | ret = kserdes_deassert_reset(sc, 0); | 1436 | ret = kserdes_deassert_reset(sc, 0); |
1437 | if (ret) { | 1437 | if (ret) { |
1438 | dev_err(sc->dev, "kserdes_deassert_reset FAILED %d\n", ret); | 1438 | dev_err(sc->dev, "kserdes_deassert_reset FAILED %d\n", ret); |
1439 | return ret; | 1439 | return ret; |
1440 | } | 1440 | } |
1441 | 1441 | ||
1442 | /* allow signal detect enable */ | 1442 | /* allow signal detect enable */ |
1443 | for_each_enable_lane(sc, i) | 1443 | for_each_enable_lane(sc, i) |
1444 | kserdes_set_lane_rate(sc, i); | 1444 | kserdes_set_lane_rate(sc, i); |
1445 | 1445 | ||
1446 | _kserdes_pll_enable(sc->regs); | 1446 | _kserdes_pll_enable(sc->regs); |
1447 | 1447 | ||
1448 | ret = kserdes_get_status(sc); | 1448 | ret = kserdes_get_status(sc); |
1449 | if (ret) { | 1449 | if (ret) { |
1450 | dev_err(sc->dev, "kserdes_get_status FAILED %d\n", ret); | 1450 | dev_err(sc->dev, "kserdes_get_status FAILED %d\n", ret); |
1451 | return ret; | 1451 | return ret; |
1452 | } | 1452 | } |
1453 | 1453 | ||
1454 | /* Get tx termination */ | 1454 | /* Get tx termination */ |
1455 | val = _kserdes_get_tx_termination(sc->regs, 0, sc->phy_type); | 1455 | val = _kserdes_get_tx_termination(sc->regs, 0, sc->phy_type); |
1456 | 1456 | ||
1457 | /* Apply tx termination */ | 1457 | /* Apply tx termination */ |
1458 | kserdes_set_tx_terminations(sc, val); | 1458 | kserdes_set_tx_terminations(sc, val); |
1459 | 1459 | ||
1460 | /* enable transmitter on all lanes */ | 1460 | /* enable transmitter on all lanes */ |
1461 | for_each_enable_lane(sc, i) | 1461 | for_each_enable_lane(sc, i) |
1462 | kserdes_clr_tx_idle(sc, i); | 1462 | kserdes_clr_tx_idle(sc, i); |
1463 | 1463 | ||
1464 | /* allow Signal Detect Enable */ | 1464 | /* allow Signal Detect Enable */ |
1465 | for_each_enable_lane(sc, i) | 1465 | for_each_enable_lane(sc, i) |
1466 | kserdes_force_signal_detect_high(sc, i); | 1466 | kserdes_force_signal_detect_high(sc, i); |
1467 | 1467 | ||
1468 | /* Wait for RX Valid on all lanes */ | 1468 | /* Wait for RX Valid on all lanes */ |
1469 | for_each_enable_lane(sc, i) { | 1469 | for_each_enable_lane(sc, i) { |
1470 | ret = kserdes_wait_lane_rx_valid(sc, i); | 1470 | ret = kserdes_wait_lane_rx_valid(sc, i); |
1471 | if (ret) { | 1471 | if (ret) { |
1472 | dev_err(sc->dev, "lane %d wait rx valid failed: %d\n", | 1472 | dev_err(sc->dev, "lane %d wait rx valid failed: %d\n", |
1473 | i, ret); | 1473 | i, ret); |
1474 | return ret; | 1474 | return ret; |
1475 | } | 1475 | } |
1476 | } | 1476 | } |
1477 | 1477 | ||
1478 | /* Apply Attenuation and Boost config if rx force flag is set */ | 1478 | /* Apply Attenuation and Boost config if rx force flag is set */ |
1479 | if (!sc->rx_force_enable) | 1479 | if (!sc->rx_force_enable) |
1480 | kserdes_att_boost_phy_patch(sc); | 1480 | kserdes_att_boost_phy_patch(sc); |
1481 | 1481 | ||
1482 | /* Enable MAC RX to allow MAC to take control */ | 1482 | /* Enable MAC RX to allow MAC to take control */ |
1483 | _kserdes_clear_wait_after(sc->regs); | 1483 | _kserdes_clear_wait_after(sc->regs); |
1484 | 1484 | ||
1485 | return lanes_enable; | 1485 | return lanes_enable; |
1486 | } | 1486 | } |
1487 | 1487 | ||
1488 | static int kserdes_sgmii_init(struct kserdes_config *sc) | 1488 | static int kserdes_sgmii_init(struct kserdes_config *sc) |
1489 | { | 1489 | { |
1490 | return kserdes_load_init_fw(sc, ks2_gbe_serdes_firmwares, | 1490 | return kserdes_load_init_fw(sc, ks2_gbe_serdes_firmwares, |
1491 | ARRAY_SIZE(ks2_gbe_serdes_firmwares)); | 1491 | ARRAY_SIZE(ks2_gbe_serdes_firmwares)); |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | static inline void _kserdes_set_link_loss_wait(void __iomem *sregs, | 1494 | static inline void _kserdes_set_link_loss_wait(void __iomem *sregs, |
1495 | u32 link_loss_wait) | 1495 | u32 link_loss_wait) |
1496 | { | 1496 | { |
1497 | kserdes_writel(sregs, LINK_LOSS_WAIT_REG, link_loss_wait); | 1497 | kserdes_writel(sregs, LINK_LOSS_WAIT_REG, link_loss_wait); |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | static inline void _kserdes_reset(void __iomem *sregs) | 1500 | static inline void _kserdes_reset(void __iomem *sregs) |
1501 | { | 1501 | { |
1502 | /* Toggle POR_EN bit */ | 1502 | /* Toggle POR_EN bit */ |
1503 | FINSR(sregs, CPU_CTRL_REG, 29, 29, 0x1); | 1503 | FINSR(sregs, CPU_CTRL_REG, 29, 29, 0x1); |
1504 | /* amount of time to sleep is by experiment */ | 1504 | /* amount of time to sleep is by experiment */ |
1505 | usleep_range(10, 20); | 1505 | usleep_range(10, 20); |
1506 | FINSR(sregs, CPU_CTRL_REG, 29, 29, 0x0); | 1506 | FINSR(sregs, CPU_CTRL_REG, 29, 29, 0x0); |
1507 | /* amount of time to sleep is by experiment */ | 1507 | /* amount of time to sleep is by experiment */ |
1508 | usleep_range(10, 20); | 1508 | usleep_range(10, 20); |
1509 | } | 1509 | } |
1510 | 1510 | ||
1511 | static inline void kserdes_xge_pll_enable(struct kserdes_config *sc) | 1511 | static inline void kserdes_xge_pll_enable(struct kserdes_config *sc) |
1512 | { | 1512 | { |
1513 | /* phyb reset clear */ | 1513 | /* phyb reset clear */ |
1514 | if (!sc->firmware) | 1514 | if (!sc->firmware) |
1515 | FINSR(sc->regs, CML_REG(0), 7, 0, 0x1f); | 1515 | FINSR(sc->regs, CML_REG(0), 7, 0, 0x1f); |
1516 | 1516 | ||
1517 | if (sc->link_rate == KSERDES_LINK_RATE_10P3125G) { | 1517 | if (sc->link_rate == KSERDES_LINK_RATE_10P3125G) { |
1518 | _kserdes_pll_enable(sc->regs); | 1518 | _kserdes_pll_enable(sc->regs); |
1519 | _kserdes_pll2_enable(sc->regs); | 1519 | _kserdes_pll2_enable(sc->regs); |
1520 | } else if (sc->link_rate == KSERDES_LINK_RATE_1P25G) { | 1520 | } else if (sc->link_rate == KSERDES_LINK_RATE_1P25G) { |
1521 | kserdes_writel(sc->regs, PLL_CTRL_REG, PLL_ENABLE_1P25G); | 1521 | kserdes_writel(sc->regs, PLL_CTRL_REG, PLL_ENABLE_1P25G); |
1522 | } | 1522 | } |
1523 | } | 1523 | } |
1524 | 1524 | ||
1525 | static inline void _kserdes_xge_enable_pcs(void __iomem *sregs, u32 lane) | 1525 | static inline void _kserdes_xge_enable_pcs(void __iomem *sregs, u32 lane) |
1526 | { | 1526 | { |
1527 | /* set bus-width to 16 bit mode */ | 1527 | /* set bus-width to 16 bit mode */ |
1528 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 23, 21, 0x7); | 1528 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 23, 21, 0x7); |
1529 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 5, 3, 0x7); | 1529 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 5, 3, 0x7); |
1530 | 1530 | ||
1531 | /* enable PCS overlay and lane select 10GKR */ | 1531 | /* enable PCS overlay and lane select 10GKR */ |
1532 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 16, 16, 0x1); | 1532 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 16, 16, 0x1); |
1533 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 19, 19, 0x1); | 1533 | FINSR(sregs, LANE_CTRL_STS_REG(lane), 19, 19, 0x1); |
1534 | } | 1534 | } |
1535 | 1535 | ||
1536 | static inline void kserdes_xge_lane_enable(struct kserdes_config *sc, u32 lane) | 1536 | static inline void kserdes_xge_lane_enable(struct kserdes_config *sc, u32 lane) |
1537 | { | 1537 | { |
1538 | u32 lane_ctrl_rate = sc->lane[lane].ctrl_rate; | 1538 | u32 lane_ctrl_rate = sc->lane[lane].ctrl_rate; |
1539 | 1539 | ||
1540 | /* Set Lane Control Rate */ | 1540 | /* Set Lane Control Rate */ |
1541 | if (sc->link_rate == KSERDES_LINK_RATE_10P3125G) | 1541 | if (sc->link_rate == KSERDES_LINK_RATE_10P3125G) |
1542 | _kserdes_set_lane_ctrl_rate(sc->regs, lane, lane_ctrl_rate); | 1542 | _kserdes_set_lane_ctrl_rate(sc->regs, lane, lane_ctrl_rate); |
1543 | else if (sc->link_rate == KSERDES_LINK_RATE_1P25G) | 1543 | else if (sc->link_rate == KSERDES_LINK_RATE_1P25G) |
1544 | kserdes_writel(sc->regs, LANE_CTRL_STS_REG(lane), | 1544 | kserdes_writel(sc->regs, LANE_CTRL_STS_REG(lane), |
1545 | LANE_CTRL_1P25G); | 1545 | LANE_CTRL_1P25G); |
1546 | 1546 | ||
1547 | _kserdes_xge_enable_pcs(sc->regs, lane); | 1547 | _kserdes_xge_enable_pcs(sc->regs, lane); |
1548 | 1548 | ||
1549 | _kserdes_lane_enable(sc->regs, lane); | 1549 | _kserdes_lane_enable(sc->regs, lane); |
1550 | 1550 | ||
1551 | if (sc->lane[lane].loopback) | 1551 | if (sc->lane[lane].loopback) |
1552 | _kserdes_set_lane_loopback(sc->regs, lane, sc->link_rate); | 1552 | _kserdes_set_lane_loopback(sc->regs, lane, sc->link_rate); |
1553 | } | 1553 | } |
1554 | 1554 | ||
1555 | static inline void _kserdes_enable_xgmii_port(struct regmap *peripheral_regmap, | 1555 | static inline void _kserdes_enable_xgmii_port(struct regmap *peripheral_regmap, |
1556 | u32 port) | 1556 | u32 port) |
1557 | { | 1557 | { |
1558 | regmap_update_bits(peripheral_regmap, XGE_CTRL_OFFSET, | 1558 | regmap_update_bits(peripheral_regmap, XGE_CTRL_OFFSET, |
1559 | GENMASK(port, port), BIT(port)); | 1559 | GENMASK(port, port), BIT(port)); |
1560 | } | 1560 | } |
1561 | 1561 | ||
1562 | static inline void _kserdes_reset_cdr(void __iomem *sregs, int lane) | 1562 | static inline void _kserdes_reset_cdr(void __iomem *sregs, int lane) |
1563 | { | 1563 | { |
1564 | /* toggle signal detect */ | 1564 | /* toggle signal detect */ |
1565 | _kserdes_force_signal_detect_low(sregs, lane); | 1565 | _kserdes_force_signal_detect_low(sregs, lane); |
1566 | /* amount of time to sleep is by experiment */ | 1566 | /* amount of time to sleep is by experiment */ |
1567 | usleep_range(1000, 2000); | 1567 | usleep_range(1000, 2000); |
1568 | _kserdes_force_signal_detect_high(sregs, lane); | 1568 | _kserdes_force_signal_detect_high(sregs, lane); |
1569 | } | 1569 | } |
1570 | 1570 | ||
1571 | /* Call every 10 ms */ | 1571 | /* Call every 10 ms */ |
1572 | static int kserdes_check_link_status(struct kserdes_config *sc, | 1572 | static int kserdes_check_link_status(struct kserdes_config *sc, |
1573 | u32 *current_state, u32 *lanes_up_map) | 1573 | u32 *current_state, u32 *lanes_up_map) |
1574 | { | 1574 | { |
1575 | u32 pcsr_rx_stat, blk_lock, blk_errs; | 1575 | u32 pcsr_rx_stat, blk_lock, blk_errs; |
1576 | int loss, i, status = 1; | 1576 | int loss, i, status = 1; |
1577 | int ret; | 1577 | int ret; |
1578 | 1578 | ||
1579 | for_each_enable_lane(sc, i) { | 1579 | for_each_enable_lane(sc, i) { |
1580 | /* Rx Signal Loss bit in serdes lane control and status reg*/ | 1580 | /* Rx Signal Loss bit in serdes lane control and status reg*/ |
1581 | loss = (kserdes_readl(sc->regs, LANE_CTRL_STS_REG(i))) & 0x01; | 1581 | loss = (kserdes_readl(sc->regs, LANE_CTRL_STS_REG(i))) & 0x01; |
1582 | 1582 | ||
1583 | /* Block Errors and Block Lock bits in PCSR rx status reg */ | 1583 | /* Block Errors and Block Lock bits in PCSR rx status reg */ |
1584 | ret = regmap_read(sc->pcsr_regmap, PCSR_RX_STATUS(i), | 1584 | ret = regmap_read(sc->pcsr_regmap, PCSR_RX_STATUS(i), |
1585 | &pcsr_rx_stat); | 1585 | &pcsr_rx_stat); |
1586 | 1586 | ||
1587 | if (ret) | 1587 | if (ret) |
1588 | return ret; | 1588 | return ret; |
1589 | 1589 | ||
1590 | blk_lock = (pcsr_rx_stat >> 30) & 0x1; | 1590 | blk_lock = (pcsr_rx_stat >> 30) & 0x1; |
1591 | blk_errs = (pcsr_rx_stat >> 16) & 0x0ff; | 1591 | blk_errs = (pcsr_rx_stat >> 16) & 0x0ff; |
1592 | 1592 | ||
1593 | /* If Block error, attempt recovery! */ | 1593 | /* If Block error, attempt recovery! */ |
1594 | if (blk_errs) | 1594 | if (blk_errs) |
1595 | blk_lock = 0; | 1595 | blk_lock = 0; |
1596 | 1596 | ||
1597 | switch (current_state[i]) { | 1597 | switch (current_state[i]) { |
1598 | case 0: | 1598 | case 0: |
1599 | /* if good link lock the signal detect ON! */ | 1599 | /* if good link lock the signal detect ON! */ |
1600 | if (!loss && blk_lock) { | 1600 | if (!loss && blk_lock) { |
1601 | dev_dbg(sc->dev, "XGE PCSR Linked Lane: %d\n", | 1601 | dev_dbg(sc->dev, "XGE PCSR Linked Lane: %d\n", |
1602 | i); | 1602 | i); |
1603 | FINSR(sc->regs, LANEX_REG(i, 0x04), 2, 1, 0x3); | 1603 | FINSR(sc->regs, LANEX_REG(i, 0x04), 2, 1, 0x3); |
1604 | current_state[i] = 1; | 1604 | current_state[i] = 1; |
1605 | } else { | 1605 | } else { |
1606 | /* | 1606 | /* |
1607 | * if no lock, then reset rx | 1607 | * if no lock, then reset rx |
1608 | * by toggling sig detect | 1608 | * by toggling sig detect |
1609 | */ | 1609 | */ |
1610 | if (!blk_lock) { | 1610 | if (!blk_lock) { |
1611 | dev_dbg(sc->dev, | 1611 | dev_dbg(sc->dev, |
1612 | "XGE PCSR Recover Lane: %d\n", | 1612 | "XGE PCSR Recover Lane: %d\n", |
1613 | i); | 1613 | i); |
1614 | 1614 | ||
1615 | _kserdes_reset_cdr(sc->regs, i); | 1615 | _kserdes_reset_cdr(sc->regs, i); |
1616 | } | 1616 | } |
1617 | } | 1617 | } |
1618 | break; | 1618 | break; |
1619 | case 1: | 1619 | case 1: |
1620 | if (!blk_lock) { | 1620 | if (!blk_lock) { |
1621 | /* Link Lost? */ | 1621 | /* Link Lost? */ |
1622 | current_state[i] = 2; | 1622 | current_state[i] = 2; |
1623 | } | 1623 | } |
1624 | break; | 1624 | break; |
1625 | case 2: | 1625 | case 2: |
1626 | if (blk_lock) { | 1626 | if (blk_lock) { |
1627 | /* Nope just noise */ | 1627 | /* Nope just noise */ |
1628 | current_state[i] = 1; | 1628 | current_state[i] = 1; |
1629 | } else { | 1629 | } else { |
1630 | /* | 1630 | /* |
1631 | * Lost the block lock, reset rx | 1631 | * Lost the block lock, reset rx |
1632 | * and go back to sync state | 1632 | * and go back to sync state |
1633 | */ | 1633 | */ |
1634 | _kserdes_reset_cdr(sc->regs, i); | 1634 | _kserdes_reset_cdr(sc->regs, i); |
1635 | current_state[i] = 0; | 1635 | current_state[i] = 0; |
1636 | } | 1636 | } |
1637 | break; | 1637 | break; |
1638 | default: | 1638 | default: |
1639 | dev_info(sc->dev, "XGE: unknown current_state[%d] %d\n", | 1639 | dev_info(sc->dev, "XGE: unknown current_state[%d] %d\n", |
1640 | i, current_state[i]); | 1640 | i, current_state[i]); |
1641 | break; | 1641 | break; |
1642 | } | 1642 | } |
1643 | 1643 | ||
1644 | if (blk_errs) { | 1644 | if (blk_errs) { |
1645 | /* Reset the Error counts! */ | 1645 | /* Reset the Error counts! */ |
1646 | regmap_update_bits(sc->pcsr_regmap, PCSR_RX_CTL(i), | 1646 | regmap_update_bits(sc->pcsr_regmap, PCSR_RX_CTL(i), |
1647 | GENMASK(7, 0), 0x19); | 1647 | GENMASK(7, 0), 0x19); |
1648 | regmap_update_bits(sc->pcsr_regmap, PCSR_RX_CTL(i), | 1648 | regmap_update_bits(sc->pcsr_regmap, PCSR_RX_CTL(i), |
1649 | GENMASK(7, 0), 0x00); | 1649 | GENMASK(7, 0), 0x00); |
1650 | } | 1650 | } |
1651 | 1651 | ||
1652 | if (current_state[i] == 1) { | 1652 | if (current_state[i] == 1) { |
1653 | *lanes_up_map |= BIT(i); | 1653 | *lanes_up_map |= BIT(i); |
1654 | } else { | 1654 | } else { |
1655 | *lanes_up_map &= ~BIT(i); | 1655 | *lanes_up_map &= ~BIT(i); |
1656 | status = 0; | 1656 | status = 0; |
1657 | } | 1657 | } |
1658 | } | 1658 | } |
1659 | 1659 | ||
1660 | return status; | 1660 | return status; |
1661 | } | 1661 | } |
1662 | 1662 | ||
1663 | static int kserdes_wait_link_up(struct kserdes_config *sc, u32 *lanes_up_map) | 1663 | static int kserdes_wait_link_up(struct kserdes_config *sc, u32 *lanes_up_map) |
1664 | { | 1664 | { |
1665 | u32 current_state[KSERDES_MAX_LANES]; | 1665 | u32 current_state[KSERDES_MAX_LANES]; |
1666 | unsigned long timeout, time_check; | 1666 | unsigned long timeout, time_check; |
1667 | int i, link_up, ret = 0; | 1667 | int i, link_up, ret = 0; |
1668 | 1668 | ||
1669 | memset(current_state, 0, sizeof(current_state)); | 1669 | memset(current_state, 0, sizeof(current_state)); |
1670 | timeout = jiffies + 2 * HZ; | 1670 | timeout = jiffies + 2 * HZ; |
1671 | 1671 | ||
1672 | do { | 1672 | do { |
1673 | time_check = jiffies; | 1673 | time_check = jiffies; |
1674 | /* amount of time to sleep is by experiment */ | 1674 | /* amount of time to sleep is by experiment */ |
1675 | usleep_range(10000, 20000); | 1675 | usleep_range(10000, 20000); |
1676 | link_up = kserdes_check_link_status(sc, current_state, | 1676 | link_up = kserdes_check_link_status(sc, current_state, |
1677 | lanes_up_map); | 1677 | lanes_up_map); |
1678 | 1678 | ||
1679 | /* | 1679 | /* |
1680 | * if we did not get link up then wait 100ms | 1680 | * if we did not get link up then wait 100ms |
1681 | * before calling it again | 1681 | * before calling it again |
1682 | */ | 1682 | */ |
1683 | if (link_up) | 1683 | if (link_up) |
1684 | break; | 1684 | break; |
1685 | 1685 | ||
1686 | for_each_enable_lane(sc, i) { | 1686 | for_each_enable_lane(sc, i) { |
1687 | if (!(*lanes_up_map & BIT(i))) { | 1687 | if (!(*lanes_up_map & BIT(i))) { |
1688 | dev_dbg(sc->dev, | 1688 | dev_dbg(sc->dev, |
1689 | "XGE: detected lane %d down\n", i); | 1689 | "XGE: detected lane %d down\n", i); |
1690 | } | 1690 | } |
1691 | } | 1691 | } |
1692 | 1692 | ||
1693 | if (time_after(time_check, timeout)) { | 1693 | if (time_after(time_check, timeout)) { |
1694 | ret = -ETIMEDOUT; | 1694 | ret = -ETIMEDOUT; |
1695 | break; | 1695 | break; |
1696 | } | 1696 | } |
1697 | 1697 | ||
1698 | } while (1); | 1698 | } while (1); |
1699 | 1699 | ||
1700 | return ret; | 1700 | return ret; |
1701 | } | 1701 | } |
1702 | 1702 | ||
1703 | static int kserdes_xge_lanes_enable(struct kserdes_config *sc) | 1703 | static int kserdes_xge_lanes_enable(struct kserdes_config *sc) |
1704 | { | 1704 | { |
1705 | struct kserdes_offsets sofs; | 1705 | struct kserdes_offsets sofs; |
1706 | int ret, i; | 1706 | int ret, i; |
1707 | int lanes_up_map = 0; | 1707 | int lanes_up_map = 0; |
1708 | 1708 | ||
1709 | if (sc->firmware) { | 1709 | if (sc->firmware) { |
1710 | /* | 1710 | /* |
1711 | * firmware started in serdes_init and | 1711 | * firmware started in serdes_init and |
1712 | * doesn't need lanes enable | 1712 | * doesn't need lanes enable |
1713 | */ | 1713 | */ |
1714 | return 0; | 1714 | return 0; |
1715 | } | 1715 | } |
1716 | 1716 | ||
1717 | kserdes_phy_patch(sc); | 1717 | kserdes_phy_patch(sc); |
1718 | kserdes_xge_pll_enable(sc); | 1718 | kserdes_xge_pll_enable(sc); |
1719 | 1719 | ||
1720 | for_each_lane(sc, i) | 1720 | for_each_lane(sc, i) |
1721 | kserdes_xge_lane_enable(sc, i); | 1721 | kserdes_xge_lane_enable(sc, i); |
1722 | 1722 | ||
1723 | ret = kserdes_get_status(sc); | 1723 | ret = kserdes_get_status(sc); |
1724 | if (ret) { | 1724 | if (ret) { |
1725 | dev_err(sc->dev, | 1725 | dev_err(sc->dev, |
1726 | "kserdes_xge_lanes_enable get status FAILED %d\n", ret); | 1726 | "kserdes_xge_lanes_enable get status FAILED %d\n", ret); |
1727 | return ret; | 1727 | return ret; |
1728 | } | 1728 | } |
1729 | 1729 | ||
1730 | kserdes_dfe_offset_calibration(sc, &sofs); | 1730 | kserdes_dfe_offset_calibration(sc, &sofs); |
1731 | 1731 | ||
1732 | for_each_lane(sc, i) | 1732 | for_each_lane(sc, i) |
1733 | _kserdes_enable_xgmii_port(sc->peripheral_regmap, i); | 1733 | _kserdes_enable_xgmii_port(sc->peripheral_regmap, i); |
1734 | 1734 | ||
1735 | kserdes_wait_link_up(sc, &lanes_up_map); | 1735 | kserdes_wait_link_up(sc, &lanes_up_map); |
1736 | 1736 | ||
1737 | return lanes_up_map; | 1737 | return lanes_up_map; |
1738 | } | 1738 | } |
1739 | 1739 | ||
1740 | static inline void kserdes_xfw_get_lane_params(struct kserdes_config *sc, | 1740 | static inline void kserdes_xfw_get_lane_params(struct kserdes_config *sc, |
1741 | int lane) | 1741 | int lane) |
1742 | { | 1742 | { |
1743 | struct kserdes_fw_config *fw = &sc->fw; | 1743 | struct kserdes_fw_config *fw = &sc->fw; |
1744 | u32 tx_ctrl, val_0, val_1; | 1744 | u32 tx_ctrl, val_0, val_1; |
1745 | u32 phy_a = PHY_A(sc->regs); | 1745 | u32 phy_a = PHY_A(sc->regs); |
1746 | 1746 | ||
1747 | val_0 = kserdes_readl(sc->regs, LANEX_REG(lane, 0x04)); | 1747 | val_0 = kserdes_readl(sc->regs, LANEX_REG(lane, 0x04)); |
1748 | val_1 = kserdes_readl(sc->regs, LANEX_REG(lane, 0x08)); | 1748 | val_1 = kserdes_readl(sc->regs, LANEX_REG(lane, 0x08)); |
1749 | 1749 | ||
1750 | tx_ctrl = ((((val_0 >> 18) & 0x1) << 24) | /* TX_CTRL_O_24 */ | 1750 | tx_ctrl = ((((val_0 >> 18) & 0x1) << 24) | /* TX_CTRL_O_24 */ |
1751 | (((val_1 >> 0) & 0xffff) << 8) | /* TX_CTRL_O_23_8 */ | 1751 | (((val_1 >> 0) & 0xffff) << 8) | /* TX_CTRL_O_23_8 */ |
1752 | (((val_0 >> 24) & 0xff) << 0)); /* TX_CTRL_O_7_0 */ | 1752 | (((val_0 >> 24) & 0xff) << 0)); /* TX_CTRL_O_7_0 */ |
1753 | 1753 | ||
1754 | if (phy_a) { | 1754 | if (phy_a) { |
1755 | fw->cm = (val_1 >> 12) & 0xf; | 1755 | fw->cm = (val_1 >> 12) & 0xf; |
1756 | fw->c1 = (val_1 >> 0) & 0x1f; | 1756 | fw->c1 = (val_1 >> 0) & 0x1f; |
1757 | fw->c2 = (val_1 >> 8) & 0xf; | 1757 | fw->c2 = (val_1 >> 8) & 0xf; |
1758 | } else { | 1758 | } else { |
1759 | fw->cm = (tx_ctrl >> 16) & 0xf; | 1759 | fw->cm = (tx_ctrl >> 16) & 0xf; |
1760 | fw->c1 = (tx_ctrl >> 8) & 0x1f; | 1760 | fw->c1 = (tx_ctrl >> 8) & 0x1f; |
1761 | fw->c2 = (tx_ctrl >> 13) & 0x7; | 1761 | fw->c2 = (tx_ctrl >> 13) & 0x7; |
1762 | fw->c2 = fw->c2 | (((tx_ctrl >> 24) & 0x1) << 3); | 1762 | fw->c2 = fw->c2 | (((tx_ctrl >> 24) & 0x1) << 3); |
1763 | } | 1763 | } |
1764 | 1764 | ||
1765 | val_0 = _kserdes_read_select_tbus(sc->regs, lane + 1, | 1765 | val_0 = _kserdes_read_select_tbus(sc->regs, lane + 1, |
1766 | (phy_a ? 0x11 : 0x10)); | 1766 | (phy_a ? 0x11 : 0x10)); |
1767 | fw->attn = (val_0 >> 4) & 0xf; | 1767 | fw->attn = (val_0 >> 4) & 0xf; |
1768 | fw->boost = (val_0 >> 8) & 0xf; | 1768 | fw->boost = (val_0 >> 8) & 0xf; |
1769 | 1769 | ||
1770 | val_0 = _kserdes_read_select_tbus(sc->regs, lane + 1, 0x5); | 1770 | val_0 = _kserdes_read_select_tbus(sc->regs, lane + 1, 0x5); |
1771 | fw->dlpf = (val_0 >> 2) & 0x3ff; | 1771 | fw->dlpf = (val_0 >> 2) & 0x3ff; |
1772 | 1772 | ||
1773 | val_0 = _kserdes_read_select_tbus(sc->regs, lane + 1, 0x6); | 1773 | val_0 = _kserdes_read_select_tbus(sc->regs, lane + 1, 0x6); |
1774 | fw->cdrcal = (val_0 >> 3) & 0xff; | 1774 | fw->rxcal = (val_0 >> 3) & 0xff; |
1775 | } | 1775 | } |
1776 | 1776 | ||
1777 | static inline void kserdes_xfw_mem_init(struct kserdes_config *sc) | 1777 | static inline void kserdes_xfw_mem_init(struct kserdes_config *sc) |
1778 | { | 1778 | { |
1779 | struct kserdes_fw_config *fw = &sc->fw; | 1779 | struct kserdes_fw_config *fw = &sc->fw; |
1780 | u32 i, lane_config = 0; | 1780 | u32 i, lane_config = 0; |
1781 | 1781 | ||
1782 | for_each_lane(sc, i) | 1782 | for_each_lane(sc, i) |
1783 | lane_config = (lane_config << 8) | (fw->lane_config[i] & 0xff); | 1783 | lane_config = (lane_config << 8) | (fw->lane_config[i] & 0xff); |
1784 | 1784 | ||
1785 | lane_config <<= 8; | 1785 | lane_config <<= 8; |
1786 | 1786 | ||
1787 | /* initialize internal parameter area */ | 1787 | /* initialize internal parameter area */ |
1788 | kserdes_writel(sc->regs, MEM_ADR_REG, KSERDES_XFW_CONFIG_START_ADDR); | 1788 | kserdes_writel(sc->regs, MEM_ADR_REG, KSERDES_XFW_CONFIG_START_ADDR); |
1789 | 1789 | ||
1790 | /* clean out unused config area */ | 1790 | /* clean out unused config area */ |
1791 | for (i = KSERDES_XFW_CONFIG_START_ADDR; | 1791 | for (i = KSERDES_XFW_CONFIG_START_ADDR; |
1792 | i < KSERDES_XFW_PARAM_START_ADDR; i += 4) | 1792 | i < KSERDES_XFW_PARAM_START_ADDR; i += 4) |
1793 | kserdes_writel(sc->regs, MEM_DATINC_REG, 0x00000000); | 1793 | kserdes_writel(sc->regs, MEM_DATINC_REG, 0x00000000); |
1794 | 1794 | ||
1795 | /* Flush 64 bytes 10,11,12,13 */ | 1795 | /* Flush 64 bytes 10,11,12,13 */ |
1796 | kserdes_writel(sc->regs, MEM_DATINC_REG, XFM_FLUSH_CMD); | 1796 | kserdes_writel(sc->regs, MEM_DATINC_REG, XFM_FLUSH_CMD); |
1797 | kserdes_writel(sc->regs, MEM_DATINC_REG, fw->fast_train); | 1797 | kserdes_writel(sc->regs, MEM_DATINC_REG, fw->fast_train); |
1798 | kserdes_writel(sc->regs, MEM_DATINC_REG, 0x00000000); | 1798 | kserdes_writel(sc->regs, MEM_DATINC_REG, 0x00000000); |
1799 | kserdes_writel(sc->regs, MEM_DATINC_REG, fw->lane_seeds); | 1799 | kserdes_writel(sc->regs, MEM_DATINC_REG, fw->lane_seeds); |
1800 | kserdes_writel(sc->regs, MEM_DATINC_REG, lane_config); | 1800 | kserdes_writel(sc->regs, MEM_DATINC_REG, lane_config); |
1801 | } | 1801 | } |
1802 | 1802 | ||
1803 | static int kserdes_xge_init(struct kserdes_config *sc) | 1803 | static int kserdes_xge_init(struct kserdes_config *sc) |
1804 | { | 1804 | { |
1805 | return kserdes_load_init_fw(sc, ks2_xgbe_serdes_firmwares, | 1805 | return kserdes_load_init_fw(sc, ks2_xgbe_serdes_firmwares, |
1806 | ARRAY_SIZE(ks2_xgbe_serdes_firmwares)); | 1806 | ARRAY_SIZE(ks2_xgbe_serdes_firmwares)); |
1807 | } | 1807 | } |
1808 | 1808 | ||
1809 | static int kserdes_pcie_lanes_enable(struct kserdes_config *sc) | 1809 | static int kserdes_pcie_lanes_enable(struct kserdes_config *sc) |
1810 | { | 1810 | { |
1811 | int ret, i; | 1811 | int ret, i; |
1812 | u32 lanes_enable = 0; | 1812 | u32 lanes_enable = 0; |
1813 | 1813 | ||
1814 | for_each_enable_lane(sc, i) | 1814 | for_each_enable_lane(sc, i) |
1815 | lanes_enable |= (1 << i); | 1815 | lanes_enable |= (1 << i); |
1816 | 1816 | ||
1817 | for_each_lane(sc, i) { | 1817 | for_each_lane(sc, i) { |
1818 | kserdes_release_reset(sc, i); | 1818 | kserdes_release_reset(sc, i); |
1819 | 1819 | ||
1820 | if (sc->lane[i].loopback) | 1820 | if (sc->lane[i].loopback) |
1821 | _kserdes_set_lane_loopback(sc->regs, i, sc->link_rate); | 1821 | _kserdes_set_lane_loopback(sc->regs, i, sc->link_rate); |
1822 | } | 1822 | } |
1823 | 1823 | ||
1824 | ret = kserdes_get_status(sc); | 1824 | ret = kserdes_get_status(sc); |
1825 | if (ret) | 1825 | if (ret) |
1826 | return ret; | 1826 | return ret; |
1827 | 1827 | ||
1828 | return lanes_enable; | 1828 | return lanes_enable; |
1829 | } | 1829 | } |
1830 | 1830 | ||
1831 | static int kserdes_pcie_init(struct kserdes_config *sc) | 1831 | static int kserdes_pcie_init(struct kserdes_config *sc) |
1832 | { | 1832 | { |
1833 | return kserdes_load_init_fw(sc, ks2_pcie_serdes_firmwares, | 1833 | return kserdes_load_init_fw(sc, ks2_pcie_serdes_firmwares, |
1834 | ARRAY_SIZE(ks2_pcie_serdes_firmwares)); | 1834 | ARRAY_SIZE(ks2_pcie_serdes_firmwares)); |
1835 | } | 1835 | } |
1836 | 1836 | ||
1837 | static int kserdes_lanes_enable(struct kserdes_config *sc) | 1837 | static int kserdes_lanes_enable(struct kserdes_config *sc) |
1838 | { | 1838 | { |
1839 | switch (sc->phy_type) { | 1839 | switch (sc->phy_type) { |
1840 | case KSERDES_PHY_SGMII: | 1840 | case KSERDES_PHY_SGMII: |
1841 | return kserdes_sgmii_lanes_enable(sc); | 1841 | return kserdes_sgmii_lanes_enable(sc); |
1842 | case KSERDES_PHY_XGE: | 1842 | case KSERDES_PHY_XGE: |
1843 | return kserdes_xge_lanes_enable(sc); | 1843 | return kserdes_xge_lanes_enable(sc); |
1844 | case KSERDES_PHY_PCIE: | 1844 | case KSERDES_PHY_PCIE: |
1845 | return kserdes_pcie_lanes_enable(sc); | 1845 | return kserdes_pcie_lanes_enable(sc); |
1846 | default: | 1846 | default: |
1847 | return -EINVAL; | 1847 | return -EINVAL; |
1848 | } | 1848 | } |
1849 | } | 1849 | } |
1850 | 1850 | ||
1851 | static int kserdes_init(struct phy *phy) | 1851 | static int kserdes_init(struct phy *phy) |
1852 | { | 1852 | { |
1853 | struct kserdes_dev *sd = phy_get_drvdata(phy); | 1853 | struct kserdes_dev *sd = phy_get_drvdata(phy); |
1854 | struct kserdes_config *sc = &sd->sc; | 1854 | struct kserdes_config *sc = &sd->sc; |
1855 | int ret; | 1855 | int ret; |
1856 | 1856 | ||
1857 | switch (sc->phy_type) { | 1857 | switch (sc->phy_type) { |
1858 | case KSERDES_PHY_SGMII: | 1858 | case KSERDES_PHY_SGMII: |
1859 | ret = kserdes_sgmii_init(sc); | 1859 | ret = kserdes_sgmii_init(sc); |
1860 | break; | 1860 | break; |
1861 | case KSERDES_PHY_XGE: | 1861 | case KSERDES_PHY_XGE: |
1862 | ret = kserdes_xge_init(sc); | 1862 | ret = kserdes_xge_init(sc); |
1863 | break; | 1863 | break; |
1864 | case KSERDES_PHY_PCIE: | 1864 | case KSERDES_PHY_PCIE: |
1865 | ret = kserdes_pcie_init(sc); | 1865 | ret = kserdes_pcie_init(sc); |
1866 | break; | 1866 | break; |
1867 | default: | 1867 | default: |
1868 | ret = -EINVAL; | 1868 | ret = -EINVAL; |
1869 | } | 1869 | } |
1870 | 1870 | ||
1871 | if (ret < 0) { | 1871 | if (ret < 0) { |
1872 | dev_err(sd->dev, "serdes initialization failed %d\n", ret); | 1872 | dev_err(sd->dev, "serdes initialization failed %d\n", ret); |
1873 | goto done; | 1873 | goto done; |
1874 | } | 1874 | } |
1875 | 1875 | ||
1876 | ret = kserdes_lanes_enable(sc); | 1876 | ret = kserdes_lanes_enable(sc); |
1877 | if (ret < 0) { | 1877 | if (ret < 0) { |
1878 | dev_err(sd->dev, "serdes lanes enable failed: %d\n", ret); | 1878 | dev_err(sd->dev, "serdes lanes enable failed: %d\n", ret); |
1879 | goto done; | 1879 | goto done; |
1880 | } | 1880 | } |
1881 | 1881 | ||
1882 | dev_dbg(sd->dev, "serdes config done lanes(mask) 0x%x\n", ret); | 1882 | dev_dbg(sd->dev, "serdes config done lanes(mask) 0x%x\n", ret); |
1883 | 1883 | ||
1884 | done: | 1884 | done: |
1885 | return ret; | 1885 | return ret; |
1886 | } | 1886 | } |
1887 | 1887 | ||
1888 | static int kserdes_of_parse_lane(struct device *dev, | 1888 | static int kserdes_of_parse_lane(struct device *dev, |
1889 | struct device_node *np, | 1889 | struct device_node *np, |
1890 | struct kserdes_config *sc) | 1890 | struct kserdes_config *sc) |
1891 | { | 1891 | { |
1892 | struct kserdes_lane_config *lc; | 1892 | struct kserdes_lane_config *lc; |
1893 | struct kserdes_equalizer *eq; | 1893 | struct kserdes_equalizer *eq; |
1894 | struct kserdes_tx_coeff *tc; | 1894 | struct kserdes_tx_coeff *tc; |
1895 | int lane_num, ret; | 1895 | int lane_num, ret; |
1896 | 1896 | ||
1897 | ret = of_property_read_u32(np, "reg", &lane_num); | 1897 | ret = of_property_read_u32(np, "reg", &lane_num); |
1898 | if (ret) { | 1898 | if (ret) { |
1899 | dev_err(dev, "Failed to parse reg\n"); | 1899 | dev_err(dev, "Failed to parse reg\n"); |
1900 | return -EINVAL; | 1900 | return -EINVAL; |
1901 | } | 1901 | } |
1902 | 1902 | ||
1903 | if (lane_num >= sc->lanes) { | 1903 | if (lane_num >= sc->lanes) { |
1904 | dev_err(dev, "Invalid lane number %u\n", lane_num); | 1904 | dev_err(dev, "Invalid lane number %u\n", lane_num); |
1905 | return -EINVAL; | 1905 | return -EINVAL; |
1906 | } | 1906 | } |
1907 | 1907 | ||
1908 | lc = &sc->lane[lane_num]; | 1908 | lc = &sc->lane[lane_num]; |
1909 | lc->enable = true; | 1909 | lc->enable = true; |
1910 | dev_dbg(dev, "lane %d enabled\n", lane_num); | 1910 | dev_dbg(dev, "lane %d enabled\n", lane_num); |
1911 | 1911 | ||
1912 | if (of_property_read_u32(np, "control-rate", &lc->ctrl_rate)) { | 1912 | if (of_property_read_u32(np, "control-rate", &lc->ctrl_rate)) { |
1913 | dev_info(dev, "use default lane control-rate: %u\n", | 1913 | dev_info(dev, "use default lane control-rate: %u\n", |
1914 | lc->ctrl_rate); | 1914 | lc->ctrl_rate); |
1915 | } | 1915 | } |
1916 | dev_dbg(dev, "lane control-rate: %d\n", lc->ctrl_rate); | 1916 | dev_dbg(dev, "lane control-rate: %d\n", lc->ctrl_rate); |
1917 | 1917 | ||
1918 | if (of_find_property(np, "loopback", NULL)) | 1918 | if (of_find_property(np, "loopback", NULL)) |
1919 | lc->loopback = true; | 1919 | lc->loopback = true; |
1920 | else | 1920 | else |
1921 | lc->loopback = false; | 1921 | lc->loopback = false; |
1922 | 1922 | ||
1923 | dev_dbg(dev, "lane loopback: %d\n", lc->loopback); | 1923 | dev_dbg(dev, "lane loopback: %d\n", lc->loopback); |
1924 | 1924 | ||
1925 | eq = &lc->rx_start; | 1925 | eq = &lc->rx_start; |
1926 | if (of_property_read_u32_array(np, "rx-start", &eq->att, 2)) { | 1926 | if (of_property_read_u32_array(np, "rx-start", &eq->att, 2)) { |
1927 | dev_info(dev, "use default lane rx-start 0 0\n"); | 1927 | dev_info(dev, "use default lane rx-start 0 0\n"); |
1928 | eq->att = 0; | 1928 | eq->att = 0; |
1929 | eq->boost = 0; | 1929 | eq->boost = 0; |
1930 | } | 1930 | } |
1931 | dev_dbg(dev, "lane rx-start: %d %d\n", eq->att, eq->boost); | 1931 | dev_dbg(dev, "lane rx-start: %d %d\n", eq->att, eq->boost); |
1932 | 1932 | ||
1933 | eq = &lc->rx_force; | 1933 | eq = &lc->rx_force; |
1934 | if (of_property_read_u32_array(np, "rx-force", &eq->att, 2)) { | 1934 | if (of_property_read_u32_array(np, "rx-force", &eq->att, 2)) { |
1935 | dev_info(dev, "use default lane rx-force 0 0\n"); | 1935 | dev_info(dev, "use default lane rx-force 0 0\n"); |
1936 | eq->att = 0; | 1936 | eq->att = 0; |
1937 | eq->boost = 0; | 1937 | eq->boost = 0; |
1938 | } | 1938 | } |
1939 | dev_dbg(dev, "lane rx-force: %d %d\n", eq->att, eq->boost); | 1939 | dev_dbg(dev, "lane rx-force: %d %d\n", eq->att, eq->boost); |
1940 | 1940 | ||
1941 | tc = &lc->tx_coeff; | 1941 | tc = &lc->tx_coeff; |
1942 | if (of_property_read_u32_array(np, "tx-coeff", &tc->c1, 5)) { | 1942 | if (of_property_read_u32_array(np, "tx-coeff", &tc->c1, 5)) { |
1943 | dev_info(dev, "use default tx-coeff 0\n"); | 1943 | dev_info(dev, "use default tx-coeff 0\n"); |
1944 | tc->c1 = 0; | 1944 | tc->c1 = 0; |
1945 | } | 1945 | } |
1946 | dev_dbg(dev, "tx-coeff: %d %d %d %d %d\n", | 1946 | dev_dbg(dev, "tx-coeff: %d %d %d %d %d\n", |
1947 | tc->c1, tc->c2, tc->cm, tc->att, tc->vreg); | 1947 | tc->c1, tc->c2, tc->cm, tc->att, tc->vreg); |
1948 | 1948 | ||
1949 | return 0; | 1949 | return 0; |
1950 | } | 1950 | } |
1951 | 1951 | ||
1952 | static void kserdes_set_sgmii_defaults(struct kserdes_config *sc) | 1952 | static void kserdes_set_sgmii_defaults(struct kserdes_config *sc) |
1953 | { | 1953 | { |
1954 | int i; | 1954 | int i; |
1955 | 1955 | ||
1956 | sc->link_rate = KSERDES_LINK_RATE_1P25G; | 1956 | sc->link_rate = KSERDES_LINK_RATE_1P25G; |
1957 | sc->lanes = 4; | 1957 | sc->lanes = 4; |
1958 | sc->rx_force_enable = false; | 1958 | sc->rx_force_enable = false; |
1959 | 1959 | ||
1960 | for_each_lane(sc, i) { | 1960 | for_each_lane(sc, i) { |
1961 | memset(&sc->lane[i], 0, sizeof(sc->lane[i])); | 1961 | memset(&sc->lane[i], 0, sizeof(sc->lane[i])); |
1962 | sc->lane[i].ctrl_rate = KSERDES_QUARTER_RATE; | 1962 | sc->lane[i].ctrl_rate = KSERDES_QUARTER_RATE; |
1963 | } | 1963 | } |
1964 | } | 1964 | } |
1965 | 1965 | ||
1966 | static void kserdes_set_xge_defaults(struct kserdes_config *sc) | 1966 | static void kserdes_set_xge_defaults(struct kserdes_config *sc) |
1967 | { | 1967 | { |
1968 | int i; | 1968 | int i; |
1969 | 1969 | ||
1970 | sc->link_rate = KSERDES_LINK_RATE_10P3125G; | 1970 | sc->link_rate = KSERDES_LINK_RATE_10P3125G; |
1971 | sc->lanes = 2; | 1971 | sc->lanes = 2; |
1972 | sc->rx_force_enable = false; | 1972 | sc->rx_force_enable = false; |
1973 | 1973 | ||
1974 | for_each_lane(sc, i) { | 1974 | for_each_lane(sc, i) { |
1975 | memset(&sc->lane[i], 0, sizeof(sc->lane[i])); | 1975 | memset(&sc->lane[i], 0, sizeof(sc->lane[i])); |
1976 | sc->lane[i].ctrl_rate = KSERDES_FULL_RATE; | 1976 | sc->lane[i].ctrl_rate = KSERDES_FULL_RATE; |
1977 | } | 1977 | } |
1978 | } | 1978 | } |
1979 | 1979 | ||
1980 | static void kserdes_set_pcie_defaults(struct kserdes_config *sc) | 1980 | static void kserdes_set_pcie_defaults(struct kserdes_config *sc) |
1981 | { | 1981 | { |
1982 | int i; | 1982 | int i; |
1983 | 1983 | ||
1984 | sc->link_rate = KSERDES_LINK_RATE_5G; | 1984 | sc->link_rate = KSERDES_LINK_RATE_5G; |
1985 | sc->lanes = 2; | 1985 | sc->lanes = 2; |
1986 | sc->rx_force_enable = false; | 1986 | sc->rx_force_enable = false; |
1987 | 1987 | ||
1988 | for_each_lane(sc, i) | 1988 | for_each_lane(sc, i) |
1989 | memset(&sc->lane[i], 0, sizeof(sc->lane[i])); | 1989 | memset(&sc->lane[i], 0, sizeof(sc->lane[i])); |
1990 | } | 1990 | } |
1991 | 1991 | ||
1992 | static void kserdes_set_defaults(struct kserdes_config *sc, | 1992 | static void kserdes_set_defaults(struct kserdes_config *sc, |
1993 | enum kserdes_phy_type phy_type) | 1993 | enum kserdes_phy_type phy_type) |
1994 | { | 1994 | { |
1995 | switch (phy_type) { | 1995 | switch (phy_type) { |
1996 | case KSERDES_PHY_SGMII: | 1996 | case KSERDES_PHY_SGMII: |
1997 | kserdes_set_sgmii_defaults(sc); | 1997 | kserdes_set_sgmii_defaults(sc); |
1998 | break; | 1998 | break; |
1999 | case KSERDES_PHY_XGE: | 1999 | case KSERDES_PHY_XGE: |
2000 | kserdes_set_xge_defaults(sc); | 2000 | kserdes_set_xge_defaults(sc); |
2001 | break; | 2001 | break; |
2002 | case KSERDES_PHY_PCIE: | 2002 | case KSERDES_PHY_PCIE: |
2003 | kserdes_set_pcie_defaults(sc); | 2003 | kserdes_set_pcie_defaults(sc); |
2004 | break; | 2004 | break; |
2005 | default: | 2005 | default: |
2006 | break; | 2006 | break; |
2007 | } | 2007 | } |
2008 | } | 2008 | } |
2009 | 2009 | ||
2010 | static const struct of_device_id kserdes_of_match[] = { | 2010 | static const struct of_device_id kserdes_of_match[] = { |
2011 | { .compatible = "ti,keystone-serdes-gbe", | 2011 | { .compatible = "ti,keystone-serdes-gbe", |
2012 | .data = &kserdes_devtype[KSERDES_PHY_SGMII], }, | 2012 | .data = &kserdes_devtype[KSERDES_PHY_SGMII], }, |
2013 | 2013 | ||
2014 | { .compatible = "ti,keystone-serdes-xgbe", | 2014 | { .compatible = "ti,keystone-serdes-xgbe", |
2015 | .data = &kserdes_devtype[KSERDES_PHY_XGE], }, | 2015 | .data = &kserdes_devtype[KSERDES_PHY_XGE], }, |
2016 | 2016 | ||
2017 | { .compatible = "ti,keystone-serdes-pcie", | 2017 | { .compatible = "ti,keystone-serdes-pcie", |
2018 | .data = &kserdes_devtype[KSERDES_PHY_PCIE], }, | 2018 | .data = &kserdes_devtype[KSERDES_PHY_PCIE], }, |
2019 | 2019 | ||
2020 | { }, | 2020 | { }, |
2021 | }; | 2021 | }; |
2022 | MODULE_DEVICE_TABLE(of, kserdes_of_match); | 2022 | MODULE_DEVICE_TABLE(of, kserdes_of_match); |
2023 | 2023 | ||
2024 | static int kserdes_of_parse(struct platform_device *pdev, | 2024 | static int kserdes_of_parse(struct platform_device *pdev, |
2025 | struct kserdes_dev *sd, | 2025 | struct kserdes_dev *sd, |
2026 | struct device_node *np) | 2026 | struct device_node *np) |
2027 | { | 2027 | { |
2028 | const struct of_device_id *of_id; | 2028 | const struct of_device_id *of_id; |
2029 | struct kserdes_config *sc = &sd->sc; | 2029 | struct kserdes_config *sc = &sd->sc; |
2030 | struct device_node *lanes_np, *child; | 2030 | struct device_node *lanes_np, *child; |
2031 | struct device *dev = sd->dev; | 2031 | struct device *dev = sd->dev; |
2032 | struct resource res; | 2032 | struct resource res; |
2033 | void __iomem *regs; | 2033 | void __iomem *regs; |
2034 | int ret; | 2034 | int ret; |
2035 | 2035 | ||
2036 | ret = of_address_to_resource(np, SERDES_REG_INDEX, &res); | 2036 | ret = of_address_to_resource(np, SERDES_REG_INDEX, &res); |
2037 | if (ret) { | 2037 | if (ret) { |
2038 | dev_err(dev, "Can't xlate serdes reg addr of node(%s)\n", | 2038 | dev_err(dev, "Can't xlate serdes reg addr of node(%s)\n", |
2039 | np->name); | 2039 | np->name); |
2040 | return ret; | 2040 | return ret; |
2041 | } | 2041 | } |
2042 | 2042 | ||
2043 | regs = devm_ioremap_resource(dev, &res); | 2043 | regs = devm_ioremap_resource(dev, &res); |
2044 | if (IS_ERR(regs)) { | 2044 | if (IS_ERR(regs)) { |
2045 | dev_err(dev, "Failed to map serdes register base\n"); | 2045 | dev_err(dev, "Failed to map serdes register base\n"); |
2046 | return PTR_ERR(regs); | 2046 | return PTR_ERR(regs); |
2047 | } | 2047 | } |
2048 | sc->regs = regs; | 2048 | sc->regs = regs; |
2049 | 2049 | ||
2050 | of_id = of_match_device(kserdes_of_match, dev); | 2050 | of_id = of_match_device(kserdes_of_match, dev); |
2051 | if (!of_id) { | 2051 | if (!of_id) { |
2052 | dev_err(dev, "unknown phy type\n"); | 2052 | dev_err(dev, "unknown phy type\n"); |
2053 | return -EINVAL; | 2053 | return -EINVAL; |
2054 | } | 2054 | } |
2055 | pdev->id_entry = of_id->data; | 2055 | pdev->id_entry = of_id->data; |
2056 | sc->phy_type = pdev->id_entry->driver_data; | 2056 | sc->phy_type = pdev->id_entry->driver_data; |
2057 | 2057 | ||
2058 | sc->dev = dev; | 2058 | sc->dev = dev; |
2059 | 2059 | ||
2060 | /* Set the defaults base on phy type */ | 2060 | /* Set the defaults base on phy type */ |
2061 | kserdes_set_defaults(sc, sc->phy_type); | 2061 | kserdes_set_defaults(sc, sc->phy_type); |
2062 | 2062 | ||
2063 | if (sc->phy_type == KSERDES_PHY_XGE) { | 2063 | if (sc->phy_type == KSERDES_PHY_XGE) { |
2064 | sc->peripheral_regmap = | 2064 | sc->peripheral_regmap = |
2065 | syscon_regmap_lookup_by_phandle(np, | 2065 | syscon_regmap_lookup_by_phandle(np, |
2066 | "syscon-peripheral"); | 2066 | "syscon-peripheral"); |
2067 | 2067 | ||
2068 | if (IS_ERR(sc->peripheral_regmap)) { | 2068 | if (IS_ERR(sc->peripheral_regmap)) { |
2069 | dev_err(sc->dev, | 2069 | dev_err(sc->dev, |
2070 | "peripheral regmap lookup failed: %ld\n", | 2070 | "peripheral regmap lookup failed: %ld\n", |
2071 | PTR_ERR(sc->peripheral_regmap)); | 2071 | PTR_ERR(sc->peripheral_regmap)); |
2072 | return PTR_ERR(sc->peripheral_regmap); | 2072 | return PTR_ERR(sc->peripheral_regmap); |
2073 | } | 2073 | } |
2074 | 2074 | ||
2075 | sc->pcsr_regmap = | 2075 | sc->pcsr_regmap = |
2076 | syscon_regmap_lookup_by_phandle(np, "syscon-link"); | 2076 | syscon_regmap_lookup_by_phandle(np, "syscon-link"); |
2077 | 2077 | ||
2078 | if (IS_ERR(sc->pcsr_regmap)) { | 2078 | if (IS_ERR(sc->pcsr_regmap)) { |
2079 | dev_err(sc->dev, "link regmap lookup failed: %ld\n", | 2079 | dev_err(sc->dev, "link regmap lookup failed: %ld\n", |
2080 | PTR_ERR(sc->pcsr_regmap)); | 2080 | PTR_ERR(sc->pcsr_regmap)); |
2081 | return PTR_ERR(sc->pcsr_regmap); | 2081 | return PTR_ERR(sc->pcsr_regmap); |
2082 | } | 2082 | } |
2083 | } | 2083 | } |
2084 | 2084 | ||
2085 | if (of_property_read_u32(np, "link-rate-kbps", &sc->link_rate)) { | 2085 | if (of_property_read_u32(np, "link-rate-kbps", &sc->link_rate)) { |
2086 | dev_info(dev, "use default link-rate-kbps: %u\n", | 2086 | dev_info(dev, "use default link-rate-kbps: %u\n", |
2087 | sc->link_rate); | 2087 | sc->link_rate); |
2088 | } | 2088 | } |
2089 | 2089 | ||
2090 | if (of_property_read_u32(np, "num-lanes", &sc->lanes)) | 2090 | if (of_property_read_u32(np, "num-lanes", &sc->lanes)) |
2091 | dev_info(dev, "use default num-lanes %d\n", sc->lanes); | 2091 | dev_info(dev, "use default num-lanes %d\n", sc->lanes); |
2092 | 2092 | ||
2093 | if (sc->lanes > KSERDES_MAX_LANES) { | 2093 | if (sc->lanes > KSERDES_MAX_LANES) { |
2094 | sc->lanes = KSERDES_MAX_LANES; | 2094 | sc->lanes = KSERDES_MAX_LANES; |
2095 | dev_info(dev, "use max allowed lanes %d\n", sc->lanes); | 2095 | dev_info(dev, "use max allowed lanes %d\n", sc->lanes); |
2096 | } | 2096 | } |
2097 | 2097 | ||
2098 | if (of_property_read_bool(np, "rx-force-enable")) | 2098 | if (of_property_read_bool(np, "rx-force-enable")) |
2099 | sc->rx_force_enable = true; | 2099 | sc->rx_force_enable = true; |
2100 | else | 2100 | else |
2101 | sc->rx_force_enable = false; | 2101 | sc->rx_force_enable = false; |
2102 | 2102 | ||
2103 | lanes_np = of_get_child_by_name(np, "lanes"); | 2103 | lanes_np = of_get_child_by_name(np, "lanes"); |
2104 | if (lanes_np) { | 2104 | if (lanes_np) { |
2105 | for_each_available_child_of_node(lanes_np, child) { | 2105 | for_each_available_child_of_node(lanes_np, child) { |
2106 | ret = kserdes_of_parse_lane(dev, child, sc); | 2106 | ret = kserdes_of_parse_lane(dev, child, sc); |
2107 | if (ret) { | 2107 | if (ret) { |
2108 | of_node_put(child); | 2108 | of_node_put(child); |
2109 | of_node_put(lanes_np); | 2109 | of_node_put(lanes_np); |
2110 | return ret; | 2110 | return ret; |
2111 | } | 2111 | } |
2112 | of_node_put(child); | 2112 | of_node_put(child); |
2113 | } | 2113 | } |
2114 | of_node_put(lanes_np); | 2114 | of_node_put(lanes_np); |
2115 | } | 2115 | } |
2116 | 2116 | ||
2117 | return 0; | 2117 | return 0; |
2118 | } | 2118 | } |
2119 | 2119 | ||
2120 | static struct phy_ops kserdes_ops = { | 2120 | static struct phy_ops kserdes_ops = { |
2121 | .init = kserdes_init, | 2121 | .init = kserdes_init, |
2122 | .owner = THIS_MODULE, | 2122 | .owner = THIS_MODULE, |
2123 | }; | 2123 | }; |
2124 | 2124 | ||
2125 | static int kserdes_probe(struct platform_device *pdev) | 2125 | static int kserdes_probe(struct platform_device *pdev) |
2126 | { | 2126 | { |
2127 | struct phy_provider *phy_provider; | 2127 | struct phy_provider *phy_provider; |
2128 | struct kserdes_dev *sd; | 2128 | struct kserdes_dev *sd; |
2129 | struct device_node *np = pdev->dev.of_node; | 2129 | struct device_node *np = pdev->dev.of_node; |
2130 | struct device *dev = &pdev->dev; | 2130 | struct device *dev = &pdev->dev; |
2131 | int ret; | 2131 | int ret; |
2132 | 2132 | ||
2133 | sd = devm_kzalloc(dev, sizeof(*sd), GFP_KERNEL); | 2133 | sd = devm_kzalloc(dev, sizeof(*sd), GFP_KERNEL); |
2134 | if (!sd) | 2134 | if (!sd) |
2135 | return -ENOMEM; | 2135 | return -ENOMEM; |
2136 | 2136 | ||
2137 | sd->dev = dev; | 2137 | sd->dev = dev; |
2138 | 2138 | ||
2139 | ret = kserdes_of_parse(pdev, sd, np); | 2139 | ret = kserdes_of_parse(pdev, sd, np); |
2140 | if (ret) | 2140 | if (ret) |
2141 | return ret; | 2141 | return ret; |
2142 | 2142 | ||
2143 | dev_set_drvdata(dev, sd); | 2143 | dev_set_drvdata(dev, sd); |
2144 | sd->phy = devm_phy_create(dev, NULL, &kserdes_ops); | 2144 | sd->phy = devm_phy_create(dev, NULL, &kserdes_ops); |
2145 | if (IS_ERR(sd->phy)) | 2145 | if (IS_ERR(sd->phy)) |
2146 | return PTR_ERR(sd->phy); | 2146 | return PTR_ERR(sd->phy); |
2147 | 2147 | ||
2148 | phy_set_drvdata(sd->phy, sd); | 2148 | phy_set_drvdata(sd->phy, sd); |
2149 | phy_provider = devm_of_phy_provider_register(sd->dev, | 2149 | phy_provider = devm_of_phy_provider_register(sd->dev, |
2150 | of_phy_simple_xlate); | 2150 | of_phy_simple_xlate); |
2151 | 2151 | ||
2152 | if (IS_ERR(phy_provider)) | 2152 | if (IS_ERR(phy_provider)) |
2153 | return PTR_ERR_OR_ZERO(phy_provider); | 2153 | return PTR_ERR_OR_ZERO(phy_provider); |
2154 | 2154 | ||
2155 | dev_vdbg(&pdev->dev, "probed"); | 2155 | dev_vdbg(&pdev->dev, "probed"); |
2156 | return 0; | 2156 | return 0; |
2157 | } | 2157 | } |
2158 | 2158 | ||
2159 | static struct platform_driver kserdes_driver = { | 2159 | static struct platform_driver kserdes_driver = { |
2160 | .probe = kserdes_probe, | 2160 | .probe = kserdes_probe, |
2161 | .driver = { | 2161 | .driver = { |
2162 | .of_match_table = kserdes_of_match, | 2162 | .of_match_table = kserdes_of_match, |
2163 | .name = "ti,keystone-serdes", | 2163 | .name = "ti,keystone-serdes", |
2164 | } | 2164 | } |
2165 | }; | 2165 | }; |
2166 | module_platform_driver(kserdes_driver); | 2166 | module_platform_driver(kserdes_driver); |
2167 | 2167 | ||
2168 | MODULE_AUTHOR("WingMan Kwok <w-kwok2@ti.com>"); | 2168 | MODULE_AUTHOR("WingMan Kwok <w-kwok2@ti.com>"); |
2169 | MODULE_DESCRIPTION("TI Keystone SerDes driver"); | 2169 | MODULE_DESCRIPTION("TI Keystone SerDes driver"); |
2170 | MODULE_LICENSE("GPL"); | 2170 | MODULE_LICENSE("GPL"); |
2171 | 2171 |