brintos

brintos / linux-shallow public Read only

0
0
Text · 9.7 KiB · 6134cea Raw
413 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Microchip Polarfire FPGA programming over slave SPI interface.4 */5 6#include <linux/unaligned.h>7#include <linux/delay.h>8#include <linux/fpga/fpga-mgr.h>9#include <linux/iopoll.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/spi/spi.h>13 14#define	MPF_SPI_ISC_ENABLE	0x0B15#define	MPF_SPI_ISC_DISABLE	0x0C16#define	MPF_SPI_READ_STATUS	0x0017#define	MPF_SPI_READ_DATA	0x0118#define	MPF_SPI_FRAME_INIT	0xAE19#define	MPF_SPI_FRAME		0xEE20#define	MPF_SPI_PRG_MODE	0x0121#define	MPF_SPI_RELEASE		0x2322 23#define	MPF_SPI_FRAME_SIZE	1624 25#define	MPF_HEADER_SIZE_OFFSET	2426#define	MPF_DATA_SIZE_OFFSET	5527 28#define	MPF_LOOKUP_TABLE_RECORD_SIZE		929#define	MPF_LOOKUP_TABLE_BLOCK_ID_OFFSET	030#define	MPF_LOOKUP_TABLE_BLOCK_START_OFFSET	131 32#define	MPF_COMPONENTS_SIZE_ID	533#define	MPF_BITSTREAM_ID	834 35#define	MPF_BITS_PER_COMPONENT_SIZE	2236 37#define	MPF_STATUS_POLL_TIMEOUT		(2 * USEC_PER_SEC)38#define	MPF_STATUS_BUSY			BIT(0)39#define	MPF_STATUS_READY		BIT(1)40#define	MPF_STATUS_SPI_VIOLATION	BIT(2)41#define	MPF_STATUS_SPI_ERROR		BIT(3)42 43struct mpf_priv {44	struct spi_device *spi;45	bool program_mode;46	u8 tx __aligned(ARCH_KMALLOC_MINALIGN);47	u8 rx;48};49 50static int mpf_read_status(struct mpf_priv *priv)51{52	/*53	 * HW status is returned on MISO in the first byte after CS went54	 * active. However, first reading can be inadequate, so we submit55	 * two identical SPI transfers and use result of the later one.56	 */57	struct spi_transfer xfers[2] = {58		{59			.tx_buf = &priv->tx,60			.rx_buf = &priv->rx,61			.len = 1,62			.cs_change = 1,63		}, {64			.tx_buf = &priv->tx,65			.rx_buf = &priv->rx,66			.len = 1,67		},68	};69	u8 status;70	int ret;71 72	priv->tx = MPF_SPI_READ_STATUS;73 74	ret = spi_sync_transfer(priv->spi, xfers, 2);75	if (ret)76		return ret;77 78	status = priv->rx;79 80	if ((status & MPF_STATUS_SPI_VIOLATION) ||81	    (status & MPF_STATUS_SPI_ERROR))82		return -EIO;83 84	return status;85}86 87static enum fpga_mgr_states mpf_ops_state(struct fpga_manager *mgr)88{89	struct mpf_priv *priv = mgr->priv;90	bool program_mode;91	int status;92 93	program_mode = priv->program_mode;94	status = mpf_read_status(priv);95 96	if (!program_mode && !status)97		return FPGA_MGR_STATE_OPERATING;98 99	return FPGA_MGR_STATE_UNKNOWN;100}101 102static int mpf_ops_parse_header(struct fpga_manager *mgr,103				struct fpga_image_info *info,104				const char *buf, size_t count)105{106	size_t component_size_byte_num, component_size_byte_off,107	       components_size_start, bitstream_start,108	       block_id_offset, block_start_offset;109	u8 header_size, blocks_num, block_id;110	u32 block_start, component_size;111	u16 components_num, i;112 113	if (!buf) {114		dev_err(&mgr->dev, "Image buffer is not provided\n");115		return -EINVAL;116	}117 118	header_size = *(buf + MPF_HEADER_SIZE_OFFSET);119	if (header_size > count) {120		info->header_size = header_size;121		return -EAGAIN;122	}123 124	/*125	 * Go through look-up table to find out where actual bitstream starts126	 * and where sizes of components of the bitstream lies.127	 */128	blocks_num = *(buf + header_size - 1);129	block_id_offset = header_size + MPF_LOOKUP_TABLE_BLOCK_ID_OFFSET;130	block_start_offset = header_size + MPF_LOOKUP_TABLE_BLOCK_START_OFFSET;131 132	header_size += blocks_num * MPF_LOOKUP_TABLE_RECORD_SIZE;133	if (header_size > count) {134		info->header_size = header_size;135		return -EAGAIN;136	}137 138	components_size_start = 0;139	bitstream_start = 0;140 141	while (blocks_num--) {142		block_id = *(buf + block_id_offset);143		block_start = get_unaligned_le32(buf + block_start_offset);144 145		switch (block_id) {146		case MPF_BITSTREAM_ID:147			bitstream_start = block_start;148			info->header_size = block_start;149			if (block_start > count)150				return -EAGAIN;151 152			break;153		case MPF_COMPONENTS_SIZE_ID:154			components_size_start = block_start;155			break;156		default:157			break;158		}159 160		if (bitstream_start && components_size_start)161			break;162 163		block_id_offset += MPF_LOOKUP_TABLE_RECORD_SIZE;164		block_start_offset += MPF_LOOKUP_TABLE_RECORD_SIZE;165	}166 167	if (!bitstream_start || !components_size_start) {168		dev_err(&mgr->dev, "Failed to parse header look-up table\n");169		return -EFAULT;170	}171 172	/*173	 * Parse bitstream size.174	 * Sizes of components of the bitstream are 22-bits long placed next175	 * to each other. Image header should be extended by now up to where176	 * actual bitstream starts, so no need for overflow check anymore.177	 */178	components_num = get_unaligned_le16(buf + MPF_DATA_SIZE_OFFSET);179 180	for (i = 0; i < components_num; i++) {181		component_size_byte_num =182			(i * MPF_BITS_PER_COMPONENT_SIZE) / BITS_PER_BYTE;183		component_size_byte_off =184			(i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;185 186		component_size = get_unaligned_le32(buf +187						    components_size_start +188						    component_size_byte_num);189		component_size >>= component_size_byte_off;190		component_size &= GENMASK(MPF_BITS_PER_COMPONENT_SIZE - 1, 0);191 192		info->data_size += component_size * MPF_SPI_FRAME_SIZE;193	}194 195	return 0;196}197 198static int mpf_poll_status(struct mpf_priv *priv, u8 mask)199{200	int ret, status;201 202	/*203	 * Busy poll HW status. Polling stops if any of the following204	 * conditions are met:205	 *  - timeout is reached206	 *  - mpf_read_status() returns an error207	 *  - busy bit is cleared AND mask bits are set208	 */209	ret = read_poll_timeout(mpf_read_status, status,210				(status < 0) ||211				((status & (MPF_STATUS_BUSY | mask)) == mask),212				0, MPF_STATUS_POLL_TIMEOUT, false, priv);213	if (ret < 0)214		return ret;215 216	return status;217}218 219static int mpf_spi_write(struct mpf_priv *priv, const void *buf, size_t buf_size)220{221	int status = mpf_poll_status(priv, 0);222 223	if (status < 0)224		return status;225 226	return spi_write_then_read(priv->spi, buf, buf_size, NULL, 0);227}228 229static int mpf_spi_write_then_read(struct mpf_priv *priv,230				   const void *txbuf, size_t txbuf_size,231				   void *rxbuf, size_t rxbuf_size)232{233	const u8 read_command[] = { MPF_SPI_READ_DATA };234	int ret;235 236	ret = mpf_spi_write(priv, txbuf, txbuf_size);237	if (ret)238		return ret;239 240	ret = mpf_poll_status(priv, MPF_STATUS_READY);241	if (ret < 0)242		return ret;243 244	return spi_write_then_read(priv->spi, read_command, sizeof(read_command),245				   rxbuf, rxbuf_size);246}247 248static int mpf_ops_write_init(struct fpga_manager *mgr,249			      struct fpga_image_info *info, const char *buf,250			      size_t count)251{252	const u8 program_mode[] = { MPF_SPI_FRAME_INIT, MPF_SPI_PRG_MODE };253	const u8 isc_en_command[] = { MPF_SPI_ISC_ENABLE };254	struct mpf_priv *priv = mgr->priv;255	struct device *dev = &mgr->dev;256	u32 isc_ret = 0;257	int ret;258 259	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {260		dev_err(dev, "Partial reconfiguration is not supported\n");261		return -EOPNOTSUPP;262	}263 264	ret = mpf_spi_write_then_read(priv, isc_en_command, sizeof(isc_en_command),265				      &isc_ret, sizeof(isc_ret));266	if (ret || isc_ret) {267		dev_err(dev, "Failed to enable ISC: spi_ret %d, isc_ret %u\n",268			ret, isc_ret);269		return -EFAULT;270	}271 272	ret = mpf_spi_write(priv, program_mode, sizeof(program_mode));273	if (ret) {274		dev_err(dev, "Failed to enter program mode: %d\n", ret);275		return ret;276	}277 278	priv->program_mode = true;279 280	return 0;281}282 283static int mpf_spi_frame_write(struct mpf_priv *priv, const char *buf)284{285	struct spi_transfer xfers[2] = {286		{287			.tx_buf = &priv->tx,288			.len = 1,289		}, {290			.tx_buf = buf,291			.len = MPF_SPI_FRAME_SIZE,292		},293	};294	int ret;295 296	ret = mpf_poll_status(priv, 0);297	if (ret < 0)298		return ret;299 300	priv->tx = MPF_SPI_FRAME;301 302	return spi_sync_transfer(priv->spi, xfers, ARRAY_SIZE(xfers));303}304 305static int mpf_ops_write(struct fpga_manager *mgr, const char *buf, size_t count)306{307	struct mpf_priv *priv = mgr->priv;308	struct device *dev = &mgr->dev;309	int ret, i;310 311	if (count % MPF_SPI_FRAME_SIZE) {312		dev_err(dev, "Bitstream size is not a multiple of %d\n",313			MPF_SPI_FRAME_SIZE);314		return -EINVAL;315	}316 317	for (i = 0; i < count / MPF_SPI_FRAME_SIZE; i++) {318		ret = mpf_spi_frame_write(priv, buf + i * MPF_SPI_FRAME_SIZE);319		if (ret) {320			dev_err(dev, "Failed to write bitstream frame %d/%zu\n",321				i, count / MPF_SPI_FRAME_SIZE);322			return ret;323		}324	}325 326	return 0;327}328 329static int mpf_ops_write_complete(struct fpga_manager *mgr,330				  struct fpga_image_info *info)331{332	const u8 isc_dis_command[] = { MPF_SPI_ISC_DISABLE };333	const u8 release_command[] = { MPF_SPI_RELEASE };334	struct mpf_priv *priv = mgr->priv;335	struct device *dev = &mgr->dev;336	int ret;337 338	ret = mpf_spi_write(priv, isc_dis_command, sizeof(isc_dis_command));339	if (ret) {340		dev_err(dev, "Failed to disable ISC: %d\n", ret);341		return ret;342	}343 344	usleep_range(1000, 2000);345 346	ret = mpf_spi_write(priv, release_command, sizeof(release_command));347	if (ret) {348		dev_err(dev, "Failed to exit program mode: %d\n", ret);349		return ret;350	}351 352	priv->program_mode = false;353 354	return 0;355}356 357static const struct fpga_manager_ops mpf_ops = {358	.state = mpf_ops_state,359	.initial_header_size = 71,360	.skip_header = true,361	.parse_header = mpf_ops_parse_header,362	.write_init = mpf_ops_write_init,363	.write = mpf_ops_write,364	.write_complete = mpf_ops_write_complete,365};366 367static int mpf_probe(struct spi_device *spi)368{369	struct device *dev = &spi->dev;370	struct fpga_manager *mgr;371	struct mpf_priv *priv;372 373	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);374	if (!priv)375		return -ENOMEM;376 377	priv->spi = spi;378 379	mgr = devm_fpga_mgr_register(dev, "Microchip Polarfire SPI FPGA Manager",380				     &mpf_ops, priv);381 382	return PTR_ERR_OR_ZERO(mgr);383}384 385static const struct spi_device_id mpf_spi_ids[] = {386	{ .name = "mpf-spi-fpga-mgr", },387	{},388};389MODULE_DEVICE_TABLE(spi, mpf_spi_ids);390 391#if IS_ENABLED(CONFIG_OF)392static const struct of_device_id mpf_of_ids[] = {393	{ .compatible = "microchip,mpf-spi-fpga-mgr" },394	{},395};396MODULE_DEVICE_TABLE(of, mpf_of_ids);397#endif /* IS_ENABLED(CONFIG_OF) */398 399static struct spi_driver mpf_driver = {400	.probe = mpf_probe,401	.id_table = mpf_spi_ids,402	.driver = {403		.name = "microchip_mpf_spi_fpga_mgr",404		.of_match_table = of_match_ptr(mpf_of_ids),405	},406};407 408module_spi_driver(mpf_driver);409 410MODULE_DESCRIPTION("Microchip Polarfire SPI FPGA Manager");411MODULE_AUTHOR("Ivan Bornyakov <i.bornyakov@metrotek.ru>");412MODULE_LICENSE("GPL");413