]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/common/idt8t49n222a_serdes_clk.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / board / freescale / common / idt8t49n222a_serdes_clk.c
1 /*
2  * Copyright 2013 Freescale Semiconductor, Inc.
3  * Author: Shaveta Leekha <shaveta@freescale.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include "idt8t49n222a_serdes_clk.h"
9
10 #define DEVICE_ID_REG           0x00
11
12 static int check_pll_status(u8 idt_addr)
13 {
14         u8 val = 0;
15         int ret;
16
17         ret = i2c_read(idt_addr, 0x17, 1, &val, 1);
18         if (ret < 0) {
19                 printf("IDT:0x%x could not read status register from device.\n",
20                         idt_addr);
21                 return ret;
22         }
23
24         if (val & 0x04) {
25                 debug("idt8t49n222a PLL is LOCKED: %x\n", val);
26         } else {
27                 printf("idt8t49n222a PLL is not LOCKED: %x\n", val);
28                 return -1;
29         }
30
31         return 0;
32 }
33
34 int set_serdes_refclk(u8 idt_addr, u8 serdes_num,
35                         enum serdes_refclk refclk1,
36                         enum serdes_refclk refclk2, u8 feedback)
37 {
38         u8 dev_id = 0;
39         int i, ret;
40
41         debug("IDT:Configuring idt8t49n222a device at I2C address: 0x%2x\n",
42                 idt_addr);
43
44         ret = i2c_read(idt_addr, DEVICE_ID_REG, 1, &dev_id, 1);
45         if (ret < 0) {
46                 debug("IDT:0x%x could not read DEV_ID from device.\n",
47                         idt_addr);
48                 return ret;
49         }
50
51         if ((dev_id != 0x00) && (dev_id != 0x24) && (dev_id != 0x2a)) {
52                 debug("IDT: device at address 0x%x is not idt8t49n222a.\n",
53                         idt_addr);
54         }
55
56         if (serdes_num != 1 && serdes_num != 2) {
57                 debug("serdes_num should be 1 for SerDes1 and"
58                         " 2 for SerDes2.\n");
59                 return -1;
60         }
61
62         if ((refclk1 == SERDES_REFCLK_122_88 && refclk2 != SERDES_REFCLK_122_88)
63                 || (refclk1 != SERDES_REFCLK_122_88
64                         && refclk2 == SERDES_REFCLK_122_88)) {
65                 debug("Only one refclk at 122.88MHz is not supported."
66                         " Please set both refclk1 & refclk2 to 122.88MHz"
67                         " or both not to 122.88MHz.\n");
68                 return -1;
69         }
70
71         if (refclk1 != SERDES_REFCLK_100 && refclk1 != SERDES_REFCLK_122_88
72                                         && refclk1 != SERDES_REFCLK_125
73                                         && refclk1 != SERDES_REFCLK_156_25) {
74                 debug("refclk1 should be 100MHZ, 122.88MHz, 125MHz"
75                         " or 156.25MHz.\n");
76                 return -1;
77         }
78
79         if (refclk2 != SERDES_REFCLK_100 && refclk2 != SERDES_REFCLK_122_88
80                                         && refclk2 != SERDES_REFCLK_125
81                                         && refclk2 != SERDES_REFCLK_156_25) {
82                 debug("refclk2 should be 100MHZ, 122.88MHz, 125MHz"
83                         " or 156.25MHz.\n");
84                 return -1;
85         }
86
87         if (feedback != 0 && feedback != 1) {
88                 debug("valid values for feedback are 0(default) or 1.\n");
89                 return -1;
90         }
91
92         /* Configuring IDT for output refclks as
93          * Refclk1 = 122.88MHz  Refclk2 = 122.88MHz
94          */
95         if (refclk1 == SERDES_REFCLK_122_88 &&
96                         refclk2 == SERDES_REFCLK_122_88) {
97                 printf("Setting refclk1:122.88 and refclk2:122.88\n");
98                 for (i = 0; i < NUM_IDT_REGS; i++)
99                         i2c_reg_write(idt_addr, idt_conf_122_88[i][0],
100                                                 idt_conf_122_88[i][1]);
101
102                 if (feedback) {
103                         for (i = 0; i < NUM_IDT_REGS_FEEDBACK; i++)
104                                 i2c_reg_write(idt_addr,
105                                         idt_conf_122_88_feedback[i][0],
106                                         idt_conf_122_88_feedback[i][1]);
107                 }
108         }
109
110         if (refclk1 != SERDES_REFCLK_122_88 &&
111                         refclk2 != SERDES_REFCLK_122_88) {
112                 for (i = 0; i < NUM_IDT_REGS; i++)
113                         i2c_reg_write(idt_addr, idt_conf_not_122_88[i][0],
114                                                 idt_conf_not_122_88[i][1]);
115         }
116
117         /* Configuring IDT for output refclks as
118          * Refclk1 = 100MHz  Refclk2 = 125MHz
119          */
120         if (refclk1 == SERDES_REFCLK_100 && refclk2 == SERDES_REFCLK_125) {
121                 printf("Setting refclk1:100 and refclk2:125\n");
122                 i2c_reg_write(idt_addr, 0x11, 0x10);
123         }
124
125         /* Configuring IDT for output refclks as
126          * Refclk1 = 125MHz  Refclk2 = 125MHz
127          */
128         if (refclk1 == SERDES_REFCLK_125 && refclk2 == SERDES_REFCLK_125) {
129                 printf("Setting refclk1:125 and refclk2:125\n");
130                 i2c_reg_write(idt_addr, 0x10, 0x10);
131                 i2c_reg_write(idt_addr, 0x11, 0x10);
132         }
133
134         /* Configuring IDT for output refclks as
135          * Refclk1 = 125MHz  Refclk2 = 100MHz
136          */
137         if (refclk1 == SERDES_REFCLK_125 && refclk2 == SERDES_REFCLK_100) {
138                 printf("Setting refclk1:125 and refclk2:100\n");
139                 i2c_reg_write(idt_addr, 0x10, 0x10);
140         }
141
142         /* Configuring IDT for output refclks as
143          * Refclk1 = 156.25MHz  Refclk2 = 156.25MHz
144          */
145         if (refclk1 == SERDES_REFCLK_156_25 &&
146                         refclk2 == SERDES_REFCLK_156_25) {
147                 printf("Setting refclk1:156.25 and refclk2:156.25\n");
148                 for (i = 0; i < NUM_IDT_REGS_156_25; i++)
149                         i2c_reg_write(idt_addr, idt_conf_156_25[i][0],
150                                                 idt_conf_156_25[i][1]);
151         }
152
153         /* Configuring IDT for output refclks as
154          * Refclk1 = 100MHz  Refclk2 = 156.25MHz
155          */
156         if (refclk1 == SERDES_REFCLK_100 &&
157                         refclk2 == SERDES_REFCLK_156_25) {
158                 printf("Setting refclk1:100 and refclk2:156.25\n");
159                 for (i = 0; i < NUM_IDT_REGS_156_25; i++)
160                         i2c_reg_write(idt_addr, idt_conf_100_156_25[i][0],
161                                                 idt_conf_100_156_25[i][1]);
162         }
163
164         /* Configuring IDT for output refclks as
165          * Refclk1 = 125MHz  Refclk2 = 156.25MHz
166          */
167         if (refclk1 == SERDES_REFCLK_125 &&
168                         refclk2 == SERDES_REFCLK_156_25) {
169                 printf("Setting refclk1:125 and refclk2:156.25\n");
170                 for (i = 0; i < NUM_IDT_REGS_156_25; i++)
171                         i2c_reg_write(idt_addr, idt_conf_125_156_25[i][0],
172                                                 idt_conf_125_156_25[i][1]);
173         }
174
175         /* Configuring IDT for output refclks as
176          * Refclk1 = 156.25MHz  Refclk2 = 100MHz
177          */
178         if (refclk1 == SERDES_REFCLK_156_25 &&
179                         refclk2 == SERDES_REFCLK_100) {
180                 printf("Setting refclk1:156.25 and refclk2:100\n");
181                 for (i = 0; i < NUM_IDT_REGS_156_25; i++)
182                         i2c_reg_write(idt_addr, idt_conf_156_25_100[i][0],
183                                                 idt_conf_156_25_100[i][1]);
184         }
185
186         /* Configuring IDT for output refclks as
187          * Refclk1 = 156.25MHz  Refclk2 = 125MHz
188          */
189         if (refclk1 == SERDES_REFCLK_156_25 &&
190                         refclk2 == SERDES_REFCLK_125) {
191                 printf("Setting refclk1:156.25 and refclk2:125\n");
192                 for (i = 0; i < NUM_IDT_REGS_156_25; i++)
193                         i2c_reg_write(idt_addr, idt_conf_156_25_125[i][0],
194                                                 idt_conf_156_25_125[i][1]);
195         }
196
197         /* waiting for maximum of 1 second if PLL doesn'r get locked
198          * initially. then check the status again.
199          */
200         if (check_pll_status(idt_addr)) {
201                 mdelay(1000);
202                 if (check_pll_status(idt_addr))
203                         return -1;
204         }
205
206         return 0;
207 }