1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. |
3 | */ |
4 | |
5 | /* Qualcomm Technologies, Inc. QDF2400 EMAC SGMII Controller driver. |
6 | */ |
7 | |
8 | #include <linux/iopoll.h> |
9 | #include "emac.h" |
10 | |
11 | /* EMAC_SGMII register offsets */ |
12 | #define EMAC_SGMII_PHY_TX_PWR_CTRL 0x000C |
13 | #define EMAC_SGMII_PHY_LANE_CTRL1 0x0018 |
14 | #define EMAC_SGMII_PHY_CDR_CTRL0 0x0058 |
15 | #define EMAC_SGMII_PHY_POW_DWN_CTRL0 0x0080 |
16 | #define EMAC_SGMII_PHY_RESET_CTRL 0x00a8 |
17 | #define EMAC_SGMII_PHY_INTERRUPT_MASK 0x00b4 |
18 | |
19 | /* SGMII digital lane registers */ |
20 | #define EMAC_SGMII_LN_DRVR_CTRL0 0x000C |
21 | #define EMAC_SGMII_LN_DRVR_CTRL1 0x0010 |
22 | #define EMAC_SGMII_LN_DRVR_TAP_EN 0x0018 |
23 | #define EMAC_SGMII_LN_TX_MARGINING 0x001C |
24 | #define EMAC_SGMII_LN_TX_PRE 0x0020 |
25 | #define EMAC_SGMII_LN_TX_POST 0x0024 |
26 | #define EMAC_SGMII_LN_TX_BAND_MODE 0x0060 |
27 | #define EMAC_SGMII_LN_LANE_MODE 0x0064 |
28 | #define EMAC_SGMII_LN_PARALLEL_RATE 0x007C |
29 | #define EMAC_SGMII_LN_CML_CTRL_MODE0 0x00C0 |
30 | #define EMAC_SGMII_LN_MIXER_CTRL_MODE0 0x00D8 |
31 | #define EMAC_SGMII_LN_VGA_INITVAL 0x013C |
32 | #define EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0 0x0184 |
33 | #define EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0 0x0190 |
34 | #define EMAC_SGMII_LN_UCDR_SO_CONFIG 0x019C |
35 | #define EMAC_SGMII_LN_RX_BAND 0x01A4 |
36 | #define EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0 0x01C0 |
37 | #define EMAC_SGMII_LN_RSM_CONFIG 0x01F8 |
38 | #define EMAC_SGMII_LN_SIGDET_ENABLES 0x0230 |
39 | #define EMAC_SGMII_LN_SIGDET_CNTRL 0x0234 |
40 | #define EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL 0x0238 |
41 | #define EMAC_SGMII_LN_RX_EN_SIGNAL 0x02AC |
42 | #define EMAC_SGMII_LN_RX_MISC_CNTRL0 0x02B8 |
43 | #define EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV 0x02C8 |
44 | #define EMAC_SGMII_LN_RX_RESECODE_OFFSET 0x02CC |
45 | |
46 | /* SGMII digital lane register values */ |
47 | #define UCDR_STEP_BY_TWO_MODE0 BIT(7) |
48 | #define UCDR_xO_GAIN_MODE(x) ((x) & 0x7f) |
49 | #define UCDR_ENABLE BIT(6) |
50 | #define UCDR_SO_SATURATION(x) ((x) & 0x3f) |
51 | |
52 | #define SIGDET_LP_BYP_PS4 BIT(7) |
53 | #define SIGDET_EN_PS0_TO_PS2 BIT(6) |
54 | |
55 | #define TXVAL_VALID_INIT BIT(4) |
56 | #define KR_PCIGEN3_MODE BIT(0) |
57 | |
58 | #define MAIN_EN BIT(0) |
59 | |
60 | #define TX_MARGINING_MUX BIT(6) |
61 | #define TX_MARGINING(x) ((x) & 0x3f) |
62 | |
63 | #define TX_PRE_MUX BIT(6) |
64 | |
65 | #define TX_POST_MUX BIT(6) |
66 | |
67 | #define CML_GEAR_MODE(x) (((x) & 7) << 3) |
68 | #define CML2CMOS_IBOOST_MODE(x) ((x) & 7) |
69 | |
70 | #define RESCODE_OFFSET(x) ((x) & 0x1f) |
71 | |
72 | #define MIXER_LOADB_MODE(x) (((x) & 0xf) << 2) |
73 | #define MIXER_DATARATE_MODE(x) ((x) & 3) |
74 | |
75 | #define VGA_THRESH_DFE(x) ((x) & 0x3f) |
76 | |
77 | #define SIGDET_LP_BYP_PS0_TO_PS2 BIT(5) |
78 | #define SIGDET_FLT_BYP BIT(0) |
79 | |
80 | #define SIGDET_LVL(x) (((x) & 0xf) << 4) |
81 | |
82 | #define SIGDET_DEGLITCH_CTRL(x) (((x) & 0xf) << 1) |
83 | |
84 | #define INVERT_PCS_RX_CLK BIT(7) |
85 | |
86 | #define DRVR_LOGIC_CLK_EN BIT(4) |
87 | #define DRVR_LOGIC_CLK_DIV(x) ((x) & 0xf) |
88 | |
89 | #define PARALLEL_RATE_MODE0(x) ((x) & 0x3) |
90 | |
91 | #define BAND_MODE0(x) ((x) & 0x3) |
92 | |
93 | #define LANE_MODE(x) ((x) & 0x1f) |
94 | |
95 | #define CDR_PD_SEL_MODE0(x) (((x) & 0x3) << 5) |
96 | #define EN_DLL_MODE0 BIT(4) |
97 | #define EN_IQ_DCC_MODE0 BIT(3) |
98 | #define EN_IQCAL_MODE0 BIT(2) |
99 | |
100 | #define BYPASS_RSM_SAMP_CAL BIT(1) |
101 | #define BYPASS_RSM_DLL_CAL BIT(0) |
102 | |
103 | #define L0_RX_EQUALIZE_ENABLE BIT(6) |
104 | |
105 | #define PWRDN_B BIT(0) |
106 | |
107 | #define CDR_MAX_CNT(x) ((x) & 0xff) |
108 | |
109 | #define SERDES_START_WAIT_TIMES 100 |
110 | |
111 | struct emac_reg_write { |
112 | unsigned int offset; |
113 | u32 val; |
114 | }; |
115 | |
116 | static void emac_reg_write_all(void __iomem *base, |
117 | const struct emac_reg_write *itr, size_t size) |
118 | { |
119 | size_t i; |
120 | |
121 | for (i = 0; i < size; ++itr, ++i) |
122 | writel(val: itr->val, addr: base + itr->offset); |
123 | } |
124 | |
125 | static const struct emac_reg_write sgmii_laned[] = { |
126 | /* CDR Settings */ |
127 | {EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0, |
128 | UCDR_STEP_BY_TWO_MODE0 | UCDR_xO_GAIN_MODE(10)}, |
129 | {EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0, UCDR_xO_GAIN_MODE(0)}, |
130 | {EMAC_SGMII_LN_UCDR_SO_CONFIG, UCDR_ENABLE | UCDR_SO_SATURATION(12)}, |
131 | |
132 | /* TX/RX Settings */ |
133 | {EMAC_SGMII_LN_RX_EN_SIGNAL, SIGDET_LP_BYP_PS4 | SIGDET_EN_PS0_TO_PS2}, |
134 | |
135 | {EMAC_SGMII_LN_DRVR_CTRL0, TXVAL_VALID_INIT | KR_PCIGEN3_MODE}, |
136 | {EMAC_SGMII_LN_DRVR_TAP_EN, MAIN_EN}, |
137 | {EMAC_SGMII_LN_TX_MARGINING, TX_MARGINING_MUX | TX_MARGINING(25)}, |
138 | {EMAC_SGMII_LN_TX_PRE, TX_PRE_MUX}, |
139 | {EMAC_SGMII_LN_TX_POST, TX_POST_MUX}, |
140 | |
141 | {EMAC_SGMII_LN_CML_CTRL_MODE0, |
142 | CML_GEAR_MODE(1) | CML2CMOS_IBOOST_MODE(1)}, |
143 | {EMAC_SGMII_LN_MIXER_CTRL_MODE0, |
144 | MIXER_LOADB_MODE(12) | MIXER_DATARATE_MODE(1)}, |
145 | {EMAC_SGMII_LN_VGA_INITVAL, VGA_THRESH_DFE(31)}, |
146 | {EMAC_SGMII_LN_SIGDET_ENABLES, |
147 | SIGDET_LP_BYP_PS0_TO_PS2 | SIGDET_FLT_BYP}, |
148 | {EMAC_SGMII_LN_SIGDET_CNTRL, SIGDET_LVL(8)}, |
149 | |
150 | {EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL, SIGDET_DEGLITCH_CTRL(4)}, |
151 | {EMAC_SGMII_LN_RX_MISC_CNTRL0, INVERT_PCS_RX_CLK}, |
152 | {EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV, |
153 | DRVR_LOGIC_CLK_EN | DRVR_LOGIC_CLK_DIV(4)}, |
154 | |
155 | {EMAC_SGMII_LN_PARALLEL_RATE, PARALLEL_RATE_MODE0(1)}, |
156 | {EMAC_SGMII_LN_TX_BAND_MODE, BAND_MODE0(1)}, |
157 | {EMAC_SGMII_LN_RX_BAND, BAND_MODE0(2)}, |
158 | {EMAC_SGMII_LN_DRVR_CTRL1, RESCODE_OFFSET(7)}, |
159 | {EMAC_SGMII_LN_RX_RESECODE_OFFSET, RESCODE_OFFSET(9)}, |
160 | {EMAC_SGMII_LN_LANE_MODE, LANE_MODE(26)}, |
161 | {EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0, CDR_PD_SEL_MODE0(2) | |
162 | EN_DLL_MODE0 | EN_IQ_DCC_MODE0 | EN_IQCAL_MODE0}, |
163 | {EMAC_SGMII_LN_RSM_CONFIG, BYPASS_RSM_SAMP_CAL | BYPASS_RSM_DLL_CAL}, |
164 | }; |
165 | |
166 | static const struct emac_reg_write physical_coding_sublayer_programming[] = { |
167 | {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B}, |
168 | {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)}, |
169 | {EMAC_SGMII_PHY_TX_PWR_CTRL, 0}, |
170 | {EMAC_SGMII_PHY_LANE_CTRL1, L0_RX_EQUALIZE_ENABLE}, |
171 | }; |
172 | |
173 | int emac_sgmii_init_qdf2400(struct emac_adapter *adpt) |
174 | { |
175 | struct emac_sgmii *phy = &adpt->phy; |
176 | void __iomem *phy_regs = phy->base; |
177 | void __iomem *laned = phy->digital; |
178 | unsigned int i; |
179 | u32 lnstatus; |
180 | |
181 | /* PCS lane-x init */ |
182 | emac_reg_write_all(base: phy->base, itr: physical_coding_sublayer_programming, |
183 | ARRAY_SIZE(physical_coding_sublayer_programming)); |
184 | |
185 | /* SGMII lane-x init */ |
186 | emac_reg_write_all(base: phy->digital, itr: sgmii_laned, ARRAY_SIZE(sgmii_laned)); |
187 | |
188 | /* Power up PCS and start reset lane state machine */ |
189 | |
190 | writel(val: 0, addr: phy_regs + EMAC_SGMII_PHY_RESET_CTRL); |
191 | writel(val: 1, addr: laned + SGMII_LN_RSM_START); |
192 | |
193 | /* Wait for c_ready assertion */ |
194 | for (i = 0; i < SERDES_START_WAIT_TIMES; i++) { |
195 | lnstatus = readl(addr: phy_regs + SGMII_PHY_LN_LANE_STATUS); |
196 | if (lnstatus & BIT(1)) |
197 | break; |
198 | usleep_range(min: 100, max: 200); |
199 | } |
200 | |
201 | if (i == SERDES_START_WAIT_TIMES) { |
202 | netdev_err(dev: adpt->netdev, format: "SGMII failed to start\n" ); |
203 | return -EIO; |
204 | } |
205 | |
206 | /* Disable digital and SERDES loopback */ |
207 | writel(val: 0, addr: phy_regs + SGMII_PHY_LN_BIST_GEN0); |
208 | writel(val: 0, addr: phy_regs + SGMII_PHY_LN_BIST_GEN2); |
209 | writel(val: 0, addr: phy_regs + SGMII_PHY_LN_CDR_CTRL1); |
210 | |
211 | /* Mask out all the SGMII Interrupt */ |
212 | writel(val: 0, addr: phy_regs + EMAC_SGMII_PHY_INTERRUPT_MASK); |
213 | |
214 | return 0; |
215 | } |
216 | |