1dfdef5a0Sryan_chen /*
2dfdef5a0Sryan_chen * This program is distributed in the hope that it will be useful,
3dfdef5a0Sryan_chen * but WITHOUT ANY WARRANTY; without even the implied warranty of
4dfdef5a0Sryan_chen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5dfdef5a0Sryan_chen * GNU General Public License for more details.
6dfdef5a0Sryan_chen *
7dfdef5a0Sryan_chen * You should have received a copy of the GNU General Public License
8dfdef5a0Sryan_chen * along with this program; if not, write to the Free Software
9dfdef5a0Sryan_chen * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10dfdef5a0Sryan_chen */
11dfdef5a0Sryan_chen
12dfdef5a0Sryan_chen #include <common.h>
13dfdef5a0Sryan_chen #include <console.h>
14dfdef5a0Sryan_chen #include <bootretry.h>
15dfdef5a0Sryan_chen #include <cli.h>
16dfdef5a0Sryan_chen #include <command.h>
17dfdef5a0Sryan_chen #include <console.h>
18dfdef5a0Sryan_chen
19dfdef5a0Sryan_chen #include <inttypes.h>
20dfdef5a0Sryan_chen #include <mapmem.h>
21dfdef5a0Sryan_chen #include <asm/io.h>
22dfdef5a0Sryan_chen #include <linux/compiler.h>
23dfdef5a0Sryan_chen
24dfdef5a0Sryan_chen #include <common.h>
25dfdef5a0Sryan_chen #include <clk-uclass.h>
26dfdef5a0Sryan_chen #include <dm.h>
27dfdef5a0Sryan_chen #include <asm/io.h>
28dfdef5a0Sryan_chen #include <dm/lists.h>
29dfdef5a0Sryan_chen #include <asm/arch/scu_ast2600.h>
30dfdef5a0Sryan_chen #include <dt-bindings/clock/ast2600-clock.h>
31dfdef5a0Sryan_chen
32dfdef5a0Sryan_chen #include <asm/arch/scu_ast2600.h>
33dfdef5a0Sryan_chen #include <dt-bindings/clock/ast2600-clock.h>
34dfdef5a0Sryan_chen
35dfdef5a0Sryan_chen DECLARE_GLOBAL_DATA_PTR;
36dfdef5a0Sryan_chen
37dfdef5a0Sryan_chen /* ------------------------------------------------------------------------- */
get_ast2600_pll_rate(struct udevice * scu_dev,unsigned int pll_idx)38dfdef5a0Sryan_chen unsigned long get_ast2600_pll_rate(struct udevice *scu_dev, unsigned int pll_idx)
39dfdef5a0Sryan_chen {
40dfdef5a0Sryan_chen struct clk clk;
41dfdef5a0Sryan_chen unsigned long ret = 0;
42dfdef5a0Sryan_chen
43dfdef5a0Sryan_chen clk.id = pll_idx;
44dfdef5a0Sryan_chen ret = clk_request(scu_dev, &clk);
45dfdef5a0Sryan_chen if (ret < 0) {
46dfdef5a0Sryan_chen return ret;
47dfdef5a0Sryan_chen }
48dfdef5a0Sryan_chen
49dfdef5a0Sryan_chen ret = clk_get_rate(&clk);
50dfdef5a0Sryan_chen
51dfdef5a0Sryan_chen clk_free(&clk);
52dfdef5a0Sryan_chen
53dfdef5a0Sryan_chen return ret;
54dfdef5a0Sryan_chen }
55dfdef5a0Sryan_chen
cal_ast2600_28nm_pll_rate(unsigned long pll_rate,unsigned int pll_idx)56dfdef5a0Sryan_chen static int cal_ast2600_28nm_pll_rate(unsigned long pll_rate, unsigned int pll_idx)
57dfdef5a0Sryan_chen {
58dfdef5a0Sryan_chen u32 ulCounter, ulLowLimit, ulHighLimit;
59dfdef5a0Sryan_chen u32 ulData;
60dfdef5a0Sryan_chen u32 ulErrRate = 2;
61dfdef5a0Sryan_chen int i = 0;
62dfdef5a0Sryan_chen
63dfdef5a0Sryan_chen // printf("pll rate : %ld \n", pll_rate);
64dfdef5a0Sryan_chen
65dfdef5a0Sryan_chen ulCounter = (pll_rate/1000) * 512 / 25000 - 1;
66dfdef5a0Sryan_chen ulLowLimit = ulCounter * (100 - ulErrRate) / 100;
67dfdef5a0Sryan_chen ulHighLimit = ulCounter * (100 + ulErrRate) / 100;
68dfdef5a0Sryan_chen writel((ulLowLimit << 16) | ulHighLimit, 0x1e6e2324);
69dfdef5a0Sryan_chen // printf("ulCounter %lx , ulLowLimit %lx , ulHighLimit %lx \n", ulCounter, ulLowLimit, ulHighLimit);
70dfdef5a0Sryan_chen
71*02294997SRyan Chen //1. Set SCU320 = 0x24 use hclk reset freq measurement counter
72*02294997SRyan Chen writel(0x24, 0x1e6e2320);
73dfdef5a0Sryan_chen //2. Wait until SCU320[29:16] = 0
74dfdef5a0Sryan_chen do {
75dfdef5a0Sryan_chen ulData = readl(0x1e6e2320);
76dfdef5a0Sryan_chen mdelay(1);
77dfdef5a0Sryan_chen } while ((ulData & 0x3fff0000) && (i++<1000)); //wait until SCU320[29:16]=0
78dfdef5a0Sryan_chen
79dfdef5a0Sryan_chen if (i>= 1000)
80dfdef5a0Sryan_chen {
81dfdef5a0Sryan_chen printf("Fre Count Eng No idle %x\n", ulData);
82dfdef5a0Sryan_chen return 1;
83dfdef5a0Sryan_chen }
84dfdef5a0Sryan_chen //3. Set SCU320[0] = 1 and SCU320[5:2] = clock for measurement
85dfdef5a0Sryan_chen writel((pll_idx << 2) | 0x1, 0x1e6e2320);
86dfdef5a0Sryan_chen //4. Delay 1ms
87dfdef5a0Sryan_chen mdelay(1);
88dfdef5a0Sryan_chen //5. Set SCU320[1] = 1
89dfdef5a0Sryan_chen writel((pll_idx << 2) | 0x3, 0x1e6e2320);
90dfdef5a0Sryan_chen
91dfdef5a0Sryan_chen //6. Wait until SCU320[6] = 1
92dfdef5a0Sryan_chen i = 0;
93dfdef5a0Sryan_chen do {
94dfdef5a0Sryan_chen ulData = readl(0x1e6e2320);
95dfdef5a0Sryan_chen mdelay(1);
96dfdef5a0Sryan_chen } while ((!(ulData & 0x40)) && (i++<1000));
97dfdef5a0Sryan_chen
98dfdef5a0Sryan_chen if (i>= 1000)
99dfdef5a0Sryan_chen {
100dfdef5a0Sryan_chen printf("PLL Detec No idle %x\n", ulData);
101dfdef5a0Sryan_chen return 1;
102dfdef5a0Sryan_chen }
103dfdef5a0Sryan_chen
104dfdef5a0Sryan_chen //7. Read SCU320[29:16] and calculate the result frequency using following equation
105dfdef5a0Sryan_chen // printf("ulCounter val : %lx \n", (readl(0x1e6e2320) & GENMASK(29, 16)) >> 16);
106dfdef5a0Sryan_chen //When the reference clock CLK25M count from 0 to 512, measure the OSCCLK counting value, then
107dfdef5a0Sryan_chen //OSCCLK frequency = CLK25M / 512 * (SCU320[29:16] + 1)
108dfdef5a0Sryan_chen // printf("rate %ld \n", (25000000 / 512) * (((readl(0x1e6e2320) & GENMASK(29, 16)) >> 16) + 1));
109dfdef5a0Sryan_chen
110dfdef5a0Sryan_chen ulData = readl(0x1e6e2320);
111dfdef5a0Sryan_chen
112dfdef5a0Sryan_chen writel(0x2C, 0x1e6e2320); //disable ring
113dfdef5a0Sryan_chen
114dfdef5a0Sryan_chen if(ulData & 0x80)
115dfdef5a0Sryan_chen return 0;
116dfdef5a0Sryan_chen else
117dfdef5a0Sryan_chen return 1;
118dfdef5a0Sryan_chen }
119dfdef5a0Sryan_chen
cal_ast2600_13nm_pll_rate(unsigned long pll_rate,unsigned int pll_idx)120dfdef5a0Sryan_chen static int cal_ast2600_13nm_pll_rate(unsigned long pll_rate, unsigned int pll_idx)
121dfdef5a0Sryan_chen {
122dfdef5a0Sryan_chen u32 ulData;
123dfdef5a0Sryan_chen u32 ulCounter, ulLowLimit, ulHighLimit;
124dfdef5a0Sryan_chen u32 ulErrRate = 2;
125dfdef5a0Sryan_chen int i = 0;
126dfdef5a0Sryan_chen
127dfdef5a0Sryan_chen // printf("pll rate : %ld \n", pll_rate);
128dfdef5a0Sryan_chen
129dfdef5a0Sryan_chen ulCounter = (pll_rate/1000) * 512 / 25000 - 1;
130dfdef5a0Sryan_chen ulLowLimit = ulCounter * (100 - ulErrRate) / 100;
131dfdef5a0Sryan_chen ulHighLimit = ulCounter * (100 + ulErrRate) / 100;
132dfdef5a0Sryan_chen writel((ulHighLimit << 16) | ulLowLimit, 0x1e6e2334);
133dfdef5a0Sryan_chen // printf("ulCounter %lx , ulLowLimit %lx , ulHighLimit %lx \n", ulCounter, ulLowLimit, ulHighLimit);
134dfdef5a0Sryan_chen
135dfdef5a0Sryan_chen //1. Set SCU320 = 0x30
136dfdef5a0Sryan_chen writel(0x30, 0x1e6e2330);
137dfdef5a0Sryan_chen //2. Wait until SCU320[29:16] = 0
138dfdef5a0Sryan_chen do {
139dfdef5a0Sryan_chen ulData = readl(0x1e6e2330);
140dfdef5a0Sryan_chen mdelay(1);
141dfdef5a0Sryan_chen } while ((ulData & 0x3fff0000) && (i++<1000)); //wait until SCU320[29:16]=0
142dfdef5a0Sryan_chen
143dfdef5a0Sryan_chen if (i>= 1000)
144dfdef5a0Sryan_chen {
145dfdef5a0Sryan_chen printf("Fre Count Eng No idle %x\n", ulData);
146dfdef5a0Sryan_chen return 1;
147dfdef5a0Sryan_chen }
148dfdef5a0Sryan_chen //3. Set SCU320[0] = 1 and SCU320[5:2] = clock for measurement
149dfdef5a0Sryan_chen writel((pll_idx << 2) | 0x1, 0x1e6e2330);
150dfdef5a0Sryan_chen //4. Delay 1ms
151dfdef5a0Sryan_chen mdelay(1);
152dfdef5a0Sryan_chen //5. Set SCU320[1] = 1
153dfdef5a0Sryan_chen writel((pll_idx << 2) | 0x3, 0x1e6e2330);
154dfdef5a0Sryan_chen
155dfdef5a0Sryan_chen //6. Wait until SCU320[6] = 1
156dfdef5a0Sryan_chen i = 0;
157dfdef5a0Sryan_chen do {
158dfdef5a0Sryan_chen ulData = readl(0x1e6e2330);
159dfdef5a0Sryan_chen mdelay(1);
160dfdef5a0Sryan_chen } while ((!(ulData & 0x40)) && (i++<1000));
161dfdef5a0Sryan_chen
162dfdef5a0Sryan_chen if (i>= 1000)
163dfdef5a0Sryan_chen {
164dfdef5a0Sryan_chen printf("PLL Detec No idle %x\n", ulData);
165dfdef5a0Sryan_chen return 1;
166dfdef5a0Sryan_chen }
167dfdef5a0Sryan_chen
168dfdef5a0Sryan_chen //7. Read SCU320[29:16] and calculate the result frequency using following equation
169dfdef5a0Sryan_chen // printf("ulCounter val : %lx \n", (readl(0x1e6e2330) & GENMASK(29, 16)) >> 16);
170dfdef5a0Sryan_chen //When the reference clock CLK25M count from 0 to 512, measure the OSCCLK counting value, then
171dfdef5a0Sryan_chen //OSCCLK frequency = CLK25M / 512 * (SCU320[29:16] + 1)
172dfdef5a0Sryan_chen // printf("rate %ld \n", (25000000 / 512) * (((readl(0x1e6e2330) & GENMASK(29, 16)) >> 16) + 1));
173dfdef5a0Sryan_chen
174dfdef5a0Sryan_chen ulData = readl(0x1e6e2330);
175dfdef5a0Sryan_chen
176dfdef5a0Sryan_chen writel(0x2C, 0x1e6e2330); //disable ring
177dfdef5a0Sryan_chen
178dfdef5a0Sryan_chen if(ulData & 0x80)
179dfdef5a0Sryan_chen return 0;
180dfdef5a0Sryan_chen else
181dfdef5a0Sryan_chen return 1;
182dfdef5a0Sryan_chen }
183dfdef5a0Sryan_chen
184dfdef5a0Sryan_chen
do_ast2600_pll_test(struct udevice * scu_dev,unsigned int pll_idx)185dfdef5a0Sryan_chen int do_ast2600_pll_test(struct udevice *scu_dev, unsigned int pll_idx)
186dfdef5a0Sryan_chen {
187261c9061Sryan_chen int ret = 0;
188dfdef5a0Sryan_chen unsigned long pll_rate = 0;
189dfdef5a0Sryan_chen
190dfdef5a0Sryan_chen switch(pll_idx) {
191dfdef5a0Sryan_chen case 0: //delay cell
192dfdef5a0Sryan_chen printf("Delay Cell : BYPASS \n");
193dfdef5a0Sryan_chen break;
194dfdef5a0Sryan_chen case 1: //nand gate
195dfdef5a0Sryan_chen printf("NAND Gate : BYPASS \n");
196dfdef5a0Sryan_chen break;
197dfdef5a0Sryan_chen case 2:
198dfdef5a0Sryan_chen printf("DLY 16 : BYPASS \n");
199dfdef5a0Sryan_chen break;
200dfdef5a0Sryan_chen case 3:
201dfdef5a0Sryan_chen printf("DLY 32 : BYPASS \n");
202dfdef5a0Sryan_chen break;
203dfdef5a0Sryan_chen case 4:
204dfdef5a0Sryan_chen pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_DPLL);
205261c9061Sryan_chen if(cal_ast2600_28nm_pll_rate(pll_rate/2, 4)) {
206dfdef5a0Sryan_chen printf("D-PLL : Fail \n");
207261c9061Sryan_chen ret = 1;
208261c9061Sryan_chen } else
209dfdef5a0Sryan_chen printf("D-PLL : PASS \n");
210dfdef5a0Sryan_chen break;
211dfdef5a0Sryan_chen case 5:
212dfdef5a0Sryan_chen pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_EPLL);
213dfdef5a0Sryan_chen if(cal_ast2600_28nm_pll_rate(pll_rate/4, 5))
214dfdef5a0Sryan_chen printf("E-PLL : Fail \n");
215dfdef5a0Sryan_chen else
216dfdef5a0Sryan_chen printf("E-PLL : PASS \n");
217dfdef5a0Sryan_chen break;
218c304f173Sryan_chen case 6:
219c304f173Sryan_chen if(readl(0x1e6ed0c0) & BIT(5)) {
220c304f173Sryan_chen switch((readl(0x1e6ed0d0) >> 16) & 0x3) {
221c304f173Sryan_chen case 1: //2.5G 125Mhz
222c304f173Sryan_chen pll_rate = 125000000;
223c304f173Sryan_chen break;
224c304f173Sryan_chen case 2:
225c304f173Sryan_chen pll_rate = 250000000;
226c304f173Sryan_chen break;
227c304f173Sryan_chen }
228c304f173Sryan_chen if(cal_ast2600_28nm_pll_rate(pll_rate, 6))
229c304f173Sryan_chen printf("XPCLK-EP : Fail \n");
230c304f173Sryan_chen else
231c304f173Sryan_chen printf("XPCLK-EP : PASS \n");
232c304f173Sryan_chen } else
233c304f173Sryan_chen printf("XPCLK-EP : Fail 0 \n");
234c304f173Sryan_chen break;
235dfdef5a0Sryan_chen case 8:
236dfdef5a0Sryan_chen pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_MPLL);
237261c9061Sryan_chen if(cal_ast2600_28nm_pll_rate(pll_rate/2, 8)) {
238dfdef5a0Sryan_chen printf("MCLK : Fail \n");
239261c9061Sryan_chen ret = 1;
240261c9061Sryan_chen } else
241dfdef5a0Sryan_chen printf("MCLK : PASS \n");
242dfdef5a0Sryan_chen break;
243c304f173Sryan_chen case 9:
244c304f173Sryan_chen pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_AHB);
245c304f173Sryan_chen if(cal_ast2600_28nm_pll_rate(pll_rate, 9)) {
246c304f173Sryan_chen printf("HCLK-28nm : Fail \n");
247c304f173Sryan_chen ret = 1;
248c304f173Sryan_chen } else
249c304f173Sryan_chen printf("HCLK-28nm : PASS \n");
250c304f173Sryan_chen break;
251dfdef5a0Sryan_chen case 16:
252dfdef5a0Sryan_chen pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_APLL);
253261c9061Sryan_chen if(cal_ast2600_13nm_pll_rate(pll_rate/8, 0)) {
254dfdef5a0Sryan_chen printf("APLL : Fail \n");
255261c9061Sryan_chen ret = 1;
256261c9061Sryan_chen } else
257dfdef5a0Sryan_chen printf("APLL : PASS \n");
258dfdef5a0Sryan_chen break;
259dfdef5a0Sryan_chen case 17:
260dfdef5a0Sryan_chen pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_AHB);
261261c9061Sryan_chen if(cal_ast2600_13nm_pll_rate(pll_rate, 1)) {
262c304f173Sryan_chen printf("HCLK-13nm : Fail \n");
263261c9061Sryan_chen ret = 1;
264261c9061Sryan_chen } else
265c304f173Sryan_chen printf("HCLK-13nm : PASS \n");
266dfdef5a0Sryan_chen break;
267dfdef5a0Sryan_chen case 18:
268dfdef5a0Sryan_chen pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_APB2);
269dfdef5a0Sryan_chen if(cal_ast2600_13nm_pll_rate(pll_rate, 2))
270dfdef5a0Sryan_chen printf("PCLK : Fail \n");
271dfdef5a0Sryan_chen else
272dfdef5a0Sryan_chen printf("PCLK : PASS \n");
273dfdef5a0Sryan_chen break;
274dfdef5a0Sryan_chen }
275dfdef5a0Sryan_chen
276dfdef5a0Sryan_chen return ret;
277dfdef5a0Sryan_chen }
278dfdef5a0Sryan_chen
do_aspeed_full_pll_test(struct udevice * scu_dev)279dfdef5a0Sryan_chen int do_aspeed_full_pll_test(struct udevice *scu_dev)
280dfdef5a0Sryan_chen {
281261c9061Sryan_chen int i = 0;
282261c9061Sryan_chen int ret = 0;
283261c9061Sryan_chen for(i = 0; i < 32; i++) {
284261c9061Sryan_chen ret += do_ast2600_pll_test(scu_dev, i);
285261c9061Sryan_chen }
286261c9061Sryan_chen
287261c9061Sryan_chen printf("**************************************************** \n");
288261c9061Sryan_chen if(ret)
289261c9061Sryan_chen printf("PLL Test : Fail \n");
290261c9061Sryan_chen else
291261c9061Sryan_chen printf("PLL Test : Pass \n");
292261c9061Sryan_chen printf("**************************************************** \n");
293dfdef5a0Sryan_chen
294dfdef5a0Sryan_chen return 1;
295dfdef5a0Sryan_chen }
296dfdef5a0Sryan_chen
297dfdef5a0Sryan_chen static int
do_aspeed_plltest(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])298dfdef5a0Sryan_chen do_aspeed_plltest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
299dfdef5a0Sryan_chen {
300dfdef5a0Sryan_chen struct udevice *scu_dev;
301dfdef5a0Sryan_chen char *pll_cmd;
302dfdef5a0Sryan_chen unsigned long pll_idx;
303dfdef5a0Sryan_chen int ret;
304dfdef5a0Sryan_chen
305dfdef5a0Sryan_chen ret = uclass_get_device_by_driver(UCLASS_CLK,
306dfdef5a0Sryan_chen DM_GET_DRIVER(aspeed_scu), &scu_dev);
307dfdef5a0Sryan_chen if (ret)
308dfdef5a0Sryan_chen return ret;
309dfdef5a0Sryan_chen
310dfdef5a0Sryan_chen if (argc != 2)
311dfdef5a0Sryan_chen return CMD_RET_USAGE;
312dfdef5a0Sryan_chen
313dfdef5a0Sryan_chen pll_cmd = argv[1];
314dfdef5a0Sryan_chen
315dfdef5a0Sryan_chen if (!strcmp(pll_cmd, "full"))
316dfdef5a0Sryan_chen ret = do_aspeed_full_pll_test(scu_dev);
317dfdef5a0Sryan_chen else {
318dfdef5a0Sryan_chen pll_idx = strtoul(argv[1], 0, 0);
319dfdef5a0Sryan_chen ret = do_ast2600_pll_test(scu_dev, pll_idx);
320dfdef5a0Sryan_chen }
321dfdef5a0Sryan_chen
322dfdef5a0Sryan_chen return ret;
323dfdef5a0Sryan_chen }
324dfdef5a0Sryan_chen
325dfdef5a0Sryan_chen U_BOOT_CMD(
326dfdef5a0Sryan_chen plltest, 3, 0, do_aspeed_plltest,
327dfdef5a0Sryan_chen "ASPEED PLL test",
328dfdef5a0Sryan_chen "ping d2 - Ping to check if the device at the targeted address can respond\n"
329dfdef5a0Sryan_chen ""
330dfdef5a0Sryan_chen );
331