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. QDF2432 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_TAP_EN 0x0018 |
22 | #define EMAC_SGMII_LN_TX_MARGINING 0x001C |
23 | #define EMAC_SGMII_LN_TX_PRE 0x0020 |
24 | #define EMAC_SGMII_LN_TX_POST 0x0024 |
25 | #define EMAC_SGMII_LN_TX_BAND_MODE 0x0060 |
26 | #define EMAC_SGMII_LN_LANE_MODE 0x0064 |
27 | #define EMAC_SGMII_LN_PARALLEL_RATE 0x0078 |
28 | #define EMAC_SGMII_LN_CML_CTRL_MODE0 0x00B8 |
29 | #define EMAC_SGMII_LN_MIXER_CTRL_MODE0 0x00D0 |
30 | #define EMAC_SGMII_LN_VGA_INITVAL 0x0134 |
31 | #define EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0 0x017C |
32 | #define EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0 0x0188 |
33 | #define EMAC_SGMII_LN_UCDR_SO_CONFIG 0x0194 |
34 | #define EMAC_SGMII_LN_RX_BAND 0x019C |
35 | #define EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0 0x01B8 |
36 | #define EMAC_SGMII_LN_RSM_CONFIG 0x01F0 |
37 | #define EMAC_SGMII_LN_SIGDET_ENABLES 0x0224 |
38 | #define EMAC_SGMII_LN_SIGDET_CNTRL 0x0228 |
39 | #define EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL 0x022C |
40 | #define EMAC_SGMII_LN_RX_EN_SIGNAL 0x02A0 |
41 | #define EMAC_SGMII_LN_RX_MISC_CNTRL0 0x02AC |
42 | #define EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV 0x02BC |
43 | |
44 | /* SGMII digital lane register values */ |
45 | #define UCDR_STEP_BY_TWO_MODE0 BIT(7) |
46 | #define UCDR_xO_GAIN_MODE(x) ((x) & 0x7f) |
47 | #define UCDR_ENABLE BIT(6) |
48 | #define UCDR_SO_SATURATION(x) ((x) & 0x3f) |
49 | |
50 | #define SIGDET_LP_BYP_PS4 BIT(7) |
51 | #define SIGDET_EN_PS0_TO_PS2 BIT(6) |
52 | |
53 | #define TXVAL_VALID_INIT BIT(4) |
54 | #define KR_PCIGEN3_MODE BIT(0) |
55 | |
56 | #define MAIN_EN BIT(0) |
57 | |
58 | #define TX_MARGINING_MUX BIT(6) |
59 | #define TX_MARGINING(x) ((x) & 0x3f) |
60 | |
61 | #define TX_PRE_MUX BIT(6) |
62 | |
63 | #define TX_POST_MUX BIT(6) |
64 | |
65 | #define CML_GEAR_MODE(x) (((x) & 7) << 3) |
66 | #define CML2CMOS_IBOOST_MODE(x) ((x) & 7) |
67 | |
68 | #define MIXER_LOADB_MODE(x) (((x) & 0xf) << 2) |
69 | #define MIXER_DATARATE_MODE(x) ((x) & 3) |
70 | |
71 | #define VGA_THRESH_DFE(x) ((x) & 0x3f) |
72 | |
73 | #define SIGDET_LP_BYP_PS0_TO_PS2 BIT(5) |
74 | #define SIGDET_FLT_BYP BIT(0) |
75 | |
76 | #define SIGDET_LVL(x) (((x) & 0xf) << 4) |
77 | |
78 | #define SIGDET_DEGLITCH_CTRL(x) (((x) & 0xf) << 1) |
79 | |
80 | #define DRVR_LOGIC_CLK_EN BIT(4) |
81 | #define DRVR_LOGIC_CLK_DIV(x) ((x) & 0xf) |
82 | |
83 | #define PARALLEL_RATE_MODE0(x) ((x) & 0x3) |
84 | |
85 | #define BAND_MODE0(x) ((x) & 0x3) |
86 | |
87 | #define LANE_MODE(x) ((x) & 0x1f) |
88 | |
89 | #define CDR_PD_SEL_MODE0(x) (((x) & 0x3) << 5) |
90 | #define BYPASS_RSM_SAMP_CAL BIT(1) |
91 | #define BYPASS_RSM_DLL_CAL BIT(0) |
92 | |
93 | #define L0_RX_EQUALIZE_ENABLE BIT(6) |
94 | |
95 | #define PWRDN_B BIT(0) |
96 | |
97 | #define CDR_MAX_CNT(x) ((x) & 0xff) |
98 | |
99 | #define SERDES_START_WAIT_TIMES 100 |
100 | |
101 | struct emac_reg_write { |
102 | unsigned int offset; |
103 | u32 val; |
104 | }; |
105 | |
106 | static void emac_reg_write_all(void __iomem *base, |
107 | const struct emac_reg_write *itr, size_t size) |
108 | { |
109 | size_t i; |
110 | |
111 | for (i = 0; i < size; ++itr, ++i) |
112 | writel(val: itr->val, addr: base + itr->offset); |
113 | } |
114 | |
115 | static const struct emac_reg_write sgmii_laned[] = { |
116 | /* CDR Settings */ |
117 | {EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0, |
118 | UCDR_STEP_BY_TWO_MODE0 | UCDR_xO_GAIN_MODE(10)}, |
119 | {EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0, UCDR_xO_GAIN_MODE(0)}, |
120 | {EMAC_SGMII_LN_UCDR_SO_CONFIG, UCDR_ENABLE | UCDR_SO_SATURATION(12)}, |
121 | |
122 | /* TX/RX Settings */ |
123 | {EMAC_SGMII_LN_RX_EN_SIGNAL, SIGDET_LP_BYP_PS4 | SIGDET_EN_PS0_TO_PS2}, |
124 | |
125 | {EMAC_SGMII_LN_DRVR_CTRL0, TXVAL_VALID_INIT | KR_PCIGEN3_MODE}, |
126 | {EMAC_SGMII_LN_DRVR_TAP_EN, MAIN_EN}, |
127 | {EMAC_SGMII_LN_TX_MARGINING, TX_MARGINING_MUX | TX_MARGINING(25)}, |
128 | {EMAC_SGMII_LN_TX_PRE, TX_PRE_MUX}, |
129 | {EMAC_SGMII_LN_TX_POST, TX_POST_MUX}, |
130 | |
131 | {EMAC_SGMII_LN_CML_CTRL_MODE0, |
132 | CML_GEAR_MODE(1) | CML2CMOS_IBOOST_MODE(1)}, |
133 | {EMAC_SGMII_LN_MIXER_CTRL_MODE0, |
134 | MIXER_LOADB_MODE(12) | MIXER_DATARATE_MODE(1)}, |
135 | {EMAC_SGMII_LN_VGA_INITVAL, VGA_THRESH_DFE(31)}, |
136 | {EMAC_SGMII_LN_SIGDET_ENABLES, |
137 | SIGDET_LP_BYP_PS0_TO_PS2 | SIGDET_FLT_BYP}, |
138 | {EMAC_SGMII_LN_SIGDET_CNTRL, SIGDET_LVL(8)}, |
139 | |
140 | {EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL, SIGDET_DEGLITCH_CTRL(4)}, |
141 | {EMAC_SGMII_LN_RX_MISC_CNTRL0, 0}, |
142 | {EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV, |
143 | DRVR_LOGIC_CLK_EN | DRVR_LOGIC_CLK_DIV(4)}, |
144 | |
145 | {EMAC_SGMII_LN_PARALLEL_RATE, PARALLEL_RATE_MODE0(1)}, |
146 | {EMAC_SGMII_LN_TX_BAND_MODE, BAND_MODE0(2)}, |
147 | {EMAC_SGMII_LN_RX_BAND, BAND_MODE0(3)}, |
148 | {EMAC_SGMII_LN_LANE_MODE, LANE_MODE(26)}, |
149 | {EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0, CDR_PD_SEL_MODE0(3)}, |
150 | {EMAC_SGMII_LN_RSM_CONFIG, BYPASS_RSM_SAMP_CAL | BYPASS_RSM_DLL_CAL}, |
151 | }; |
152 | |
153 | static const struct emac_reg_write physical_coding_sublayer_programming[] = { |
154 | {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B}, |
155 | {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)}, |
156 | {EMAC_SGMII_PHY_TX_PWR_CTRL, 0}, |
157 | {EMAC_SGMII_PHY_LANE_CTRL1, L0_RX_EQUALIZE_ENABLE}, |
158 | }; |
159 | |
160 | int emac_sgmii_init_qdf2432(struct emac_adapter *adpt) |
161 | { |
162 | struct emac_sgmii *phy = &adpt->phy; |
163 | void __iomem *phy_regs = phy->base; |
164 | void __iomem *laned = phy->digital; |
165 | unsigned int i; |
166 | u32 lnstatus; |
167 | |
168 | /* PCS lane-x init */ |
169 | emac_reg_write_all(base: phy->base, itr: physical_coding_sublayer_programming, |
170 | ARRAY_SIZE(physical_coding_sublayer_programming)); |
171 | |
172 | /* SGMII lane-x init */ |
173 | emac_reg_write_all(base: phy->digital, itr: sgmii_laned, ARRAY_SIZE(sgmii_laned)); |
174 | |
175 | /* Power up PCS and start reset lane state machine */ |
176 | |
177 | writel(val: 0, addr: phy_regs + EMAC_SGMII_PHY_RESET_CTRL); |
178 | writel(val: 1, addr: laned + SGMII_LN_RSM_START); |
179 | |
180 | /* Wait for c_ready assertion */ |
181 | for (i = 0; i < SERDES_START_WAIT_TIMES; i++) { |
182 | lnstatus = readl(addr: phy_regs + SGMII_PHY_LN_LANE_STATUS); |
183 | if (lnstatus & BIT(1)) |
184 | break; |
185 | usleep_range(min: 100, max: 200); |
186 | } |
187 | |
188 | if (i == SERDES_START_WAIT_TIMES) { |
189 | netdev_err(dev: adpt->netdev, format: "SGMII failed to start\n" ); |
190 | return -EIO; |
191 | } |
192 | |
193 | /* Disable digital and SERDES loopback */ |
194 | writel(val: 0, addr: phy_regs + SGMII_PHY_LN_BIST_GEN0); |
195 | writel(val: 0, addr: phy_regs + SGMII_PHY_LN_BIST_GEN2); |
196 | writel(val: 0, addr: phy_regs + SGMII_PHY_LN_CDR_CTRL1); |
197 | |
198 | /* Mask out all the SGMII Interrupt */ |
199 | writel(val: 0, addr: phy_regs + EMAC_SGMII_PHY_INTERRUPT_MASK); |
200 | |
201 | return 0; |
202 | } |
203 | |