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