]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/spear/x600/fpga.c
Merge branch 'u-boot-samsung/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / board / spear / x600 / fpga.c
1 /*
2  * Copyright (C) 2012 Stefan Roese <sr@denx.de>
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <spartan3.h>
9 #include <command.h>
10 #include <asm/gpio.h>
11 #include <asm/io.h>
12 #include <asm/arch/hardware.h>
13 #include <asm/arch/spr_misc.h>
14 #include <asm/arch/spr_ssp.h>
15
16 /*
17  * FPGA program pin configuration on X600:
18  *
19  * Only PROG and DONE are connected to GPIOs. INIT is not connected to the
20  * SoC at all. And CLOCK and DATA are connected to the SSP2 port. We use
21  * 16bit serial writes via this SSP port to write the data bits into the
22  * FPGA.
23  */
24 #define CONFIG_SYS_FPGA_PROG            2
25 #define CONFIG_SYS_FPGA_DONE            3
26
27 /*
28  * Set the active-low FPGA reset signal.
29  */
30 static void fpga_reset(int assert)
31 {
32         /*
33          * On x600 we have no means to toggle the FPGA reset signal
34          */
35         debug("%s:%d: RESET (%d)\n", __func__, __LINE__, assert);
36 }
37
38 /*
39  * Set the FPGA's active-low SelectMap program line to the specified level
40  */
41 static int fpga_pgm_fn(int assert, int flush, int cookie)
42 {
43         debug("%s:%d: FPGA PROG (%d)\n", __func__, __LINE__, assert);
44
45         gpio_set_value(CONFIG_SYS_FPGA_PROG, assert);
46
47         return assert;
48 }
49
50 /*
51  * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
52  * asserted (low).
53  */
54 static int fpga_init_fn(int cookie)
55 {
56         static int state;
57
58         debug("%s:%d: init (state=%d)\n", __func__, __LINE__, state);
59
60         /*
61          * On x600, the FPGA INIT signal is not connected to the SoC.
62          * We can't read the INIT status. Let's return the "correct"
63          * INIT signal state generated via a local state-machine.
64          */
65         if (++state == 1) {
66                 return 1;
67         } else {
68                 state = 0;
69                 return 0;
70         }
71 }
72
73 /*
74  * Test the state of the active-high FPGA DONE pin
75  */
76 static int fpga_done_fn(int cookie)
77 {
78         struct ssp_regs *ssp = (struct ssp_regs *)CONFIG_SSP2_BASE;
79
80         /*
81          * Wait for Tx-FIFO to become empty before looking for DONE
82          */
83         while (!(readl(&ssp->sspsr) & SSPSR_TFE))
84                 ;
85
86         if (gpio_get_value(CONFIG_SYS_FPGA_DONE))
87                 return 1;
88         else
89                 return 0;
90 }
91
92 /*
93  * FPGA pre-configuration function. Just make sure that
94  * FPGA reset is asserted to keep the FPGA from starting up after
95  * configuration.
96  */
97 static int fpga_pre_config_fn(int cookie)
98 {
99         debug("%s:%d: FPGA pre-configuration\n", __func__, __LINE__);
100         fpga_reset(true);
101
102         return 0;
103 }
104
105 /*
106  * FPGA post configuration function. Blip the FPGA reset line and then see if
107  * the FPGA appears to be running.
108  */
109 static int fpga_post_config_fn(int cookie)
110 {
111         int rc = 0;
112
113         debug("%s:%d: FPGA post configuration\n", __func__, __LINE__);
114
115         fpga_reset(true);
116         udelay(100);
117         fpga_reset(false);
118         udelay(100);
119
120         return rc;
121 }
122
123 static int fpga_clk_fn(int assert_clk, int flush, int cookie)
124 {
125         /*
126          * No dedicated clock signal on x600 (data & clock generated)
127          * in SSP interface. So we don't have to do anything here.
128          */
129         return assert_clk;
130 }
131
132 static int fpga_wr_fn(int assert_write, int flush, int cookie)
133 {
134         struct ssp_regs *ssp = (struct ssp_regs *)CONFIG_SSP2_BASE;
135         static int count;
136         static u16 data;
137
138         /*
139          * First collect 16 bits of data
140          */
141         data = data << 1;
142         if (assert_write)
143                 data |= 1;
144
145         /*
146          * If 16 bits are not available, return for more bits
147          */
148         count++;
149         if (count != 16)
150                 return assert_write;
151
152         count = 0;
153
154         /*
155          * Wait for Tx-FIFO to become ready
156          */
157         while (!(readl(&ssp->sspsr) & SSPSR_TNF))
158                 ;
159
160         /* Send 16 bits to FPGA via SSP bus */
161         writel(data, &ssp->sspdr);
162
163         return assert_write;
164 }
165
166 static xilinx_spartan3_slave_serial_fns x600_fpga_fns = {
167         fpga_pre_config_fn,
168         fpga_pgm_fn,
169         fpga_clk_fn,
170         fpga_init_fn,
171         fpga_done_fn,
172         fpga_wr_fn,
173         fpga_post_config_fn,
174 };
175
176 static xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
177         XILINX_XC3S1200E_DESC(slave_serial, &x600_fpga_fns, 0)
178 };
179
180 /*
181  * Initialize the SelectMap interface.  We assume that the mode and the
182  * initial state of all of the port pins have already been set!
183  */
184 static void fpga_serialslave_init(void)
185 {
186         debug("%s:%d: Initialize serial slave interface\n", __func__, __LINE__);
187         fpga_pgm_fn(false, false, 0);   /* make sure program pin is inactive */
188 }
189
190 static int expi_setup(int freq)
191 {
192         struct misc_regs *misc = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
193         int pll2_m, pll2_n, pll2_p, expi_x, expi_y;
194
195         pll2_m = (freq * 2) / 1000;
196         pll2_n = 15;
197         pll2_p = 1;
198         expi_x = 1;
199         expi_y = 2;
200
201         /*
202          * Disable reset, Low compression, Disable retiming, Enable Expi,
203          * Enable soft reset, DMA, PLL2, Internal
204          */
205         writel(EXPI_CLK_CFG_LOW_COMPR | EXPI_CLK_CFG_CLK_EN | EXPI_CLK_CFG_RST |
206                EXPI_CLK_SYNT_EN | EXPI_CLK_CFG_SEL_PLL2 |
207                EXPI_CLK_CFG_INT_CLK_EN | (expi_y << 16) | (expi_x << 24),
208                &misc->expi_clk_cfg);
209
210         /*
211          * 6 uA, Internal feedback, 1st order, Non-dithered, Sample Parameters,
212          * Enable PLL2, Disable reset
213          */
214         writel((pll2_m << 24) | (pll2_p << 8) | (pll2_n), &misc->pll2_frq);
215         writel(PLL2_CNTL_6UA | PLL2_CNTL_SAMPLE | PLL2_CNTL_ENABLE |
216                PLL2_CNTL_RESETN | PLL2_CNTL_LOCK, &misc->pll2_cntl);
217
218         /*
219          * Disable soft reset
220          */
221         clrbits_le32(&misc->expi_clk_cfg, EXPI_CLK_CFG_RST);
222
223         return 0;
224 }
225
226 /*
227  * Initialize the fpga
228  */
229 int x600_init_fpga(void)
230 {
231         struct ssp_regs *ssp = (struct ssp_regs *)CONFIG_SSP2_BASE;
232         struct misc_regs *misc = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
233
234         /* Enable SSP2 clock */
235         writel(readl(&misc->periph1_clken) | MISC_SSP2ENB | MISC_GPIO4ENB,
236                &misc->periph1_clken);
237
238         /* Set EXPI clock to 45 MHz */
239         expi_setup(45000);
240
241         /* Configure GPIO directions */
242         gpio_direction_output(CONFIG_SYS_FPGA_PROG, 0);
243         gpio_direction_input(CONFIG_SYS_FPGA_DONE);
244
245         writel(SSPCR0_DSS_16BITS, &ssp->sspcr0);
246         writel(SSPCR1_SSE, &ssp->sspcr1);
247
248         /*
249          * Set lowest prescale divisor value (CPSDVSR) of 2 for max download
250          * speed.
251          *
252          * Actual data clock rate is: 80MHz / (CPSDVSR * (SCR + 1))
253          * With CPSDVSR at 2 and SCR at 0, the maximume clock rate is 40MHz.
254          */
255         writel(2, &ssp->sspcpsr);
256
257         fpga_init();
258         fpga_serialslave_init();
259
260         debug("%s:%d: Adding fpga 0\n", __func__, __LINE__);
261         fpga_add(fpga_xilinx, &fpga[0]);
262
263         return 0;
264 }