blob: 7e78d6e2d6ce6659b598b69cf101429e206ee8e8 [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
Tom Rinidec7ea02024-05-20 13:35:03 -060010#include <config.h> /* core U-Boot definitions */
Alexander Dahle543b1b2022-10-07 14:19:59 +020011#include <log.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060012#include <time.h>
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020013#include <altera.h>
14#include <ACEX1K.h> /* ACEX device family */
Simon Glassdbd79542020-05-10 11:40:11 -060015#include <linux/delay.h>
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020016
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020017/* Note: The assumption is that we cannot possibly run fast enough to
18 * overrun the device (the Slave Parallel mode can free run at 50MHz).
Tom Rini88d86ec2022-12-04 10:03:57 -050019 * If there is a need to operate slower, define CFG_FPGA_DELAY in
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020020 * the board config file to slow things down.
21 */
Tom Rini88d86ec2022-12-04 10:03:57 -050022#ifndef CFG_FPGA_DELAY
23#define CFG_FPGA_DELAY()
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020024#endif
25
Tom Rini6a5dccc2022-11-16 13:10:41 -050026#ifndef CFG_SYS_FPGA_WAIT
27#define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ / 10 /* 100 ms */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020028#endif
29
Wolfgang Denk74f9b382011-07-30 13:33:49 +000030static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize);
31static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020032/* static int CYC2_ps_info( Altera_desc *desc ); */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020033
34/* ------------------------------------------------------------------------- */
35/* CYCLON2 Generic Implementation */
Wolfgang Denk74f9b382011-07-30 13:33:49 +000036int CYC2_load(Altera_desc *desc, const void *buf, size_t bsize)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020037{
38 int ret_val = FPGA_FAIL;
39
40 switch (desc->iface) {
41 case passive_serial:
Alexander Dahle543b1b2022-10-07 14:19:59 +020042 log_debug("Launching Passive Serial Loader\n");
Alexander Dahl246bc022019-06-28 14:41:21 +020043 ret_val = CYC2_ps_load(desc, buf, bsize);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020044 break;
45
Michael Jonesd846bb52011-07-14 23:09:41 +000046 case fast_passive_parallel:
47 /* Fast Passive Parallel (FPP) and PS only differ in what is
48 * done in the write() callback. Use the existing PS load
49 * function for FPP, too.
50 */
Alexander Dahle543b1b2022-10-07 14:19:59 +020051 log_debug("Launching Fast Passive Parallel Loader\n");
Michael Jonesd846bb52011-07-14 23:09:41 +000052 ret_val = CYC2_ps_load(desc, buf, bsize);
53 break;
54
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020055 /* Add new interface types here */
56
57 default:
Alexander Dahl246bc022019-06-28 14:41:21 +020058 printf("%s: Unsupported interface type, %d\n",
59 __func__, desc->iface);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020060 }
61
62 return ret_val;
63}
64
Wolfgang Denk74f9b382011-07-30 13:33:49 +000065int CYC2_dump(Altera_desc *desc, const void *buf, size_t bsize)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020066{
67 int ret_val = FPGA_FAIL;
68
69 switch (desc->iface) {
70 case passive_serial:
Alexander Dahle543b1b2022-10-07 14:19:59 +020071 log_debug("Launching Passive Serial Dump\n");
Alexander Dahl246bc022019-06-28 14:41:21 +020072 ret_val = CYC2_ps_dump(desc, buf, bsize);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020073 break;
74
75 /* Add new interface types here */
76
77 default:
Alexander Dahl246bc022019-06-28 14:41:21 +020078 printf("%s: Unsupported interface type, %d\n",
79 __func__, desc->iface);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020080 }
81
82 return ret_val;
83}
84
Alexander Dahl246bc022019-06-28 14:41:21 +020085int CYC2_info(Altera_desc *desc)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020086{
87 return FPGA_SUCCESS;
88}
89
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020090/* ------------------------------------------------------------------------- */
Alexander Dahl246bc022019-06-28 14:41:21 +020091/* CYCLON2 Passive Serial Generic Implementation */
Wolfgang Denk74f9b382011-07-30 13:33:49 +000092static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020093{
94 int ret_val = FPGA_FAIL; /* assume the worst */
95 Altera_CYC2_Passive_Serial_fns *fn = desc->iface_fns;
96 int ret = 0;
97
Alexander Dahle543b1b2022-10-07 14:19:59 +020098 log_debug("start with interface functions @ 0x%p\n", fn);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +020099
100 if (fn) {
101 int cookie = desc->cookie; /* make a local copy */
102 unsigned long ts; /* timestamp */
103
Alexander Dahle543b1b2022-10-07 14:19:59 +0200104 log_debug("Function Table:\n"
105 "ptr:\t0x%p\n"
106 "struct: 0x%p\n"
107 "config:\t0x%p\n"
108 "status:\t0x%p\n"
109 "write:\t0x%p\n"
110 "done:\t0x%p\n\n",
111 &fn, fn, fn->config, fn->status,
112 fn->write, fn->done);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200113#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Alexander Dahl246bc022019-06-28 14:41:21 +0200114 printf("Loading FPGA Device %d...", cookie);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200115#endif
116
117 /*
118 * Run the pre configuration function if there is one.
119 */
Alexander Dahl246bc022019-06-28 14:41:21 +0200120 if (*fn->pre)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200121 (*fn->pre) (cookie);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200122
123 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700124 (*fn->config) (false, true, cookie); /* De-assert nCONFIG */
Stephan Gatzka67f32912012-10-22 23:11:41 +0000125 udelay(100);
York Sun4a598092013-04-01 11:29:11 -0700126 (*fn->config) (true, true, cookie); /* Assert nCONFIG */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200127
128 udelay(2); /* T_cfg > 2us */
129
130 /* Wait for nSTATUS to be asserted */
Alexander Dahl246bc022019-06-28 14:41:21 +0200131 ts = get_timer(0); /* get current time */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200132 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500133 CFG_FPGA_DELAY();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500134 if (get_timer(ts) > CFG_SYS_FPGA_WAIT) {
Alexander Dahl246bc022019-06-28 14:41:21 +0200135 /* check the time */
136 puts("** Timeout waiting for STATUS to go high.\n");
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200137 (*fn->abort) (cookie);
138 return FPGA_FAIL;
139 }
140 } while (!(*fn->status) (cookie));
141
142 /* Get ready for the burn */
Tom Rini88d86ec2022-12-04 10:03:57 -0500143 CFG_FPGA_DELAY();
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200144
York Sun4a598092013-04-01 11:29:11 -0700145 ret = (*fn->write) (buf, bsize, true, cookie);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200146 if (ret) {
Alexander Dahl246bc022019-06-28 14:41:21 +0200147 puts("** Write failed.\n");
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200148 (*fn->abort) (cookie);
149 return FPGA_FAIL;
150 }
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200151#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200152 puts(" OK? ...");
153#endif
154
Tom Rini88d86ec2022-12-04 10:03:57 -0500155 CFG_FPGA_DELAY();
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200156
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200157#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Alexander Dahl246bc022019-06-28 14:41:21 +0200158 putc(' '); /* terminate the dotted line */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200159#endif
160
Alexander Dahla8da71c2019-06-28 14:41:22 +0200161 /*
162 * Checking FPGA's CONF_DONE signal - correctly booted ?
163 */
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200164
Alexander Dahla8da71c2019-06-28 14:41:22 +0200165 if (!(*fn->done) (cookie)) {
166 puts("** Booting failed! CONF_DONE is still deasserted.\n");
167 (*fn->abort) (cookie);
168 return FPGA_FAIL;
169 }
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200170#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Alexander Dahla8da71c2019-06-28 14:41:22 +0200171 puts(" OK\n");
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200172#endif
173
Alexander Dahla8da71c2019-06-28 14:41:22 +0200174 ret_val = FPGA_SUCCESS;
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200175
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200176#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Alexander Dahla8da71c2019-06-28 14:41:22 +0200177 if (ret_val == FPGA_SUCCESS)
178 puts("Done.\n");
179 else
180 puts("Fail.\n");
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200181#endif
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200182
Alexander Dahld52678c2019-06-28 14:41:23 +0200183 /*
184 * Run the post configuration function if there is one.
185 */
186 if (*fn->post)
187 (*fn->post) (cookie);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200188 } else {
Alexander Dahl246bc022019-06-28 14:41:21 +0200189 printf("%s: NULL Interface function table!\n", __func__);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200190 }
191
192 return ret_val;
193}
194
Wolfgang Denk74f9b382011-07-30 13:33:49 +0000195static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize)
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200196{
197 /* Readback is only available through the Slave Parallel and */
198 /* boundary-scan interfaces. */
Alexander Dahl246bc022019-06-28 14:41:21 +0200199 printf("%s: Passive Serial Dumping is unavailable\n", __func__);
Stefan Roese5f1cf2d2006-08-15 14:15:51 +0200200 return FPGA_FAIL;
201}