Commit 230fe9b202ff0ca396ad9a564816cc87d42daa6e
Committed by
Marek Vasut
1 parent
604364e42c
Exists in
v2017.01-smarct4x
and in
37 other branches
arm: socfpga: fpga: Add SoCFPGA FPGA programming interface
Add code necessary to program the FPGA part of SoCFPGA from U-Boot with an RBF blob. This patch also integrates the code into the FPGA driver framework in U-Boot so it can be used via the 'fpga' command. Signed-off-by: Pavel Machek <pavel@denx.de> Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chin Liang See <clsee@altera.com> Cc: Dinh Nguyen <dinguyen@altera.com> Cc: Albert Aribaud <albert.u.boot@aribaud.net> Cc: Tom Rini <trini@ti.com> Cc: Wolfgang Denk <wd@denx.de> Cc: Pavel Machek <pavel@denx.de> V2: Move the not-CPU specific stuff into drivers/fpga/ and base this on the cleaned up altera FPGA support.
Showing 8 changed files with 504 additions and 1 deletions Side-by-side Diff
arch/arm/cpu/armv7/socfpga/Makefile
... | ... | @@ -8,6 +8,7 @@ |
8 | 8 | # |
9 | 9 | |
10 | 10 | obj-y := lowlevel_init.o |
11 | -obj-y += misc.o timer.o reset_manager.o system_manager.o clock_manager.o | |
11 | +obj-y += misc.o timer.o reset_manager.o system_manager.o clock_manager.o \ | |
12 | + fpga_manager.o | |
12 | 13 | obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o scan_manager.o |
arch/arm/cpu/armv7/socfpga/fpga_manager.c
1 | +/* | |
2 | + * Copyright (C) 2012 Altera Corporation <www.altera.com> | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * This file contains only support functions used also by the SoCFPGA | |
6 | + * platform code, the real meat is located in drivers/fpga/socfpga.c . | |
7 | + * | |
8 | + * SPDX-License-Identifier: BSD-3-Clause | |
9 | + */ | |
10 | + | |
11 | +#include <common.h> | |
12 | +#include <asm/io.h> | |
13 | +#include <asm/errno.h> | |
14 | +#include <asm/arch/fpga_manager.h> | |
15 | +#include <asm/arch/reset_manager.h> | |
16 | +#include <asm/arch/system_manager.h> | |
17 | + | |
18 | +DECLARE_GLOBAL_DATA_PTR; | |
19 | + | |
20 | +/* Timeout count */ | |
21 | +#define FPGA_TIMEOUT_CNT 0x1000000 | |
22 | + | |
23 | +static struct socfpga_fpga_manager *fpgamgr_regs = | |
24 | + (struct socfpga_fpga_manager *)SOCFPGA_FPGAMGRREGS_ADDRESS; | |
25 | + | |
26 | +/* Check whether FPGA Init_Done signal is high */ | |
27 | +static int is_fpgamgr_initdone_high(void) | |
28 | +{ | |
29 | + unsigned long val; | |
30 | + | |
31 | + val = readl(&fpgamgr_regs->gpio_ext_porta); | |
32 | + return val & FPGAMGRREGS_MON_GPIO_EXT_PORTA_ID_MASK; | |
33 | +} | |
34 | + | |
35 | +/* Get the FPGA mode */ | |
36 | +int fpgamgr_get_mode(void) | |
37 | +{ | |
38 | + unsigned long val; | |
39 | + | |
40 | + val = readl(&fpgamgr_regs->stat); | |
41 | + return val & FPGAMGRREGS_STAT_MODE_MASK; | |
42 | +} | |
43 | + | |
44 | +/* Check whether FPGA is ready to be accessed */ | |
45 | +int fpgamgr_test_fpga_ready(void) | |
46 | +{ | |
47 | + /* Check for init done signal */ | |
48 | + if (!is_fpgamgr_initdone_high()) | |
49 | + return 0; | |
50 | + | |
51 | + /* Check again to avoid false glitches */ | |
52 | + if (!is_fpgamgr_initdone_high()) | |
53 | + return 0; | |
54 | + | |
55 | + if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_USERMODE) | |
56 | + return 0; | |
57 | + | |
58 | + return 1; | |
59 | +} | |
60 | + | |
61 | +/* Poll until FPGA is ready to be accessed or timeout occurred */ | |
62 | +int fpgamgr_poll_fpga_ready(void) | |
63 | +{ | |
64 | + unsigned long i; | |
65 | + | |
66 | + /* If FPGA is blank, wait till WD invoke warm reset */ | |
67 | + for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { | |
68 | + /* check for init done signal */ | |
69 | + if (!is_fpgamgr_initdone_high()) | |
70 | + continue; | |
71 | + /* check again to avoid false glitches */ | |
72 | + if (!is_fpgamgr_initdone_high()) | |
73 | + continue; | |
74 | + return 1; | |
75 | + } | |
76 | + | |
77 | + return 0; | |
78 | +} |
arch/arm/cpu/armv7/socfpga/misc.c
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | |
7 | 7 | #include <common.h> |
8 | 8 | #include <asm/io.h> |
9 | +#include <altera.h> | |
9 | 10 | #include <miiphy.h> |
10 | 11 | #include <netdev.h> |
11 | 12 | #include <asm/arch/reset_manager.h> |
... | ... | @@ -93,6 +94,39 @@ |
93 | 94 | } |
94 | 95 | #endif |
95 | 96 | |
97 | +#ifdef CONFIG_FPGA | |
98 | +/* | |
99 | + * FPGA programming support for SoC FPGA Cyclone V | |
100 | + */ | |
101 | +static Altera_desc altera_fpga[] = { | |
102 | + { | |
103 | + /* Family */ | |
104 | + Altera_SoCFPGA, | |
105 | + /* Interface type */ | |
106 | + fast_passive_parallel, | |
107 | + /* No limitation as additional data will be ignored */ | |
108 | + -1, | |
109 | + /* No device function table */ | |
110 | + NULL, | |
111 | + /* Base interface address specified in driver */ | |
112 | + NULL, | |
113 | + /* No cookie implementation */ | |
114 | + 0 | |
115 | + }, | |
116 | +}; | |
117 | + | |
118 | +/* add device descriptor to FPGA device table */ | |
119 | +static void socfpga_fpga_add(void) | |
120 | +{ | |
121 | + int i; | |
122 | + fpga_init(); | |
123 | + for (i = 0; i < ARRAY_SIZE(altera_fpga); i++) | |
124 | + fpga_add(fpga_altera, &altera_fpga[i]); | |
125 | +} | |
126 | +#else | |
127 | +static inline void socfpga_fpga_add(void) {} | |
128 | +#endif | |
129 | + | |
96 | 130 | int arch_cpu_init(void) |
97 | 131 | { |
98 | 132 | /* |
... | ... | @@ -108,6 +142,8 @@ |
108 | 142 | |
109 | 143 | int misc_init_r(void) |
110 | 144 | { |
145 | + /* Add device descriptor to FPGA device table */ | |
146 | + socfpga_fpga_add(); | |
111 | 147 | return 0; |
112 | 148 | } |
arch/arm/include/asm/arch-socfpga/fpga_manager.h
1 | +/* | |
2 | + * Copyright (C) 2012 Altera Corporation <www.altera.com> | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * SPDX-License-Identifier: BSD-3-Clause | |
6 | + */ | |
7 | + | |
8 | +#ifndef _FPGA_MANAGER_H_ | |
9 | +#define _FPGA_MANAGER_H_ | |
10 | + | |
11 | +#include <altera.h> | |
12 | + | |
13 | +struct socfpga_fpga_manager { | |
14 | + /* FPGA Manager Module */ | |
15 | + u32 stat; /* 0x00 */ | |
16 | + u32 ctrl; | |
17 | + u32 dclkcnt; | |
18 | + u32 dclkstat; | |
19 | + u32 gpo; /* 0x10 */ | |
20 | + u32 gpi; | |
21 | + u32 misci; /* 0x18 */ | |
22 | + u32 _pad_0x1c_0x82c[517]; | |
23 | + | |
24 | + /* Configuration Monitor (MON) Registers */ | |
25 | + u32 gpio_inten; /* 0x830 */ | |
26 | + u32 gpio_intmask; | |
27 | + u32 gpio_inttype_level; | |
28 | + u32 gpio_int_polarity; | |
29 | + u32 gpio_intstatus; /* 0x840 */ | |
30 | + u32 gpio_raw_intstatus; | |
31 | + u32 _pad_0x848; | |
32 | + u32 gpio_porta_eoi; | |
33 | + u32 gpio_ext_porta; /* 0x850 */ | |
34 | + u32 _pad_0x854_0x85c[3]; | |
35 | + u32 gpio_1s_sync; /* 0x860 */ | |
36 | + u32 _pad_0x864_0x868[2]; | |
37 | + u32 gpio_ver_id_code; | |
38 | + u32 gpio_config_reg2; /* 0x870 */ | |
39 | + u32 gpio_config_reg1; | |
40 | +}; | |
41 | + | |
42 | +#define FPGAMGRREGS_STAT_MODE_MASK 0x7 | |
43 | +#define FPGAMGRREGS_STAT_MSEL_MASK 0xf8 | |
44 | +#define FPGAMGRREGS_STAT_MSEL_LSB 3 | |
45 | + | |
46 | +#define FPGAMGRREGS_CTRL_CFGWDTH_MASK 0x200 | |
47 | +#define FPGAMGRREGS_CTRL_AXICFGEN_MASK 0x100 | |
48 | +#define FPGAMGRREGS_CTRL_NCONFIGPULL_MASK 0x4 | |
49 | +#define FPGAMGRREGS_CTRL_NCE_MASK 0x2 | |
50 | +#define FPGAMGRREGS_CTRL_EN_MASK 0x1 | |
51 | +#define FPGAMGRREGS_CTRL_CDRATIO_LSB 6 | |
52 | + | |
53 | +#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_CRC_MASK 0x8 | |
54 | +#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_ID_MASK 0x4 | |
55 | +#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK 0x2 | |
56 | +#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK 0x1 | |
57 | + | |
58 | +/* FPGA Mode */ | |
59 | +#define FPGAMGRREGS_MODE_FPGAOFF 0x0 | |
60 | +#define FPGAMGRREGS_MODE_RESETPHASE 0x1 | |
61 | +#define FPGAMGRREGS_MODE_CFGPHASE 0x2 | |
62 | +#define FPGAMGRREGS_MODE_INITPHASE 0x3 | |
63 | +#define FPGAMGRREGS_MODE_USERMODE 0x4 | |
64 | +#define FPGAMGRREGS_MODE_UNKNOWN 0x5 | |
65 | + | |
66 | +/* FPGA CD Ratio Value */ | |
67 | +#define CDRATIO_x1 0x0 | |
68 | +#define CDRATIO_x2 0x1 | |
69 | +#define CDRATIO_x4 0x2 | |
70 | +#define CDRATIO_x8 0x3 | |
71 | + | |
72 | +/* SoCFPGA support functions */ | |
73 | +int fpgamgr_test_fpga_ready(void); | |
74 | +int fpgamgr_poll_fpga_ready(void); | |
75 | +int fpgamgr_get_mode(void); | |
76 | + | |
77 | +#endif /* _FPGA_MANAGER_H_ */ |
drivers/fpga/Makefile
drivers/fpga/altera.c
... | ... | @@ -37,6 +37,9 @@ |
37 | 37 | { Altera_StratixII, "StratixII", StratixII_load, |
38 | 38 | StratixII_dump, StratixII_info }, |
39 | 39 | #endif |
40 | +#if defined(CONFIG_FPGA_SOCFPGA) | |
41 | + { Altera_SoCFPGA, "SoC FPGA", socfpga_load, NULL, NULL }, | |
42 | +#endif | |
40 | 43 | }; |
41 | 44 | |
42 | 45 | static int altera_validate(Altera_desc *desc, const char *fn) |
drivers/fpga/socfpga.c
1 | +/* | |
2 | + * Copyright (C) 2012 Altera Corporation <www.altera.com> | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * SPDX-License-Identifier: BSD-3-Clause | |
6 | + */ | |
7 | + | |
8 | +#include <common.h> | |
9 | +#include <asm/io.h> | |
10 | +#include <asm/errno.h> | |
11 | +#include <asm/arch/fpga_manager.h> | |
12 | +#include <asm/arch/reset_manager.h> | |
13 | +#include <asm/arch/system_manager.h> | |
14 | + | |
15 | +DECLARE_GLOBAL_DATA_PTR; | |
16 | + | |
17 | +/* Timeout count */ | |
18 | +#define FPGA_TIMEOUT_CNT 0x1000000 | |
19 | + | |
20 | +static struct socfpga_fpga_manager *fpgamgr_regs = | |
21 | + (struct socfpga_fpga_manager *)SOCFPGA_FPGAMGRREGS_ADDRESS; | |
22 | +static struct socfpga_system_manager *sysmgr_regs = | |
23 | + (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; | |
24 | + | |
25 | +/* Set CD ratio */ | |
26 | +static void fpgamgr_set_cd_ratio(unsigned long ratio) | |
27 | +{ | |
28 | + clrsetbits_le32(&fpgamgr_regs->ctrl, | |
29 | + 0x3 << FPGAMGRREGS_CTRL_CDRATIO_LSB, | |
30 | + (ratio & 0x3) << FPGAMGRREGS_CTRL_CDRATIO_LSB); | |
31 | +} | |
32 | + | |
33 | +static int fpgamgr_dclkcnt_set(unsigned long cnt) | |
34 | +{ | |
35 | + unsigned long i; | |
36 | + | |
37 | + /* Clear any existing done status */ | |
38 | + if (readl(&fpgamgr_regs->dclkstat)) | |
39 | + writel(0x1, &fpgamgr_regs->dclkstat); | |
40 | + | |
41 | + /* Write the dclkcnt */ | |
42 | + writel(cnt, &fpgamgr_regs->dclkcnt); | |
43 | + | |
44 | + /* Wait till the dclkcnt done */ | |
45 | + for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { | |
46 | + if (!readl(&fpgamgr_regs->dclkstat)) | |
47 | + continue; | |
48 | + | |
49 | + writel(0x1, &fpgamgr_regs->dclkstat); | |
50 | + return 0; | |
51 | + } | |
52 | + | |
53 | + return -ETIMEDOUT; | |
54 | +} | |
55 | + | |
56 | +/* Start the FPGA programming by initialize the FPGA Manager */ | |
57 | +static int fpgamgr_program_init(void) | |
58 | +{ | |
59 | + unsigned long msel, i; | |
60 | + | |
61 | + /* Get the MSEL value */ | |
62 | + msel = readl(&fpgamgr_regs->stat); | |
63 | + msel &= FPGAMGRREGS_STAT_MSEL_MASK; | |
64 | + msel >>= FPGAMGRREGS_STAT_MSEL_LSB; | |
65 | + | |
66 | + /* | |
67 | + * Set the cfg width | |
68 | + * If MSEL[3] = 1, cfg width = 32 bit | |
69 | + */ | |
70 | + if (msel & 0x8) { | |
71 | + setbits_le32(&fpgamgr_regs->ctrl, | |
72 | + FPGAMGRREGS_CTRL_CFGWDTH_MASK); | |
73 | + | |
74 | + /* To determine the CD ratio */ | |
75 | + /* MSEL[1:0] = 0, CD Ratio = 1 */ | |
76 | + if ((msel & 0x3) == 0x0) | |
77 | + fpgamgr_set_cd_ratio(CDRATIO_x1); | |
78 | + /* MSEL[1:0] = 1, CD Ratio = 4 */ | |
79 | + else if ((msel & 0x3) == 0x1) | |
80 | + fpgamgr_set_cd_ratio(CDRATIO_x4); | |
81 | + /* MSEL[1:0] = 2, CD Ratio = 8 */ | |
82 | + else if ((msel & 0x3) == 0x2) | |
83 | + fpgamgr_set_cd_ratio(CDRATIO_x8); | |
84 | + | |
85 | + } else { /* MSEL[3] = 0 */ | |
86 | + clrbits_le32(&fpgamgr_regs->ctrl, | |
87 | + FPGAMGRREGS_CTRL_CFGWDTH_MASK); | |
88 | + | |
89 | + /* To determine the CD ratio */ | |
90 | + /* MSEL[1:0] = 0, CD Ratio = 1 */ | |
91 | + if ((msel & 0x3) == 0x0) | |
92 | + fpgamgr_set_cd_ratio(CDRATIO_x1); | |
93 | + /* MSEL[1:0] = 1, CD Ratio = 2 */ | |
94 | + else if ((msel & 0x3) == 0x1) | |
95 | + fpgamgr_set_cd_ratio(CDRATIO_x2); | |
96 | + /* MSEL[1:0] = 2, CD Ratio = 4 */ | |
97 | + else if ((msel & 0x3) == 0x2) | |
98 | + fpgamgr_set_cd_ratio(CDRATIO_x4); | |
99 | + } | |
100 | + | |
101 | + /* To enable FPGA Manager configuration */ | |
102 | + clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCE_MASK); | |
103 | + | |
104 | + /* To enable FPGA Manager drive over configuration line */ | |
105 | + setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK); | |
106 | + | |
107 | + /* Put FPGA into reset phase */ | |
108 | + setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK); | |
109 | + | |
110 | + /* (1) wait until FPGA enter reset phase */ | |
111 | + for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { | |
112 | + if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_RESETPHASE) | |
113 | + break; | |
114 | + } | |
115 | + | |
116 | + /* If not in reset state, return error */ | |
117 | + if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_RESETPHASE) { | |
118 | + puts("FPGA: Could not reset\n"); | |
119 | + return -1; | |
120 | + } | |
121 | + | |
122 | + /* Release FPGA from reset phase */ | |
123 | + clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK); | |
124 | + | |
125 | + /* (2) wait until FPGA enter configuration phase */ | |
126 | + for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { | |
127 | + if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_CFGPHASE) | |
128 | + break; | |
129 | + } | |
130 | + | |
131 | + /* If not in configuration state, return error */ | |
132 | + if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_CFGPHASE) { | |
133 | + puts("FPGA: Could not configure\n"); | |
134 | + return -2; | |
135 | + } | |
136 | + | |
137 | + /* Clear all interrupts in CB Monitor */ | |
138 | + writel(0xFFF, &fpgamgr_regs->gpio_porta_eoi); | |
139 | + | |
140 | + /* Enable AXI configuration */ | |
141 | + setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK); | |
142 | + | |
143 | + return 0; | |
144 | +} | |
145 | + | |
146 | +/* Write the RBF data to FPGA Manager */ | |
147 | +static void fpgamgr_program_write(const void *rbf_data, unsigned long rbf_size) | |
148 | +{ | |
149 | + uint32_t src = (uint32_t)rbf_data; | |
150 | + uint32_t dst = SOCFPGA_FPGAMGRDATA_ADDRESS; | |
151 | + | |
152 | + /* Number of loops for 32-byte long copying. */ | |
153 | + uint32_t loops32 = rbf_size / 32; | |
154 | + /* Number of loops for 4-byte long copying + trailing bytes */ | |
155 | + uint32_t loops4 = DIV_ROUND_UP(rbf_size % 32, 4); | |
156 | + | |
157 | + asm volatile( | |
158 | + "1: ldmia %0!, {r0-r7}\n" | |
159 | + " stmia %1!, {r0-r7}\n" | |
160 | + " sub %1, #32\n" | |
161 | + " subs %2, #1\n" | |
162 | + " bne 1b\n" | |
163 | + "2: ldr %2, [%0], #4\n" | |
164 | + " str %2, [%1]\n" | |
165 | + " subs %3, #1\n" | |
166 | + " bne 2b\n" | |
167 | + : "+r"(src), "+r"(dst), "+r"(loops32), "+r"(loops4) : | |
168 | + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "cc"); | |
169 | +} | |
170 | + | |
171 | +/* Ensure the FPGA entering config done */ | |
172 | +static int fpgamgr_program_poll_cd(void) | |
173 | +{ | |
174 | + const uint32_t mask = FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK | | |
175 | + FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK; | |
176 | + unsigned long reg, i; | |
177 | + | |
178 | + /* (3) wait until full config done */ | |
179 | + for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { | |
180 | + reg = readl(&fpgamgr_regs->gpio_ext_porta); | |
181 | + | |
182 | + /* Config error */ | |
183 | + if (!(reg & mask)) { | |
184 | + printf("FPGA: Configuration error.\n"); | |
185 | + return -3; | |
186 | + } | |
187 | + | |
188 | + /* Config done without error */ | |
189 | + if (reg & mask) | |
190 | + break; | |
191 | + } | |
192 | + | |
193 | + /* Timeout happened, return error */ | |
194 | + if (i == FPGA_TIMEOUT_CNT) { | |
195 | + printf("FPGA: Timeout waiting for program.\n"); | |
196 | + return -4; | |
197 | + } | |
198 | + | |
199 | + /* Disable AXI configuration */ | |
200 | + clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK); | |
201 | + | |
202 | + return 0; | |
203 | +} | |
204 | + | |
205 | +/* Ensure the FPGA entering init phase */ | |
206 | +static int fpgamgr_program_poll_initphase(void) | |
207 | +{ | |
208 | + unsigned long i; | |
209 | + | |
210 | + /* Additional clocks for the CB to enter initialization phase */ | |
211 | + if (fpgamgr_dclkcnt_set(0x4)) | |
212 | + return -5; | |
213 | + | |
214 | + /* (4) wait until FPGA enter init phase or user mode */ | |
215 | + for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { | |
216 | + if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_INITPHASE) | |
217 | + break; | |
218 | + if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE) | |
219 | + break; | |
220 | + } | |
221 | + | |
222 | + /* If not in configuration state, return error */ | |
223 | + if (i == FPGA_TIMEOUT_CNT) | |
224 | + return -6; | |
225 | + | |
226 | + return 0; | |
227 | +} | |
228 | + | |
229 | +/* Ensure the FPGA entering user mode */ | |
230 | +static int fpgamgr_program_poll_usermode(void) | |
231 | +{ | |
232 | + unsigned long i; | |
233 | + | |
234 | + /* Additional clocks for the CB to exit initialization phase */ | |
235 | + if (fpgamgr_dclkcnt_set(0x5000)) | |
236 | + return -7; | |
237 | + | |
238 | + /* (5) wait until FPGA enter user mode */ | |
239 | + for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { | |
240 | + if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE) | |
241 | + break; | |
242 | + } | |
243 | + /* If not in configuration state, return error */ | |
244 | + if (i == FPGA_TIMEOUT_CNT) | |
245 | + return -8; | |
246 | + | |
247 | + /* To release FPGA Manager drive over configuration line */ | |
248 | + clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK); | |
249 | + | |
250 | + return 0; | |
251 | +} | |
252 | + | |
253 | +/* | |
254 | + * FPGA Manager to program the FPGA. This is the interface used by FPGA driver. | |
255 | + * Return 0 for sucess, non-zero for error. | |
256 | + */ | |
257 | +int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) | |
258 | +{ | |
259 | + unsigned long status; | |
260 | + | |
261 | + if ((uint32_t)rbf_data & 0x3) { | |
262 | + puts("FPGA: Unaligned data, realign to 32bit boundary.\n"); | |
263 | + return -EINVAL; | |
264 | + } | |
265 | + | |
266 | + /* Prior programming the FPGA, all bridges need to be shut off */ | |
267 | + | |
268 | + /* Disable all signals from hps peripheral controller to fpga */ | |
269 | + writel(0, &sysmgr_regs->fpgaintfgrp_module); | |
270 | + | |
271 | + /* Disable all signals from FPGA to HPS SDRAM */ | |
272 | +#define SDR_CTRLGRP_FPGAPORTRST_ADDRESS 0x5080 | |
273 | + writel(0, SOCFPGA_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS); | |
274 | + | |
275 | + /* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */ | |
276 | + socfpga_bridges_reset(1); | |
277 | + | |
278 | + /* Unmap the bridges from NIC-301 */ | |
279 | + writel(0x1, SOCFPGA_L3REGS_ADDRESS); | |
280 | + | |
281 | + /* Initialize the FPGA Manager */ | |
282 | + status = fpgamgr_program_init(); | |
283 | + if (status) | |
284 | + return status; | |
285 | + | |
286 | + /* Write the RBF data to FPGA Manager */ | |
287 | + fpgamgr_program_write(rbf_data, rbf_size); | |
288 | + | |
289 | + /* Ensure the FPGA entering config done */ | |
290 | + status = fpgamgr_program_poll_cd(); | |
291 | + if (status) | |
292 | + return status; | |
293 | + | |
294 | + /* Ensure the FPGA entering init phase */ | |
295 | + status = fpgamgr_program_poll_initphase(); | |
296 | + if (status) | |
297 | + return status; | |
298 | + | |
299 | + /* Ensure the FPGA entering user mode */ | |
300 | + return fpgamgr_program_poll_usermode(); | |
301 | +} |
include/altera.h
... | ... | @@ -40,6 +40,8 @@ |
40 | 40 | Altera_CYC2, |
41 | 41 | /* StratixII Family */ |
42 | 42 | Altera_StratixII, |
43 | + /* SoCFPGA Family */ | |
44 | + Altera_SoCFPGA, | |
43 | 45 | |
44 | 46 | /* Add new models here */ |
45 | 47 | |
... | ... | @@ -90,6 +92,10 @@ |
90 | 92 | Altera_abort_fn abort; |
91 | 93 | Altera_post_fn post; |
92 | 94 | } altera_board_specific_func; |
95 | + | |
96 | +#ifdef CONFIG_FPGA_SOCFPGA | |
97 | +int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size); | |
98 | +#endif | |
93 | 99 | |
94 | 100 | #endif /* _ALTERA_H_ */ |