1/******************************************************************************
2**
3** FILE NAME    : ifxmips_pcie_phy.c
4** PROJECT      : IFX UEIP for VRX200
5** MODULES      : PCIe PHY sub module
6**
7** DATE         : 14 May 2009
8** AUTHOR       : Lei Chuanhua
9** DESCRIPTION  : PCIe Root Complex Driver
10** COPYRIGHT    :       Copyright (c) 2009
11**                      Infineon Technologies AG
12**                      Am Campeon 1-12, 85579 Neubiberg, Germany
13**
14**    This program is free software; you can redistribute it and/or modify
15**    it under the terms of the GNU General Public License as published by
16**    the Free Software Foundation; either version 2 of the License, or
17**    (at your option) any later version.
18** HISTORY
19** $Version $Date        $Author         $Comment
20** 0.0.1    14 May,2009  Lei Chuanhua    Initial version
21*******************************************************************************/
22/*!
23 \file ifxmips_pcie_phy.c
24 \ingroup IFX_PCIE
25 \brief PCIe PHY PLL register programming source file
26*/
27#include <linux/types.h>
28#include <linux/kernel.h>
29#include <asm/paccess.h>
30#include <linux/delay.h>
31
32#include "pcie-lantiq.h"
33
34/* PCIe PDI only supports 16 bit operation */
35
36#define IFX_PCIE_PHY_REG_WRITE16(__addr, __data) \
37    ((*(volatile u16 *) (__addr)) = (__data))
38
39#define IFX_PCIE_PHY_REG_READ16(__addr)  \
40    (*(volatile u16 *) (__addr))
41
42#define IFX_PCIE_PHY_REG16(__addr)   \
43    (*(volatile u16 *) (__addr))
44
45#define IFX_PCIE_PHY_REG(__reg, __value, __mask) do { \
46    u16 read_data;                                    \
47    u16 write_data;                                   \
48    read_data = IFX_PCIE_PHY_REG_READ16((__reg));      \
49    write_data = (read_data & ((u16)~(__mask))) | (((u16)(__value)) & ((u16)(__mask)));\
50    IFX_PCIE_PHY_REG_WRITE16((__reg), write_data);               \
51} while (0)
52
53#define IFX_PCIE_PLL_TIMEOUT 1000 /* Tunnable */
54
55static void
56pcie_phy_comm_setup(int pcie_port)
57{
58   /* PLL Setting */
59    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL1(pcie_port), 0x120e, 0xFFFF);
60
61    /* increase the bias reference voltage */
62    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x39D7, 0xFFFF);
63    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x0900, 0xFFFF);
64
65    /* Endcnt */
66    IFX_PCIE_PHY_REG(PCIE_PHY_RX1_EI(pcie_port), 0x0004, 0xFFFF);
67    IFX_PCIE_PHY_REG(PCIE_PHY_RX1_A_CTRL(pcie_port), 0x6803, 0xFFFF);
68
69    /* force */
70    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL1(pcie_port), 0x0008, 0x0008);
71
72    /* predrv_ser_en */
73    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_A_CTRL2(pcie_port), 0x0706, 0xFFFF);
74
75    /* ctrl_lim */
76    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL3(pcie_port), 0x1FFF, 0xFFFF);
77
78    /* ctrl */
79    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_A_CTRL1(pcie_port), 0x0800, 0xFF00);
80
81    /* predrv_ser_en */
82    IFX_PCIE_PHY_REG(PCIE_PHY_TX2_A_CTRL2(pcie_port), 0x4702, 0x7F00);
83
84    /* RTERM*/
85    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL2(pcie_port), 0x2e00, 0xFFFF);
86
87    /* Improved 100MHz clock output  */
88    IFX_PCIE_PHY_REG(PCIE_PHY_TX2_CTRL2(pcie_port), 0x3096, 0xFFFF);
89    IFX_PCIE_PHY_REG(PCIE_PHY_TX2_A_CTRL2(pcie_port), 0x4707, 0xFFFF);
90
91    /* Reduced CDR BW to avoid glitches */
92    IFX_PCIE_PHY_REG(PCIE_PHY_RX1_CDR(pcie_port), 0x0235, 0xFFFF);
93}
94
95#ifdef CONFIG_IFX_PCIE_PHY_36MHZ_MODE
96static void
97pcie_phy_36mhz_mode_setup(int pcie_port)
98{
99    IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d enter\n", __func__, pcie_port);
100
101    /* en_ext_mmd_div_ratio */
102    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0002);
103
104    /* ext_mmd_div_ratio*/
105    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0070);
106
107    /* pll_ensdm */
108    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0200, 0x0200);
109
110    /* en_const_sdm */
111    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0100, 0x0100);
112
113    /* mmd */
114    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x2000, 0xe000);
115
116    /* lf_mode */
117    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x0000, 0x4000);
118
119    /* const_sdm */
120    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL1(pcie_port), 0x38e4, 0xFFFF);
121
122    /* const sdm */
123    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x00ee, 0x00FF);
124
125    /* pllmod */
126    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL7(pcie_port), 0x0002, 0xFFFF);
127    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL6(pcie_port), 0x3a04, 0xFFFF);
128    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL5(pcie_port), 0xfae3, 0xFFFF);
129    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL4(pcie_port), 0x1b72, 0xFFFF);
130
131    IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d exit\n", __func__, pcie_port);
132}
133#endif /* CONFIG_IFX_PCIE_PHY_36MHZ_MODE */
134
135#ifdef CONFIG_IFX_PCIE_PHY_36MHZ_SSC_MODE
136static void
137pcie_phy_36mhz_ssc_mode_setup(int pcie_port)
138{
139    IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d enter\n", __func__, pcie_port);
140
141    /* PLL Setting */
142    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL1(pcie_port), 0x120e, 0xFFFF);
143
144    /* Increase the bias reference voltage */
145    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x39D7, 0xFFFF);
146    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x0900, 0xFFFF);
147
148    /* Endcnt */
149    IFX_PCIE_PHY_REG(PCIE_PHY_RX1_EI(pcie_port), 0x0004, 0xFFFF);
150    IFX_PCIE_PHY_REG(PCIE_PHY_RX1_A_CTRL(pcie_port), 0x6803, 0xFFFF);
151
152    /* Force */
153    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL1(pcie_port), 0x0008, 0x0008);
154
155    /* Predrv_ser_en */
156    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_A_CTRL2(pcie_port), 0x0706, 0xFFFF);
157
158    /* ctrl_lim */
159    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL3(pcie_port), 0x1FFF, 0xFFFF);
160
161    /* ctrl */
162    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_A_CTRL1(pcie_port), 0x0800, 0xFF00);
163
164    /* predrv_ser_en */
165    IFX_PCIE_PHY_REG(PCIE_PHY_TX2_A_CTRL2(pcie_port), 0x4702, 0x7F00);
166
167    /* RTERM*/
168    IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL2(pcie_port), 0x2e00, 0xFFFF);
169
170    /* en_ext_mmd_div_ratio */
171    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0002);
172
173    /* ext_mmd_div_ratio*/
174    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0070);
175
176    /* pll_ensdm */
177    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0400, 0x0400);
178
179    /* en_const_sdm */
180    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0200, 0x0200);
181
182    /* mmd */
183    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x2000, 0xe000);
184
185    /* lf_mode */
186    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x0000, 0x4000);
187
188    /* const_sdm */
189    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL1(pcie_port), 0x38e4, 0xFFFF);
190
191    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0000, 0x0100);
192    /* const sdm */
193    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x00ee, 0x00FF);
194
195    /* pllmod */
196    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL7(pcie_port), 0x0002, 0xFFFF);
197    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL6(pcie_port), 0x3a04, 0xFFFF);
198    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL5(pcie_port), 0xfae3, 0xFFFF);
199    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL4(pcie_port), 0x1c72, 0xFFFF);
200
201    /* improved 100MHz clock output  */
202    IFX_PCIE_PHY_REG(PCIE_PHY_TX2_CTRL2(pcie_port), 0x3096, 0xFFFF);
203    IFX_PCIE_PHY_REG(PCIE_PHY_TX2_A_CTRL2(pcie_port), 0x4707, 0xFFFF);
204
205    /* reduced CDR BW to avoid glitches */
206    IFX_PCIE_PHY_REG(PCIE_PHY_RX1_CDR(pcie_port), 0x0235, 0xFFFF);
207
208    IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d exit\n", __func__, pcie_port);
209}
210#endif /* CONFIG_IFX_PCIE_PHY_36MHZ_SSC_MODE */
211
212#ifdef CONFIG_IFX_PCIE_PHY_25MHZ_MODE
213static void
214pcie_phy_25mhz_mode_setup(int pcie_port)
215{
216    IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d enter\n", __func__, pcie_port);
217    /* en_const_sdm */
218    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0100, 0x0100);
219
220    /* pll_ensdm */
221    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0000, 0x0200);
222
223    /* en_ext_mmd_div_ratio*/
224    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0002, 0x0002);
225
226    /* ext_mmd_div_ratio*/
227    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0040, 0x0070);
228
229    /* mmd */
230    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x6000, 0xe000);
231
232    /* lf_mode */
233    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x4000, 0x4000);
234
235    IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d exit\n", __func__, pcie_port);
236}
237#endif /* CONFIG_IFX_PCIE_PHY_25MHZ_MODE */
238
239#ifdef CONFIG_IFX_PCIE_PHY_100MHZ_MODE
240static void
241pcie_phy_100mhz_mode_setup(int pcie_port)
242{
243    IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d enter\n", __func__, pcie_port);
244    /* en_ext_mmd_div_ratio */
245    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0002);
246
247    /* ext_mmd_div_ratio*/
248    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0070);
249
250    /* pll_ensdm */
251    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0200, 0x0200);
252
253    /* en_const_sdm */
254    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0100, 0x0100);
255
256    /* mmd */
257    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x2000, 0xe000);
258
259    /* lf_mode */
260    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x0000, 0x4000);
261
262    /* const_sdm */
263    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL1(pcie_port), 0x38e4, 0xFFFF);
264
265    /* const sdm */
266    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x00ee, 0x00FF);
267
268    /* pllmod */
269    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL7(pcie_port), 0x0002, 0xFFFF);
270    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL6(pcie_port), 0x3a04, 0xFFFF);
271    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL5(pcie_port), 0xfae3, 0xFFFF);
272    IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL4(pcie_port), 0x1b72, 0xFFFF);
273
274    IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d exit\n", __func__, pcie_port);
275}
276#endif /* CONFIG_IFX_PCIE_PHY_100MHZ_MODE */
277
278static int
279pcie_phy_wait_startup_ready(int pcie_port)
280{
281    int i;
282
283    for (i = 0; i < IFX_PCIE_PLL_TIMEOUT; i++) {
284        if ((IFX_PCIE_PHY_REG16(PCIE_PHY_PLL_STATUS(pcie_port)) & 0x0040) != 0) {
285            break;
286        }
287        udelay(10);
288    }
289    if (i >= IFX_PCIE_PLL_TIMEOUT) {
290        printk(KERN_ERR "%s PLL Link timeout\n", __func__);
291        return -1;
292    }
293    return 0;
294}
295
296static void
297pcie_phy_load_enable(int pcie_port, int slice)
298{
299    /* Set the load_en of tx/rx slice to '1' */
300    switch (slice) {
301        case 1:
302            IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL1(pcie_port), 0x0010, 0x0010);
303            break;
304        case 2:
305            IFX_PCIE_PHY_REG(PCIE_PHY_TX2_CTRL1(pcie_port), 0x0010, 0x0010);
306            break;
307        case 3:
308            IFX_PCIE_PHY_REG(PCIE_PHY_RX1_CTRL1(pcie_port), 0x0002, 0x0002);
309            break;
310    }
311}
312
313static void
314pcie_phy_load_disable(int pcie_port, int slice)
315{
316    /* set the load_en of tx/rx slice to '0' */
317    switch (slice) {
318        case 1:
319            IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL1(pcie_port), 0x0000, 0x0010);
320            break;
321        case 2:
322            IFX_PCIE_PHY_REG(PCIE_PHY_TX2_CTRL1(pcie_port), 0x0000, 0x0010);
323            break;
324        case 3:
325            IFX_PCIE_PHY_REG(PCIE_PHY_RX1_CTRL1(pcie_port), 0x0000, 0x0002);
326            break;
327    }
328}
329
330static void pcie_phy_load_war(int pcie_port)
331{
332	int slice;
333
334	for (slice = 1; slice < 4; slice++) {
335		pcie_phy_load_enable(pcie_port, slice);
336		udelay(1);
337		pcie_phy_load_disable(pcie_port, slice);
338	}
339}
340
341static void pcie_phy_tx2_modulation(int pcie_port)
342{
343	IFX_PCIE_PHY_REG(PCIE_PHY_TX2_MOD1(pcie_port), 0x1FFE, 0xFFFF);
344	IFX_PCIE_PHY_REG(PCIE_PHY_TX2_MOD2(pcie_port), 0xFFFE, 0xFFFF);
345	IFX_PCIE_PHY_REG(PCIE_PHY_TX2_MOD3(pcie_port), 0x0601, 0xFFFF);
346	mdelay(1);
347	IFX_PCIE_PHY_REG(PCIE_PHY_TX2_MOD3(pcie_port), 0x0001, 0xFFFF);
348}
349
350static void pcie_phy_tx1_modulation(int pcie_port)
351{
352	IFX_PCIE_PHY_REG(PCIE_PHY_TX1_MOD1(pcie_port), 0x1FFE, 0xFFFF);
353	IFX_PCIE_PHY_REG(PCIE_PHY_TX1_MOD2(pcie_port), 0xFFFE, 0xFFFF);
354	IFX_PCIE_PHY_REG(PCIE_PHY_TX1_MOD3(pcie_port), 0x0601, 0xFFFF);
355	mdelay(1);
356	IFX_PCIE_PHY_REG(PCIE_PHY_TX1_MOD3(pcie_port), 0x0001, 0xFFFF);
357}
358
359static void pcie_phy_tx_modulation_war(int pcie_port)
360{
361	int i;
362#define PCIE_PHY_MODULATION_NUM 5
363	for (i = 0; i < PCIE_PHY_MODULATION_NUM; i++) {
364		pcie_phy_tx2_modulation(pcie_port);
365		pcie_phy_tx1_modulation(pcie_port);
366	}
367#undef PCIE_PHY_MODULATION_NUM
368}
369
370void pcie_phy_clock_mode_setup(int pcie_port)
371{
372	pcie_pdi_big_endian(pcie_port);
373
374	/* Enable PDI to access PCIe PHY register */
375	pcie_pdi_pmu_enable(pcie_port);
376
377	/* Configure PLL and PHY clock */
378	pcie_phy_comm_setup(pcie_port);
379
380#ifdef CONFIG_IFX_PCIE_PHY_36MHZ_MODE
381	pcie_phy_36mhz_mode_setup(pcie_port);
382#elif defined(CONFIG_IFX_PCIE_PHY_36MHZ_SSC_MODE)
383	pcie_phy_36mhz_ssc_mode_setup(pcie_port);
384#elif defined(CONFIG_IFX_PCIE_PHY_25MHZ_MODE)
385	pcie_phy_25mhz_mode_setup(pcie_port);
386#elif defined (CONFIG_IFX_PCIE_PHY_100MHZ_MODE)
387	pcie_phy_100mhz_mode_setup(pcie_port);
388#else
389	#error "PCIE PHY Clock Mode must be chosen first!!!!"
390#endif /* CONFIG_IFX_PCIE_PHY_36MHZ_MODE */
391
392	/* Enable PCIe PHY and make PLL setting take effect */
393	pcie_phy_pmu_enable(pcie_port);
394
395	/* Check if we are in startup_ready status */
396	pcie_phy_wait_startup_ready(pcie_port);
397
398	pcie_phy_load_war(pcie_port);
399
400	/* Apply TX modulation workarounds */
401	pcie_phy_tx_modulation_war(pcie_port);
402
403#ifdef IFX_PCI_PHY_REG_DUMP
404	IFX_PCIE_PRINT(PCIE_MSG_PHY, "Modified PHY register dump\n");
405	pcie_phy_reg_dump(pcie_port);
406#endif
407}
408
409