]>
Commit | Line | Data |
---|---|---|
b5e7f1bc | 1 | /* |
2 | * (C) Copyright 2002-2013 | |
3 | * Eric Jarrige <eric.jarrige@armadeus.org> | |
4 | * | |
5 | * based on the files by | |
6 | * Rich Ireland, Enterasys Networks, rireland@enterasys.com | |
7 | * and | |
8 | * Keith Outwater, keith_outwater@mvis.com | |
9 | * | |
10 | * SPDX-License-Identifier: GPL-2.0+ | |
11 | */ | |
12 | #include <common.h> | |
13 | ||
14 | #include <asm/arch/imx-regs.h> | |
15 | #include <asm/gpio.h> | |
16 | #include <asm/io.h> | |
17 | #include <command.h> | |
18 | #include <config.h> | |
19 | #include "fpga.h" | |
20 | #include <spartan3.h> | |
21 | #include "apf27.h" | |
22 | ||
23 | /* | |
24 | * Note that these are pointers to code that is in Flash. They will be | |
25 | * relocated at runtime. | |
26 | * Spartan2 code is used to download our Spartan 3 :) code is compatible. | |
27 | * Just take care about the file size | |
28 | */ | |
2a6e3869 | 29 | xilinx_spartan3_slave_parallel_fns fpga_fns = { |
b5e7f1bc | 30 | fpga_pre_fn, |
31 | fpga_pgm_fn, | |
32 | fpga_init_fn, | |
33 | NULL, | |
34 | fpga_done_fn, | |
35 | fpga_clk_fn, | |
36 | fpga_cs_fn, | |
37 | fpga_wr_fn, | |
38 | fpga_rdata_fn, | |
39 | fpga_wdata_fn, | |
40 | fpga_busy_fn, | |
41 | fpga_abort_fn, | |
42 | fpga_post_fn, | |
43 | }; | |
44 | ||
f8c1be98 | 45 | xilinx_desc fpga[CONFIG_FPGA_COUNT] = { |
2a6e3869 | 46 | {xilinx_spartan3, |
b5e7f1bc | 47 | slave_parallel, |
48 | 1196128l/8, | |
49 | (void *)&fpga_fns, | |
50 | 0, | |
14cfc4f3 | 51 | &spartan3_op, |
b5e7f1bc | 52 | "3s200aft256"} |
53 | }; | |
54 | ||
55 | /* | |
56 | * Initialize GPIO port B before download | |
57 | */ | |
58 | int fpga_pre_fn(int cookie) | |
59 | { | |
60 | /* Initialize GPIO pins */ | |
61 | gpio_set_value(ACFG_FPGA_PWR, 1); | |
62 | imx_gpio_mode(ACFG_FPGA_INIT | GPIO_IN | GPIO_PUEN | GPIO_GPIO); | |
63 | imx_gpio_mode(ACFG_FPGA_DONE | GPIO_IN | GPIO_PUEN | GPIO_GPIO); | |
64 | imx_gpio_mode(ACFG_FPGA_PRG | GPIO_OUT | GPIO_PUEN | GPIO_GPIO); | |
65 | imx_gpio_mode(ACFG_FPGA_CLK | GPIO_OUT | GPIO_PUEN | GPIO_GPIO); | |
66 | imx_gpio_mode(ACFG_FPGA_RW | GPIO_OUT | GPIO_PUEN | GPIO_GPIO); | |
67 | imx_gpio_mode(ACFG_FPGA_CS | GPIO_OUT | GPIO_PUEN | GPIO_GPIO); | |
68 | imx_gpio_mode(ACFG_FPGA_SUSPEND|GPIO_OUT|GPIO_PUEN|GPIO_GPIO); | |
69 | gpio_set_value(ACFG_FPGA_RESET, 1); | |
70 | imx_gpio_mode(ACFG_FPGA_RESET | GPIO_OUT | GPIO_PUEN | GPIO_GPIO); | |
71 | imx_gpio_mode(ACFG_FPGA_PWR | GPIO_OUT | GPIO_PUEN | GPIO_GPIO); | |
72 | gpio_set_value(ACFG_FPGA_PRG, 1); | |
73 | gpio_set_value(ACFG_FPGA_CLK, 1); | |
74 | gpio_set_value(ACFG_FPGA_RW, 1); | |
75 | gpio_set_value(ACFG_FPGA_CS, 1); | |
76 | gpio_set_value(ACFG_FPGA_SUSPEND, 0); | |
77 | gpio_set_value(ACFG_FPGA_PWR, 0); | |
78 | udelay(30000); /*wait until supply started*/ | |
79 | ||
80 | return cookie; | |
81 | } | |
82 | ||
83 | /* | |
84 | * Set the FPGA's active-low program line to the specified level | |
85 | */ | |
86 | int fpga_pgm_fn(int assert, int flush, int cookie) | |
87 | { | |
88 | debug("%s:%d: FPGA PROGRAM %s", __func__, __LINE__, | |
89 | assert ? "high" : "low"); | |
90 | gpio_set_value(ACFG_FPGA_PRG, !assert); | |
91 | return assert; | |
92 | } | |
93 | ||
94 | /* | |
95 | * Set the FPGA's active-high clock line to the specified level | |
96 | */ | |
97 | int fpga_clk_fn(int assert_clk, int flush, int cookie) | |
98 | { | |
99 | debug("%s:%d: FPGA CLOCK %s", __func__, __LINE__, | |
100 | assert_clk ? "high" : "low"); | |
101 | gpio_set_value(ACFG_FPGA_CLK, !assert_clk); | |
102 | return assert_clk; | |
103 | } | |
104 | ||
105 | /* | |
106 | * Test the state of the active-low FPGA INIT line. Return 1 on INIT | |
107 | * asserted (low). | |
108 | */ | |
109 | int fpga_init_fn(int cookie) | |
110 | { | |
111 | int value; | |
112 | debug("%s:%d: INIT check... ", __func__, __LINE__); | |
113 | value = gpio_get_value(ACFG_FPGA_INIT); | |
114 | /* printf("init value read %x",value); */ | |
115 | #ifdef CONFIG_SYS_FPGA_IS_PROTO | |
116 | return value; | |
117 | #else | |
118 | return !value; | |
119 | #endif | |
120 | } | |
121 | ||
122 | /* | |
123 | * Test the state of the active-high FPGA DONE pin | |
124 | */ | |
125 | int fpga_done_fn(int cookie) | |
126 | { | |
127 | debug("%s:%d: DONE check... %s", __func__, __LINE__, | |
128 | gpio_get_value(ACFG_FPGA_DONE) ? "high" : "low"); | |
129 | return gpio_get_value(ACFG_FPGA_DONE) ? FPGA_SUCCESS : FPGA_FAIL; | |
130 | } | |
131 | ||
132 | /* | |
133 | * Set the FPGA's wr line to the specified level | |
134 | */ | |
135 | int fpga_wr_fn(int assert_write, int flush, int cookie) | |
136 | { | |
137 | debug("%s:%d: FPGA RW... %s ", __func__, __LINE__, | |
138 | assert_write ? "high" : "low"); | |
139 | gpio_set_value(ACFG_FPGA_RW, !assert_write); | |
140 | return assert_write; | |
141 | } | |
142 | ||
143 | int fpga_cs_fn(int assert_cs, int flush, int cookie) | |
144 | { | |
145 | debug("%s:%d: FPGA CS %s ", __func__, __LINE__, | |
146 | assert_cs ? "high" : "low"); | |
147 | gpio_set_value(ACFG_FPGA_CS, !assert_cs); | |
148 | return assert_cs; | |
149 | } | |
150 | ||
151 | int fpga_rdata_fn(unsigned char *data, int cookie) | |
152 | { | |
153 | debug("%s:%d: FPGA READ DATA %02X ", __func__, __LINE__, | |
154 | *((char *)ACFG_FPGA_RDATA)); | |
155 | *data = (unsigned char) | |
156 | ((*((unsigned short *)ACFG_FPGA_RDATA))&0x00FF); | |
157 | return *data; | |
158 | } | |
159 | ||
160 | int fpga_wdata_fn(unsigned char data, int flush, int cookie) | |
161 | { | |
162 | debug("%s:%d: FPGA WRITE DATA %02X ", __func__, __LINE__, | |
163 | data); | |
164 | *((unsigned short *)ACFG_FPGA_WDATA) = data; | |
165 | return data; | |
166 | } | |
167 | ||
168 | int fpga_abort_fn(int cookie) | |
169 | { | |
170 | return fpga_post_fn(cookie); | |
171 | } | |
172 | ||
173 | ||
174 | int fpga_busy_fn(int cookie) | |
175 | { | |
176 | return 1; | |
177 | } | |
178 | ||
179 | int fpga_post_fn(int cookie) | |
180 | { | |
181 | debug("%s:%d: FPGA POST ", __func__, __LINE__); | |
182 | ||
183 | imx_gpio_mode(ACFG_FPGA_RW | GPIO_PF | GPIO_PUEN); | |
184 | imx_gpio_mode(ACFG_FPGA_CS | GPIO_PF | GPIO_PUEN); | |
185 | imx_gpio_mode(ACFG_FPGA_CLK | GPIO_PF | GPIO_PUEN); | |
186 | gpio_set_value(ACFG_FPGA_PRG, 1); | |
187 | gpio_set_value(ACFG_FPGA_RESET, 0); | |
188 | imx_gpio_mode(ACFG_FPGA_RESET | GPIO_OUT | GPIO_PUEN | GPIO_GPIO); | |
189 | return cookie; | |
190 | } | |
191 | ||
192 | void apf27_fpga_setup(void) | |
193 | { | |
194 | struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; | |
195 | struct system_control_regs *system = | |
196 | (struct system_control_regs *)IMX_SYSTEM_CTL_BASE; | |
197 | ||
198 | /* Configure FPGA CLKO */ | |
199 | writel(ACFG_CCSR_VAL, &pll->ccsr); | |
200 | ||
201 | /* Configure strentgh for FPGA */ | |
202 | writel(ACFG_DSCR10_VAL, &system->dscr10); | |
203 | writel(ACFG_DSCR3_VAL, &system->dscr3); | |
204 | writel(ACFG_DSCR7_VAL, &system->dscr7); | |
205 | writel(ACFG_DSCR2_VAL, &system->dscr2); | |
206 | } | |
207 | ||
208 | /* | |
209 | * Initialize the fpga. Return 1 on success, 0 on failure. | |
210 | */ | |
211 | void APF27_init_fpga(void) | |
212 | { | |
213 | int i; | |
214 | ||
215 | apf27_fpga_setup(); | |
216 | ||
217 | fpga_init(); | |
218 | ||
219 | for (i = 0; i < CONFIG_FPGA_COUNT; i++) { | |
220 | debug("%s:%d: Adding fpga %d\n", __func__, __LINE__, i); | |
221 | fpga_add(fpga_xilinx, &fpga[i]); | |
222 | } | |
223 | ||
224 | return; | |
225 | } |