blob: f264ff8c0ecd564de6b7065b9c8e443d17eefa0f [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Stefan Roese5f1cf2d2006-08-15 14:15:51 +02002/*
3 * (C) Copyright 2006
4 * Heiko Schocher, hs@denx.de
5 * Based on ACE1XK.c
Stefan Roese5f1cf2d2006-08-15 14:15:51 +02006 */
7
Alexander Dahle543b1b2022-10-07 14:19:59 +02008#define LOG_CATEGORY UCLASS_FPGA
9
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020010#include <common.h> /* core U-Boot definitions */
Alexander Dahle543b1b2022-10-07 14:19:59 +020011#include <log.h>
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020012#include <altera.h>
13#include <ACEX1K.h> /* ACEX device family */
Simon Glassdbd79542020-05-10 11:40:11 -060014#include <linux/delay.h>
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020015
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020016/* Note: The assumption is that we cannot possibly run fast enough to
17 * overrun the device (the Slave Parallel mode can free run at 50MHz).
18 * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
19 * the board config file to slow things down.
20 */
21#ifndef CONFIG_FPGA_DELAY
22#define CONFIG_FPGA_DELAY()
23#endif
24
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020025#ifndef CONFIG_SYS_FPGA_WAIT
Alexander Dahl246bc022019-06-28 14:41:21 +020026#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ / 10 /* 100 ms */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020027#endif
28
Wolfgang Denk74f9b382011-07-30 13:33:49 +000029static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize);
30static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020031/* static int CYC2_ps_info( Altera_desc *desc ); */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020032
33/* ------------------------------------------------------------------------- */
34/* CYCLON2 Generic Implementation */
Wolfgang Denk74f9b382011-07-30 13:33:49 +000035int CYC2_load(Altera_desc *desc, const void *buf, size_t bsize)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020036{
37 int ret_val = FPGA_FAIL;
38
39 switch (desc->iface) {
40 case passive_serial:
Alexander Dahle543b1b2022-10-07 14:19:59 +020041 log_debug("Launching Passive Serial Loader\n");
Alexander Dahl246bc022019-06-28 14:41:21 +020042 ret_val = CYC2_ps_load(desc, buf, bsize);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020043 break;
44
Michael Jonesd846bb52011-07-14 23:09:41 +000045 case fast_passive_parallel:
46 /* Fast Passive Parallel (FPP) and PS only differ in what is
47 * done in the write() callback. Use the existing PS load
48 * function for FPP, too.
49 */
Alexander Dahle543b1b2022-10-07 14:19:59 +020050 log_debug("Launching Fast Passive Parallel Loader\n");
Michael Jonesd846bb52011-07-14 23:09:41 +000051 ret_val = CYC2_ps_load(desc, buf, bsize);
52 break;
53
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020054 /* Add new interface types here */
55
56 default:
Alexander Dahl246bc022019-06-28 14:41:21 +020057 printf("%s: Unsupported interface type, %d\n",
58 __func__, desc->iface);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020059 }
60
61 return ret_val;
62}
63
Wolfgang Denk74f9b382011-07-30 13:33:49 +000064int CYC2_dump(Altera_desc *desc, const void *buf, size_t bsize)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020065{
66 int ret_val = FPGA_FAIL;
67
68 switch (desc->iface) {
69 case passive_serial:
Alexander Dahle543b1b2022-10-07 14:19:59 +020070 log_debug("Launching Passive Serial Dump\n");
Alexander Dahl246bc022019-06-28 14:41:21 +020071 ret_val = CYC2_ps_dump(desc, buf, bsize);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020072 break;
73
74 /* Add new interface types here */
75
76 default:
Alexander Dahl246bc022019-06-28 14:41:21 +020077 printf("%s: Unsupported interface type, %d\n",
78 __func__, desc->iface);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020079 }
80
81 return ret_val;
82}
83
Alexander Dahl246bc022019-06-28 14:41:21 +020084int CYC2_info(Altera_desc *desc)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020085{
86 return FPGA_SUCCESS;
87}
88
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020089/* ------------------------------------------------------------------------- */
Alexander Dahl246bc022019-06-28 14:41:21 +020090/* CYCLON2 Passive Serial Generic Implementation */
Wolfgang Denk74f9b382011-07-30 13:33:49 +000091static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020092{
93 int ret_val = FPGA_FAIL; /* assume the worst */
94 Altera_CYC2_Passive_Serial_fns *fn = desc->iface_fns;
95 int ret = 0;
96
Alexander Dahle543b1b2022-10-07 14:19:59 +020097 log_debug("start with interface functions @ 0x%p\n", fn);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020098
99 if (fn) {
100 int cookie = desc->cookie; /* make a local copy */
101 unsigned long ts; /* timestamp */
102
Alexander Dahle543b1b2022-10-07 14:19:59 +0200103 log_debug("Function Table:\n"
104 "ptr:\t0x%p\n"
105 "struct: 0x%p\n"
106 "config:\t0x%p\n"
107 "status:\t0x%p\n"
108 "write:\t0x%p\n"
109 "done:\t0x%p\n\n",
110 &fn, fn, fn->config, fn->status,
111 fn->write, fn->done);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200112#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Alexander Dahl246bc022019-06-28 14:41:21 +0200113 printf("Loading FPGA Device %d...", cookie);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200114#endif
115
116 /*
117 * Run the pre configuration function if there is one.
118 */
Alexander Dahl246bc022019-06-28 14:41:21 +0200119 if (*fn->pre)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200120 (*fn->pre) (cookie);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200121
122 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700123 (*fn->config) (false, true, cookie); /* De-assert nCONFIG */
Stephan Gatzka67f32912012-10-22 23:11:41 +0000124 udelay(100);
York Sun4a598092013-04-01 11:29:11 -0700125 (*fn->config) (true, true, cookie); /* Assert nCONFIG */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200126
127 udelay(2); /* T_cfg > 2us */
128
129 /* Wait for nSTATUS to be asserted */
Alexander Dahl246bc022019-06-28 14:41:21 +0200130 ts = get_timer(0); /* get current time */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200131 do {
Alexander Dahl246bc022019-06-28 14:41:21 +0200132 CONFIG_FPGA_DELAY();
133 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
134 /* check the time */
135 puts("** Timeout waiting for STATUS to go high.\n");
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200136 (*fn->abort) (cookie);
137 return FPGA_FAIL;
138 }
139 } while (!(*fn->status) (cookie));
140
141 /* Get ready for the burn */
Alexander Dahl246bc022019-06-28 14:41:21 +0200142 CONFIG_FPGA_DELAY();
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200143
York Sun4a598092013-04-01 11:29:11 -0700144 ret = (*fn->write) (buf, bsize, true, cookie);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200145 if (ret) {
Alexander Dahl246bc022019-06-28 14:41:21 +0200146 puts("** Write failed.\n");
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200147 (*fn->abort) (cookie);
148 return FPGA_FAIL;
149 }
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200150#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200151 puts(" OK? ...");
152#endif
153
Alexander Dahl246bc022019-06-28 14:41:21 +0200154 CONFIG_FPGA_DELAY();
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200155
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200156#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Alexander Dahl246bc022019-06-28 14:41:21 +0200157 putc(' '); /* terminate the dotted line */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200158#endif
159
Alexander Dahla8da71c2019-06-28 14:41:22 +0200160 /*
161 * Checking FPGA's CONF_DONE signal - correctly booted ?
162 */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200163
Alexander Dahla8da71c2019-06-28 14:41:22 +0200164 if (!(*fn->done) (cookie)) {
165 puts("** Booting failed! CONF_DONE is still deasserted.\n");
166 (*fn->abort) (cookie);
167 return FPGA_FAIL;
168 }
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200169#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Alexander Dahla8da71c2019-06-28 14:41:22 +0200170 puts(" OK\n");
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200171#endif
172
Alexander Dahla8da71c2019-06-28 14:41:22 +0200173 ret_val = FPGA_SUCCESS;
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200174
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200175#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Alexander Dahla8da71c2019-06-28 14:41:22 +0200176 if (ret_val == FPGA_SUCCESS)
177 puts("Done.\n");
178 else
179 puts("Fail.\n");
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200180#endif
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200181
Alexander Dahld52678c2019-06-28 14:41:23 +0200182 /*
183 * Run the post configuration function if there is one.
184 */
185 if (*fn->post)
186 (*fn->post) (cookie);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200187 } else {
Alexander Dahl246bc022019-06-28 14:41:21 +0200188 printf("%s: NULL Interface function table!\n", __func__);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200189 }
190
191 return ret_val;
192}
193
Wolfgang Denk74f9b382011-07-30 13:33:49 +0000194static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200195{
196 /* Readback is only available through the Slave Parallel and */
197 /* boundary-scan interfaces. */
Alexander Dahl246bc022019-06-28 14:41:21 +0200198 printf("%s: Passive Serial Dumping is unavailable\n", __func__);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200199 return FPGA_FAIL;
200}