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. FSM9900 EMAC SGMII Controller driver. |
6 | */ |
7 | |
8 | #include <linux/iopoll.h> |
9 | #include "emac.h" |
10 | |
11 | /* EMAC_QSERDES register offsets */ |
12 | #define EMAC_QSERDES_COM_SYS_CLK_CTRL 0x0000 |
13 | #define EMAC_QSERDES_COM_PLL_CNTRL 0x0014 |
14 | #define EMAC_QSERDES_COM_PLL_IP_SETI 0x0018 |
15 | #define EMAC_QSERDES_COM_PLL_CP_SETI 0x0024 |
16 | #define EMAC_QSERDES_COM_PLL_IP_SETP 0x0028 |
17 | #define EMAC_QSERDES_COM_PLL_CP_SETP 0x002c |
18 | #define EMAC_QSERDES_COM_SYSCLK_EN_SEL 0x0038 |
19 | #define EMAC_QSERDES_COM_RESETSM_CNTRL 0x0040 |
20 | #define EMAC_QSERDES_COM_PLLLOCK_CMP1 0x0044 |
21 | #define EMAC_QSERDES_COM_PLLLOCK_CMP2 0x0048 |
22 | #define EMAC_QSERDES_COM_PLLLOCK_CMP3 0x004c |
23 | #define EMAC_QSERDES_COM_PLLLOCK_CMP_EN 0x0050 |
24 | #define EMAC_QSERDES_COM_DEC_START1 0x0064 |
25 | #define EMAC_QSERDES_COM_DIV_FRAC_START1 0x0098 |
26 | #define EMAC_QSERDES_COM_DIV_FRAC_START2 0x009c |
27 | #define EMAC_QSERDES_COM_DIV_FRAC_START3 0x00a0 |
28 | #define EMAC_QSERDES_COM_DEC_START2 0x00a4 |
29 | #define EMAC_QSERDES_COM_PLL_CRCTRL 0x00ac |
30 | #define EMAC_QSERDES_COM_RESET_SM 0x00bc |
31 | #define EMAC_QSERDES_TX_BIST_MODE_LANENO 0x0100 |
32 | #define EMAC_QSERDES_TX_TX_EMP_POST1_LVL 0x0108 |
33 | #define EMAC_QSERDES_TX_TX_DRV_LVL 0x010c |
34 | #define EMAC_QSERDES_TX_LANE_MODE 0x0150 |
35 | #define EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN 0x0170 |
36 | #define EMAC_QSERDES_RX_CDR_CONTROL 0x0200 |
37 | #define EMAC_QSERDES_RX_CDR_CONTROL2 0x0210 |
38 | #define EMAC_QSERDES_RX_RX_EQ_GAIN12 0x0230 |
39 | |
40 | /* EMAC_SGMII register offsets */ |
41 | #define EMAC_SGMII_PHY_SERDES_START 0x0000 |
42 | #define EMAC_SGMII_PHY_CMN_PWR_CTRL 0x0004 |
43 | #define EMAC_SGMII_PHY_RX_PWR_CTRL 0x0008 |
44 | #define EMAC_SGMII_PHY_TX_PWR_CTRL 0x000C |
45 | #define EMAC_SGMII_PHY_LANE_CTRL1 0x0018 |
46 | #define EMAC_SGMII_PHY_CDR_CTRL0 0x0058 |
47 | #define EMAC_SGMII_PHY_POW_DWN_CTRL0 0x0080 |
48 | #define EMAC_SGMII_PHY_INTERRUPT_MASK 0x00b4 |
49 | |
50 | #define PLL_IPSETI(x) ((x) & 0x3f) |
51 | |
52 | #define PLL_CPSETI(x) ((x) & 0xff) |
53 | |
54 | #define PLL_IPSETP(x) ((x) & 0x3f) |
55 | |
56 | #define PLL_CPSETP(x) ((x) & 0x1f) |
57 | |
58 | #define PLL_RCTRL(x) (((x) & 0xf) << 4) |
59 | #define PLL_CCTRL(x) ((x) & 0xf) |
60 | |
61 | #define LANE_MODE(x) ((x) & 0x1f) |
62 | |
63 | #define SYSCLK_CM BIT(4) |
64 | #define SYSCLK_AC_COUPLE BIT(3) |
65 | |
66 | #define OCP_EN BIT(5) |
67 | #define PLL_DIV_FFEN BIT(2) |
68 | #define PLL_DIV_ORD BIT(1) |
69 | |
70 | #define SYSCLK_SEL_CMOS BIT(3) |
71 | |
72 | #define FRQ_TUNE_MODE BIT(4) |
73 | |
74 | #define PLLLOCK_CMP_EN BIT(0) |
75 | |
76 | #define DEC_START1_MUX BIT(7) |
77 | #define DEC_START1(x) ((x) & 0x7f) |
78 | |
79 | #define DIV_FRAC_START_MUX BIT(7) |
80 | #define DIV_FRAC_START(x) ((x) & 0x7f) |
81 | |
82 | #define DIV_FRAC_START3_MUX BIT(4) |
83 | #define DIV_FRAC_START3(x) ((x) & 0xf) |
84 | |
85 | #define DEC_START2_MUX BIT(1) |
86 | #define DEC_START2 BIT(0) |
87 | |
88 | #define READY BIT(5) |
89 | |
90 | #define TX_EMP_POST1_LVL_MUX BIT(5) |
91 | #define TX_EMP_POST1_LVL(x) ((x) & 0x1f) |
92 | |
93 | #define TX_DRV_LVL_MUX BIT(4) |
94 | #define TX_DRV_LVL(x) ((x) & 0xf) |
95 | |
96 | #define EMP_EN_MUX BIT(1) |
97 | #define EMP_EN BIT(0) |
98 | |
99 | #define SECONDORDERENABLE BIT(6) |
100 | #define FIRSTORDER_THRESH(x) (((x) & 0x7) << 3) |
101 | #define SECONDORDERGAIN(x) ((x) & 0x7) |
102 | |
103 | #define RX_EQ_GAIN2(x) (((x) & 0xf) << 4) |
104 | #define RX_EQ_GAIN1(x) ((x) & 0xf) |
105 | |
106 | #define SERDES_START BIT(0) |
107 | |
108 | #define BIAS_EN BIT(6) |
109 | #define PLL_EN BIT(5) |
110 | #define SYSCLK_EN BIT(4) |
111 | #define CLKBUF_L_EN BIT(3) |
112 | #define PLL_TXCLK_EN BIT(1) |
113 | #define PLL_RXCLK_EN BIT(0) |
114 | |
115 | #define L0_RX_SIGDET_EN BIT(7) |
116 | #define L0_RX_TERM_MODE(x) (((x) & 3) << 4) |
117 | #define L0_RX_I_EN BIT(1) |
118 | |
119 | #define L0_TX_EN BIT(5) |
120 | #define L0_CLKBUF_EN BIT(4) |
121 | #define L0_TRAN_BIAS_EN BIT(1) |
122 | |
123 | #define L0_RX_EQUALIZE_ENABLE BIT(6) |
124 | #define L0_RESET_TSYNC_EN BIT(4) |
125 | #define L0_DRV_LVL(x) ((x) & 0xf) |
126 | |
127 | #define PWRDN_B BIT(0) |
128 | #define CDR_MAX_CNT(x) ((x) & 0xff) |
129 | |
130 | #define PLLLOCK_CMP(x) ((x) & 0xff) |
131 | |
132 | #define SERDES_START_WAIT_TIMES 100 |
133 | |
134 | struct emac_reg_write { |
135 | unsigned int offset; |
136 | u32 val; |
137 | }; |
138 | |
139 | static void emac_reg_write_all(void __iomem *base, |
140 | const struct emac_reg_write *itr, size_t size) |
141 | { |
142 | size_t i; |
143 | |
144 | for (i = 0; i < size; ++itr, ++i) |
145 | writel(val: itr->val, addr: base + itr->offset); |
146 | } |
147 | |
148 | static const struct emac_reg_write physical_coding_sublayer_programming[] = { |
149 | {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)}, |
150 | {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B}, |
151 | {EMAC_SGMII_PHY_CMN_PWR_CTRL, |
152 | BIAS_EN | SYSCLK_EN | CLKBUF_L_EN | PLL_TXCLK_EN | PLL_RXCLK_EN}, |
153 | {EMAC_SGMII_PHY_TX_PWR_CTRL, L0_TX_EN | L0_CLKBUF_EN | L0_TRAN_BIAS_EN}, |
154 | {EMAC_SGMII_PHY_RX_PWR_CTRL, |
155 | L0_RX_SIGDET_EN | L0_RX_TERM_MODE(1) | L0_RX_I_EN}, |
156 | {EMAC_SGMII_PHY_CMN_PWR_CTRL, |
157 | BIAS_EN | PLL_EN | SYSCLK_EN | CLKBUF_L_EN | PLL_TXCLK_EN | |
158 | PLL_RXCLK_EN}, |
159 | {EMAC_SGMII_PHY_LANE_CTRL1, |
160 | L0_RX_EQUALIZE_ENABLE | L0_RESET_TSYNC_EN | L0_DRV_LVL(15)}, |
161 | }; |
162 | |
163 | static const struct emac_reg_write sysclk_refclk_setting[] = { |
164 | {EMAC_QSERDES_COM_SYSCLK_EN_SEL, SYSCLK_SEL_CMOS}, |
165 | {EMAC_QSERDES_COM_SYS_CLK_CTRL, SYSCLK_CM | SYSCLK_AC_COUPLE}, |
166 | }; |
167 | |
168 | static const struct emac_reg_write pll_setting[] = { |
169 | {EMAC_QSERDES_COM_PLL_IP_SETI, PLL_IPSETI(1)}, |
170 | {EMAC_QSERDES_COM_PLL_CP_SETI, PLL_CPSETI(59)}, |
171 | {EMAC_QSERDES_COM_PLL_IP_SETP, PLL_IPSETP(10)}, |
172 | {EMAC_QSERDES_COM_PLL_CP_SETP, PLL_CPSETP(9)}, |
173 | {EMAC_QSERDES_COM_PLL_CRCTRL, PLL_RCTRL(15) | PLL_CCTRL(11)}, |
174 | {EMAC_QSERDES_COM_PLL_CNTRL, OCP_EN | PLL_DIV_FFEN | PLL_DIV_ORD}, |
175 | {EMAC_QSERDES_COM_DEC_START1, DEC_START1_MUX | DEC_START1(2)}, |
176 | {EMAC_QSERDES_COM_DEC_START2, DEC_START2_MUX | DEC_START2}, |
177 | {EMAC_QSERDES_COM_DIV_FRAC_START1, |
178 | DIV_FRAC_START_MUX | DIV_FRAC_START(85)}, |
179 | {EMAC_QSERDES_COM_DIV_FRAC_START2, |
180 | DIV_FRAC_START_MUX | DIV_FRAC_START(42)}, |
181 | {EMAC_QSERDES_COM_DIV_FRAC_START3, |
182 | DIV_FRAC_START3_MUX | DIV_FRAC_START3(3)}, |
183 | {EMAC_QSERDES_COM_PLLLOCK_CMP1, PLLLOCK_CMP(43)}, |
184 | {EMAC_QSERDES_COM_PLLLOCK_CMP2, PLLLOCK_CMP(104)}, |
185 | {EMAC_QSERDES_COM_PLLLOCK_CMP3, PLLLOCK_CMP(0)}, |
186 | {EMAC_QSERDES_COM_PLLLOCK_CMP_EN, PLLLOCK_CMP_EN}, |
187 | {EMAC_QSERDES_COM_RESETSM_CNTRL, FRQ_TUNE_MODE}, |
188 | }; |
189 | |
190 | static const struct emac_reg_write cdr_setting[] = { |
191 | {EMAC_QSERDES_RX_CDR_CONTROL, |
192 | SECONDORDERENABLE | FIRSTORDER_THRESH(3) | SECONDORDERGAIN(2)}, |
193 | {EMAC_QSERDES_RX_CDR_CONTROL2, |
194 | SECONDORDERENABLE | FIRSTORDER_THRESH(3) | SECONDORDERGAIN(4)}, |
195 | }; |
196 | |
197 | static const struct emac_reg_write tx_rx_setting[] = { |
198 | {EMAC_QSERDES_TX_BIST_MODE_LANENO, 0}, |
199 | {EMAC_QSERDES_TX_TX_DRV_LVL, TX_DRV_LVL_MUX | TX_DRV_LVL(15)}, |
200 | {EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN, EMP_EN_MUX | EMP_EN}, |
201 | {EMAC_QSERDES_TX_TX_EMP_POST1_LVL, |
202 | TX_EMP_POST1_LVL_MUX | TX_EMP_POST1_LVL(1)}, |
203 | {EMAC_QSERDES_RX_RX_EQ_GAIN12, RX_EQ_GAIN2(15) | RX_EQ_GAIN1(15)}, |
204 | {EMAC_QSERDES_TX_LANE_MODE, LANE_MODE(8)}, |
205 | }; |
206 | |
207 | int emac_sgmii_init_fsm9900(struct emac_adapter *adpt) |
208 | { |
209 | struct emac_sgmii *phy = &adpt->phy; |
210 | unsigned int i; |
211 | |
212 | emac_reg_write_all(base: phy->base, itr: physical_coding_sublayer_programming, |
213 | ARRAY_SIZE(physical_coding_sublayer_programming)); |
214 | emac_reg_write_all(base: phy->base, itr: sysclk_refclk_setting, |
215 | ARRAY_SIZE(sysclk_refclk_setting)); |
216 | emac_reg_write_all(base: phy->base, itr: pll_setting, ARRAY_SIZE(pll_setting)); |
217 | emac_reg_write_all(base: phy->base, itr: cdr_setting, ARRAY_SIZE(cdr_setting)); |
218 | emac_reg_write_all(base: phy->base, itr: tx_rx_setting, ARRAY_SIZE(tx_rx_setting)); |
219 | |
220 | /* Power up the Ser/Des engine */ |
221 | writel(SERDES_START, addr: phy->base + EMAC_SGMII_PHY_SERDES_START); |
222 | |
223 | for (i = 0; i < SERDES_START_WAIT_TIMES; i++) { |
224 | if (readl(addr: phy->base + EMAC_QSERDES_COM_RESET_SM) & READY) |
225 | break; |
226 | usleep_range(min: 100, max: 200); |
227 | } |
228 | |
229 | if (i == SERDES_START_WAIT_TIMES) { |
230 | netdev_err(dev: adpt->netdev, format: "error: ser/des failed to start\n" ); |
231 | return -EIO; |
232 | } |
233 | /* Mask out all the SGMII Interrupt */ |
234 | writel(val: 0, addr: phy->base + EMAC_SGMII_PHY_INTERRUPT_MASK); |
235 | |
236 | return 0; |
237 | } |
238 | |