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 }
208