diff options
author | Stefan Roese <sr@denx.de> | 2012-12-07 03:06:59 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-01-17 13:25:03 -0500 |
commit | 781551df57c792aee291cd80a6aca24cd56cdd71 (patch) | |
tree | 0d50fddf9e87033b260a9aeec19f98d87798a9e0 /drivers/misc/lattice-ecp3-config.c | |
parent | 93ce83b6e0ffe8d48dae46bc0983dd3f01ec7e32 (diff) |
misc: Add Lattice ECP3 FPGA configuration via SPI
This patch adds support for bitstream configuration (programming /
loading) of the Lattice ECP3 FPGA's via the SPI bus.
Here an example on my custom MPC5200 based board:
$ echo 1 > /sys/class/firmware/spi0.0/loading
$ cat fpga_a4m2k.bit > /sys/class/firmware/spi0.0/data
$ echo 0 > /sys/class/firmware/spi0.0/loading
leads to these messages:
lattice-ecp3 spi0.0: FPGA Lattice ECP3-35 detected
lattice-ecp3 spi0.0: Configuring the FPGA...
lattice-ecp3 spi0.0: FPGA succesfully configured!
Signed-off-by: Stefan Roese <sr@denx.de>
Acked-by: Ming Lei <ming.lei@canonical.com>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/lattice-ecp3-config.c')
-rw-r--r-- | drivers/misc/lattice-ecp3-config.c | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c new file mode 100644 index 000000000000..ff3106ce8237 --- /dev/null +++ b/drivers/misc/lattice-ecp3-config.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Stefan Roese <sr@denx.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/device.h> | ||
11 | #include <linux/firmware.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/spi/spi.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/delay.h> | ||
19 | |||
20 | #define FIRMWARE_NAME "lattice-ecp3.bit" | ||
21 | |||
22 | /* | ||
23 | * The JTAG ID's of the supported FPGA's. The ID is 32bit wide | ||
24 | * reversed as noted in the manual. | ||
25 | */ | ||
26 | #define ID_ECP3_17 0xc2088080 | ||
27 | #define ID_ECP3_35 0xc2048080 | ||
28 | |||
29 | /* FPGA commands */ | ||
30 | #define FPGA_CMD_READ_ID 0x07 /* plus 24 bits */ | ||
31 | #define FPGA_CMD_READ_STATUS 0x09 /* plus 24 bits */ | ||
32 | #define FPGA_CMD_CLEAR 0x70 | ||
33 | #define FPGA_CMD_REFRESH 0x71 | ||
34 | #define FPGA_CMD_WRITE_EN 0x4a /* plus 2 bits */ | ||
35 | #define FPGA_CMD_WRITE_DIS 0x4f /* plus 8 bits */ | ||
36 | #define FPGA_CMD_WRITE_INC 0x41 /* plus 0 bits */ | ||
37 | |||
38 | /* | ||
39 | * The status register is 32bit revered, DONE is bit 17 from the TN1222.pdf | ||
40 | * (LatticeECP3 Slave SPI Port User's Guide) | ||
41 | */ | ||
42 | #define FPGA_STATUS_DONE 0x00004000 | ||
43 | #define FPGA_STATUS_CLEARED 0x00010000 | ||
44 | |||
45 | #define FPGA_CLEAR_TIMEOUT 5000 /* max. 5000ms for FPGA clear */ | ||
46 | #define FPGA_CLEAR_MSLEEP 10 | ||
47 | #define FPGA_CLEAR_LOOP_COUNT (FPGA_CLEAR_TIMEOUT / FPGA_CLEAR_MSLEEP) | ||
48 | |||
49 | struct fpga_data { | ||
50 | struct completion fw_loaded; | ||
51 | }; | ||
52 | |||
53 | struct ecp3_dev { | ||
54 | u32 jedec_id; | ||
55 | char *name; | ||
56 | }; | ||
57 | |||
58 | static const struct ecp3_dev ecp3_dev[] = { | ||
59 | { | ||
60 | .jedec_id = ID_ECP3_17, | ||
61 | .name = "Lattice ECP3-17", | ||
62 | }, | ||
63 | { | ||
64 | .jedec_id = ID_ECP3_35, | ||
65 | .name = "Lattice ECP3-35", | ||
66 | }, | ||
67 | }; | ||
68 | |||
69 | static void firmware_load(const struct firmware *fw, void *context) | ||
70 | { | ||
71 | struct spi_device *spi = (struct spi_device *)context; | ||
72 | struct fpga_data *data = dev_get_drvdata(&spi->dev); | ||
73 | u8 *buffer; | ||
74 | int ret; | ||
75 | u8 txbuf[8]; | ||
76 | u8 rxbuf[8]; | ||
77 | int rx_len = 8; | ||
78 | int i; | ||
79 | u32 jedec_id; | ||
80 | u32 status; | ||
81 | |||
82 | if (fw->size == 0) { | ||
83 | dev_err(&spi->dev, "Error: Firmware size is 0!\n"); | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | /* Fill dummy data (24 stuffing bits for commands) */ | ||
88 | txbuf[1] = 0x00; | ||
89 | txbuf[2] = 0x00; | ||
90 | txbuf[3] = 0x00; | ||
91 | |||
92 | /* Trying to speak with the FPGA via SPI... */ | ||
93 | txbuf[0] = FPGA_CMD_READ_ID; | ||
94 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); | ||
95 | dev_dbg(&spi->dev, "FPGA JTAG ID=%08x\n", *(u32 *)&rxbuf[4]); | ||
96 | jedec_id = *(u32 *)&rxbuf[4]; | ||
97 | |||
98 | for (i = 0; i < ARRAY_SIZE(ecp3_dev); i++) { | ||
99 | if (jedec_id == ecp3_dev[i].jedec_id) | ||
100 | break; | ||
101 | } | ||
102 | if (i == ARRAY_SIZE(ecp3_dev)) { | ||
103 | dev_err(&spi->dev, | ||
104 | "Error: No supported FPGA detected (JEDEC_ID=%08x)!\n", | ||
105 | jedec_id); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | dev_info(&spi->dev, "FPGA %s detected\n", ecp3_dev[i].name); | ||
110 | |||
111 | txbuf[0] = FPGA_CMD_READ_STATUS; | ||
112 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); | ||
113 | dev_dbg(&spi->dev, "FPGA Status=%08x\n", *(u32 *)&rxbuf[4]); | ||
114 | |||
115 | buffer = kzalloc(fw->size + 8, GFP_KERNEL); | ||
116 | if (!buffer) { | ||
117 | dev_err(&spi->dev, "Error: Can't allocate memory!\n"); | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Insert WRITE_INC command into stream (one SPI frame) | ||
123 | */ | ||
124 | buffer[0] = FPGA_CMD_WRITE_INC; | ||
125 | buffer[1] = 0xff; | ||
126 | buffer[2] = 0xff; | ||
127 | buffer[3] = 0xff; | ||
128 | memcpy(buffer + 4, fw->data, fw->size); | ||
129 | |||
130 | txbuf[0] = FPGA_CMD_REFRESH; | ||
131 | ret = spi_write(spi, txbuf, 4); | ||
132 | |||
133 | txbuf[0] = FPGA_CMD_WRITE_EN; | ||
134 | ret = spi_write(spi, txbuf, 4); | ||
135 | |||
136 | txbuf[0] = FPGA_CMD_CLEAR; | ||
137 | ret = spi_write(spi, txbuf, 4); | ||
138 | |||
139 | /* | ||
140 | * Wait for FPGA memory to become cleared | ||
141 | */ | ||
142 | for (i = 0; i < FPGA_CLEAR_LOOP_COUNT; i++) { | ||
143 | txbuf[0] = FPGA_CMD_READ_STATUS; | ||
144 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); | ||
145 | status = *(u32 *)&rxbuf[4]; | ||
146 | if (status == FPGA_STATUS_CLEARED) | ||
147 | break; | ||
148 | |||
149 | msleep(FPGA_CLEAR_MSLEEP); | ||
150 | } | ||
151 | |||
152 | if (i == FPGA_CLEAR_LOOP_COUNT) { | ||
153 | dev_err(&spi->dev, | ||
154 | "Error: Timeout waiting for FPGA to clear (status=%08x)!\n", | ||
155 | status); | ||
156 | kfree(buffer); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | dev_info(&spi->dev, "Configuring the FPGA...\n"); | ||
161 | ret = spi_write(spi, buffer, fw->size + 8); | ||
162 | |||
163 | txbuf[0] = FPGA_CMD_WRITE_DIS; | ||
164 | ret = spi_write(spi, txbuf, 4); | ||
165 | |||
166 | txbuf[0] = FPGA_CMD_READ_STATUS; | ||
167 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); | ||
168 | dev_dbg(&spi->dev, "FPGA Status=%08x\n", *(u32 *)&rxbuf[4]); | ||
169 | status = *(u32 *)&rxbuf[4]; | ||
170 | |||
171 | /* Check result */ | ||
172 | if (status & FPGA_STATUS_DONE) | ||
173 | dev_info(&spi->dev, "FPGA succesfully configured!\n"); | ||
174 | else | ||
175 | dev_info(&spi->dev, "FPGA not configured (DONE not set)\n"); | ||
176 | |||
177 | /* | ||
178 | * Don't forget to release the firmware again | ||
179 | */ | ||
180 | release_firmware(fw); | ||
181 | |||
182 | kfree(buffer); | ||
183 | |||
184 | complete(&data->fw_loaded); | ||
185 | } | ||
186 | |||
187 | static int __devinit lattice_ecp3_probe(struct spi_device *spi) | ||
188 | { | ||
189 | struct fpga_data *data; | ||
190 | int err; | ||
191 | |||
192 | data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL); | ||
193 | if (!data) { | ||
194 | dev_err(&spi->dev, "Memory allocation for fpga_data failed\n"); | ||
195 | return -ENOMEM; | ||
196 | } | ||
197 | spi_set_drvdata(spi, data); | ||
198 | |||
199 | init_completion(&data->fw_loaded); | ||
200 | err = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | ||
201 | FIRMWARE_NAME, &spi->dev, | ||
202 | GFP_KERNEL, spi, firmware_load); | ||
203 | if (err) { | ||
204 | dev_err(&spi->dev, "Firmware loading failed with %d!\n", err); | ||
205 | return err; | ||
206 | } | ||
207 | |||
208 | dev_info(&spi->dev, "FPGA bitstream configuration driver registered\n"); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int __devexit lattice_ecp3_remove(struct spi_device *spi) | ||
214 | { | ||
215 | struct fpga_data *data = spi_get_drvdata(spi); | ||
216 | |||
217 | wait_for_completion(&data->fw_loaded); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static const struct spi_device_id lattice_ecp3_id[] __devinitdata = { | ||
223 | { "ecp3-17", 0 }, | ||
224 | { "ecp3-35", 0 }, | ||
225 | { } | ||
226 | }; | ||
227 | MODULE_DEVICE_TABLE(spi, lattice_ecp3_id); | ||
228 | |||
229 | static struct spi_driver lattice_ecp3_driver = { | ||
230 | .driver = { | ||
231 | .name = "lattice-ecp3", | ||
232 | .owner = THIS_MODULE, | ||
233 | }, | ||
234 | .probe = lattice_ecp3_probe, | ||
235 | .remove = __devexit_p(lattice_ecp3_remove), | ||
236 | .id_table = lattice_ecp3_id, | ||
237 | }; | ||
238 | |||
239 | module_spi_driver(lattice_ecp3_driver); | ||
240 | |||
241 | MODULE_AUTHOR("Stefan Roese <sr@denx.de>"); | ||
242 | MODULE_DESCRIPTION("Lattice ECP3 FPGA configuration via SPI"); | ||
243 | MODULE_LICENSE("GPL"); | ||