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 | |
| 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>
| -rw-r--r-- | drivers/misc/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/misc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/misc/lattice-ecp3-config.c | 243 |
3 files changed, 255 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 264e647413b5..3ec3f9ece9d9 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -499,6 +499,17 @@ config USB_SWITCH_FSA9480 | |||
| 499 | stereo and mono audio, video, microphone and UART data to use | 499 | stereo and mono audio, video, microphone and UART data to use |
| 500 | a common connector port. | 500 | a common connector port. |
| 501 | 501 | ||
| 502 | config LATTICE_ECP3_CONFIG | ||
| 503 | tristate "Lattice ECP3 FPGA bitstream configuration via SPI" | ||
| 504 | depends on SPI && SYSFS | ||
| 505 | select FW_LOADER | ||
| 506 | default n | ||
| 507 | help | ||
| 508 | This option enables support for bitstream configuration (programming | ||
| 509 | or loading) of the Lattice ECP3 FPGA family via SPI. | ||
| 510 | |||
| 511 | If unsure, say N. | ||
| 512 | |||
| 502 | source "drivers/misc/c2port/Kconfig" | 513 | source "drivers/misc/c2port/Kconfig" |
| 503 | source "drivers/misc/eeprom/Kconfig" | 514 | source "drivers/misc/eeprom/Kconfig" |
| 504 | source "drivers/misc/cb710/Kconfig" | 515 | source "drivers/misc/cb710/Kconfig" |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5c99726dd617..35a1463c72d9 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -51,3 +51,4 @@ obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ | |||
| 51 | obj-$(CONFIG_INTEL_MEI) += mei/ | 51 | obj-$(CONFIG_INTEL_MEI) += mei/ |
| 52 | obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o | 52 | obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o |
| 53 | obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ | 53 | obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ |
| 54 | obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o | ||
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"); | ||
