]>
Commit | Line | Data |
---|---|---|
aea02abe SR |
1 | /* |
2 | * Copyright (C) 2016 Stefan Roese <sr@denx.de> | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <altera.h> | |
9 | #include <errno.h> | |
10 | #include <asm/gpio.h> | |
11 | #include <asm/io.h> | |
12 | #include <asm/arch/cpu.h> | |
13 | #include <asm/arch/soc.h> | |
14 | #include <asm/arch-mvebu/spi.h> | |
15 | #include "theadorable.h" | |
16 | ||
17 | /* | |
18 | * FPGA programming support | |
19 | */ | |
20 | static int fpga_pre_fn(int cookie) | |
21 | { | |
22 | int gpio_config = COOKIE2CONFIG(cookie); | |
23 | int gpio_done = COOKIE2DONE(cookie); | |
24 | int ret; | |
25 | ||
26 | debug("%s (%d): cookie=%08x gpio_config=%d gpio_done=%d\n", | |
27 | __func__, __LINE__, cookie, gpio_config, gpio_done); | |
28 | ||
29 | /* Configure config pin */ | |
30 | /* Set to output */ | |
31 | ret = gpio_request(gpio_config, "CONFIG"); | |
32 | if (ret < 0) | |
33 | return ret; | |
34 | gpio_direction_output(gpio_config, 1); | |
35 | ||
36 | /* Configure done pin */ | |
37 | /* Set to input */ | |
38 | ret = gpio_request(gpio_done, "DONE"); | |
39 | if (ret < 0) | |
40 | return ret; | |
41 | ||
42 | gpio_direction_input(gpio_done); | |
43 | ||
44 | return 0; | |
45 | } | |
46 | ||
47 | static int fpga_config_fn(int assert, int flush, int cookie) | |
48 | { | |
49 | int gpio_config = COOKIE2CONFIG(cookie); | |
50 | ||
51 | debug("%s (%d): cookie=%08x gpio_config=%d\n", | |
52 | __func__, __LINE__, cookie, gpio_config); | |
53 | ||
54 | if (assert) | |
55 | gpio_set_value(gpio_config, 1); | |
56 | else | |
57 | gpio_set_value(gpio_config, 0); | |
58 | ||
59 | return 0; | |
60 | } | |
61 | ||
62 | static int fpga_write_fn(const void *buf, size_t len, int flush, int cookie) | |
63 | { | |
64 | int spi_bus = COOKIE2SPI_BUS(cookie); | |
65 | int spi_dev = COOKIE2SPI_DEV(cookie); | |
66 | struct kwspi_registers *reg; | |
67 | u32 control_reg; | |
68 | u32 config_reg; | |
69 | void *dst; | |
70 | ||
71 | /* | |
72 | * Write data to FPGA attached to SPI bus via SPI direct write. | |
73 | * This results in the fastest and easiest way to program the | |
74 | * bitstream into the FPGA. | |
75 | */ | |
76 | debug("%s (%d): cookie=%08x spi_bus=%d spi_dev=%d\n", | |
77 | __func__, __LINE__, cookie, spi_bus, spi_dev); | |
78 | ||
79 | if (spi_bus == 0) { | |
80 | reg = (struct kwspi_registers *)MVEBU_REGISTER(0x10600); | |
81 | dst = (void *)SPI_BUS0_DEV1_BASE; | |
82 | } else { | |
83 | reg = (struct kwspi_registers *)MVEBU_REGISTER(0x10680); | |
84 | dst = (void *)SPI_BUS1_DEV2_BASE; | |
85 | } | |
86 | ||
87 | /* Configure SPI controller for direct access mode */ | |
88 | control_reg = readl(®->ctrl); | |
89 | config_reg = readl(®->cfg); | |
90 | writel(0x00000214, ®->cfg); /* 27MHz clock */ | |
91 | writel(0x00000000, ®->dw_cfg); /* don't de-asset CS */ | |
92 | writel(KWSPI_CSN_ACT, ®->ctrl); /* activate CS */ | |
93 | ||
94 | /* Copy data to the SPI direct mapped window */ | |
95 | memcpy(dst, buf, len); | |
96 | ||
97 | /* Restore original register values */ | |
98 | writel(control_reg, ®->ctrl); | |
99 | writel(config_reg, ®->cfg); | |
100 | ||
101 | return 0; | |
102 | } | |
103 | ||
104 | /* Returns the state of CONF_DONE Pin */ | |
105 | static int fpga_done_fn(int cookie) | |
106 | { | |
107 | int gpio_done = COOKIE2DONE(cookie); | |
108 | unsigned long ts; | |
109 | ||
110 | debug("%s (%d): cookie=%08x gpio_done=%d\n", | |
111 | __func__, __LINE__, cookie, gpio_done); | |
112 | ||
113 | ts = get_timer(0); | |
114 | do { | |
115 | if (gpio_get_value(gpio_done)) | |
116 | return 0; | |
117 | } while (get_timer(ts) < 1000); | |
118 | ||
119 | /* timeout so return error */ | |
120 | return -ENODEV; | |
121 | } | |
122 | ||
123 | static altera_board_specific_func stratixv_fns = { | |
124 | .pre = fpga_pre_fn, | |
125 | .config = fpga_config_fn, | |
126 | .write = fpga_write_fn, | |
127 | .done = fpga_done_fn, | |
128 | }; | |
129 | ||
130 | static Altera_desc altera_fpga[] = { | |
131 | { | |
132 | /* Family */ | |
133 | Altera_StratixV, | |
134 | /* Interface type */ | |
135 | passive_serial, | |
136 | /* No limitation as additional data will be ignored */ | |
137 | -1, | |
138 | /* Device function table */ | |
139 | (void *)&stratixv_fns, | |
140 | /* Base interface address specified in driver */ | |
141 | NULL, | |
142 | /* Cookie implementation */ | |
143 | /* | |
144 | * In this 32bit word the following information is coded: | |
145 | * Bit 31 ... Bit 0 | |
146 | * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin | |
147 | */ | |
148 | FPGA_COOKIE(0, 1, 26, 7) | |
149 | }, | |
150 | { | |
151 | /* Family */ | |
152 | Altera_StratixV, | |
153 | /* Interface type */ | |
154 | passive_serial, | |
155 | /* No limitation as additional data will be ignored */ | |
156 | -1, | |
157 | /* Device function table */ | |
158 | (void *)&stratixv_fns, | |
159 | /* Base interface address specified in driver */ | |
160 | NULL, | |
161 | /* Cookie implementation */ | |
162 | /* | |
163 | * In this 32bit word the following information is coded: | |
164 | * Bit 31 ... Bit 0 | |
165 | * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin | |
166 | */ | |
167 | FPGA_COOKIE(1, 2, 29, 9) | |
168 | }, | |
169 | }; | |
170 | ||
171 | /* Add device descriptor to FPGA device table */ | |
172 | void board_fpga_add(void) | |
173 | { | |
174 | int i; | |
175 | ||
176 | fpga_init(); | |
177 | for (i = 0; i < ARRAY_SIZE(altera_fpga); i++) | |
178 | fpga_add(fpga_altera, &altera_fpga[i]); | |
179 | } |