brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 93949df Raw
243 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2012 Stefan Roese <sr@denx.de>4 */5 6#include <linux/device.h>7#include <linux/firmware.h>8#include <linux/module.h>9#include <linux/errno.h>10#include <linux/kernel.h>11#include <linux/spi/spi.h>12#include <linux/platform_device.h>13#include <linux/delay.h>14#include <linux/unaligned.h>15 16#define FIRMWARE_NAME	"lattice-ecp3.bit"17 18/*19 * The JTAG ID's of the supported FPGA's. The ID is 32bit wide20 * reversed as noted in the manual.21 */22#define ID_ECP3_17	0xc208808023#define ID_ECP3_35	0xc204808024 25/* FPGA commands */26#define FPGA_CMD_READ_ID	0x07	/* plus 24 bits */27#define FPGA_CMD_READ_STATUS	0x09	/* plus 24 bits */28#define FPGA_CMD_CLEAR		0x7029#define FPGA_CMD_REFRESH	0x7130#define FPGA_CMD_WRITE_EN	0x4a	/* plus 2 bits */31#define FPGA_CMD_WRITE_DIS	0x4f	/* plus 8 bits */32#define FPGA_CMD_WRITE_INC	0x41	/* plus 0 bits */33 34/*35 * The status register is 32bit revered, DONE is bit 17 from the TN1222.pdf36 * (LatticeECP3 Slave SPI Port User's Guide)37 */38#define FPGA_STATUS_DONE	0x0000400039#define FPGA_STATUS_CLEARED	0x0001000040 41#define FPGA_CLEAR_TIMEOUT	5000	/* max. 5000ms for FPGA clear */42#define FPGA_CLEAR_MSLEEP	1043#define FPGA_CLEAR_LOOP_COUNT	(FPGA_CLEAR_TIMEOUT / FPGA_CLEAR_MSLEEP)44 45struct fpga_data {46	struct completion fw_loaded;47};48 49struct ecp3_dev {50	u32 jedec_id;51	char *name;52};53 54static const struct ecp3_dev ecp3_dev[] = {55	{56		.jedec_id = ID_ECP3_17,57		.name = "Lattice ECP3-17",58	},59	{60		.jedec_id = ID_ECP3_35,61		.name = "Lattice ECP3-35",62	},63};64 65static void firmware_load(const struct firmware *fw, void *context)66{67	struct spi_device *spi = (struct spi_device *)context;68	struct fpga_data *data = spi_get_drvdata(spi);69	u8 *buffer;70	u8 txbuf[8];71	u8 rxbuf[8];72	int rx_len = 8;73	int i;74	u32 jedec_id;75	u32 status;76 77	if (fw == NULL) {78		dev_err(&spi->dev, "Cannot load firmware, aborting\n");79		goto out;80	}81 82	if (fw->size == 0) {83		dev_err(&spi->dev, "Error: Firmware size is 0!\n");84		goto out;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	spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);95	jedec_id = get_unaligned_be32(&rxbuf[4]);96	dev_dbg(&spi->dev, "FPGA JTAG ID=%08x\n", jedec_id);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		goto out;107	}108 109	dev_info(&spi->dev, "FPGA %s detected\n", ecp3_dev[i].name);110 111	txbuf[0] = FPGA_CMD_READ_STATUS;112	spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);113	status = get_unaligned_be32(&rxbuf[4]);114	dev_dbg(&spi->dev, "FPGA Status=%08x\n", status);115 116	buffer = kzalloc(fw->size + 8, GFP_KERNEL);117	if (!buffer) {118		dev_err(&spi->dev, "Error: Can't allocate memory!\n");119		goto out;120	}121 122	/*123	 * Insert WRITE_INC command into stream (one SPI frame)124	 */125	buffer[0] = FPGA_CMD_WRITE_INC;126	buffer[1] = 0xff;127	buffer[2] = 0xff;128	buffer[3] = 0xff;129	memcpy(buffer + 4, fw->data, fw->size);130 131	txbuf[0] = FPGA_CMD_REFRESH;132	spi_write(spi, txbuf, 4);133 134	txbuf[0] = FPGA_CMD_WRITE_EN;135	spi_write(spi, txbuf, 4);136 137	txbuf[0] = FPGA_CMD_CLEAR;138	spi_write(spi, txbuf, 4);139 140	/*141	 * Wait for FPGA memory to become cleared142	 */143	for (i = 0; i < FPGA_CLEAR_LOOP_COUNT; i++) {144		txbuf[0] = FPGA_CMD_READ_STATUS;145		spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);146		status = get_unaligned_be32(&rxbuf[4]);147		if (status == FPGA_STATUS_CLEARED)148			break;149 150		msleep(FPGA_CLEAR_MSLEEP);151	}152 153	if (i == FPGA_CLEAR_LOOP_COUNT) {154		dev_err(&spi->dev,155			"Error: Timeout waiting for FPGA to clear (status=%08x)!\n",156			status);157		kfree(buffer);158		goto out;159	}160 161	dev_info(&spi->dev, "Configuring the FPGA...\n");162	spi_write(spi, buffer, fw->size + 8);163 164	txbuf[0] = FPGA_CMD_WRITE_DIS;165	spi_write(spi, txbuf, 4);166 167	txbuf[0] = FPGA_CMD_READ_STATUS;168	spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);169	status = get_unaligned_be32(&rxbuf[4]);170	dev_dbg(&spi->dev, "FPGA Status=%08x\n", status);171 172	/* Check result */173	if (status & FPGA_STATUS_DONE)174		dev_info(&spi->dev, "FPGA successfully configured!\n");175	else176		dev_info(&spi->dev, "FPGA not configured (DONE not set)\n");177 178	/*179	 * Don't forget to release the firmware again180	 */181	release_firmware(fw);182 183	kfree(buffer);184out:185	complete(&data->fw_loaded);186}187 188static int lattice_ecp3_probe(struct spi_device *spi)189{190	struct fpga_data *data;191	int err;192 193	data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);194	if (!data) {195		dev_err(&spi->dev, "Memory allocation for fpga_data failed\n");196		return -ENOMEM;197	}198	spi_set_drvdata(spi, data);199 200	init_completion(&data->fw_loaded);201	err = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,202				      FIRMWARE_NAME, &spi->dev,203				      GFP_KERNEL, spi, firmware_load);204	if (err) {205		dev_err(&spi->dev, "Firmware loading failed with %d!\n", err);206		return err;207	}208 209	dev_info(&spi->dev, "FPGA bitstream configuration driver registered\n");210 211	return 0;212}213 214static void lattice_ecp3_remove(struct spi_device *spi)215{216	struct fpga_data *data = spi_get_drvdata(spi);217 218	wait_for_completion(&data->fw_loaded);219}220 221static const struct spi_device_id lattice_ecp3_id[] = {222	{ "ecp3-17", 0 },223	{ "ecp3-35", 0 },224	{ }225};226MODULE_DEVICE_TABLE(spi, lattice_ecp3_id);227 228static struct spi_driver lattice_ecp3_driver = {229	.driver = {230		.name = "lattice-ecp3",231	},232	.probe = lattice_ecp3_probe,233	.remove = lattice_ecp3_remove,234	.id_table = lattice_ecp3_id,235};236 237module_spi_driver(lattice_ecp3_driver);238 239MODULE_AUTHOR("Stefan Roese <sr@denx.de>");240MODULE_DESCRIPTION("Lattice ECP3 FPGA configuration via SPI");241MODULE_LICENSE("GPL");242MODULE_FIRMWARE(FIRMWARE_NAME);243