brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · 44691cf Raw
154 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Lattice FPGA programming over slave SPI sysCONFIG interface.4 */5 6#include <linux/of.h>7#include <linux/spi/spi.h>8 9#include "lattice-sysconfig.h"10 11static const u32 ecp5_spi_max_speed_hz = 60000000;12 13static int sysconfig_spi_cmd_transfer(struct sysconfig_priv *priv,14				      const void *tx_buf, size_t tx_len,15				      void *rx_buf, size_t rx_len)16{17	struct spi_device *spi = to_spi_device(priv->dev);18 19	return spi_write_then_read(spi, tx_buf, tx_len, rx_buf, rx_len);20}21 22static int sysconfig_spi_bitstream_burst_init(struct sysconfig_priv *priv)23{24	const u8 lsc_bitstream_burst[] = SYSCONFIG_LSC_BITSTREAM_BURST;25	struct spi_device *spi = to_spi_device(priv->dev);26	struct spi_transfer xfer = {};27	struct spi_message msg;28	size_t buf_len;29	void *buf;30	int ret;31 32	buf_len = sizeof(lsc_bitstream_burst);33 34	buf = kmemdup(lsc_bitstream_burst, buf_len, GFP_KERNEL);35	if (!buf)36		return -ENOMEM;37 38	xfer.len = buf_len;39	xfer.tx_buf = buf;40	xfer.cs_change = 1;41 42	spi_message_init_with_transfers(&msg, &xfer, 1);43 44	/*45	 * Lock SPI bus for exclusive usage until FPGA programming is done.46	 * SPI bus will be released in sysconfig_spi_bitstream_burst_complete().47	 */48	spi_bus_lock(spi->controller);49 50	ret = spi_sync_locked(spi, &msg);51	if (ret)52		spi_bus_unlock(spi->controller);53 54	kfree(buf);55 56	return ret;57}58 59static int sysconfig_spi_bitstream_burst_write(struct sysconfig_priv *priv,60					       const char *buf, size_t len)61{62	struct spi_device *spi = to_spi_device(priv->dev);63	struct spi_transfer xfer = {64		.tx_buf = buf,65		.len = len,66		.cs_change = 1,67	};68	struct spi_message msg;69 70	spi_message_init_with_transfers(&msg, &xfer, 1);71 72	return spi_sync_locked(spi, &msg);73}74 75static int sysconfig_spi_bitstream_burst_complete(struct sysconfig_priv *priv)76{77	struct spi_device *spi = to_spi_device(priv->dev);78 79	/* Bitstream burst write is done, release SPI bus */80	spi_bus_unlock(spi->controller);81 82	/* Toggle CS to finish bitstream write */83	return spi_write(spi, NULL, 0);84}85 86static int sysconfig_spi_probe(struct spi_device *spi)87{88	const struct spi_device_id *dev_id;89	struct device *dev = &spi->dev;90	struct sysconfig_priv *priv;91	const u32 *spi_max_speed;92 93	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);94	if (!priv)95		return -ENOMEM;96 97	spi_max_speed = device_get_match_data(dev);98	if (!spi_max_speed) {99		dev_id = spi_get_device_id(spi);100		if (!dev_id)101			return -ENODEV;102 103		spi_max_speed = (const u32 *)dev_id->driver_data;104	}105 106	if (!spi_max_speed)107		return -EINVAL;108 109	if (spi->max_speed_hz > *spi_max_speed) {110		dev_err(dev, "SPI speed %u is too high, maximum speed is %u\n",111			spi->max_speed_hz, *spi_max_speed);112		return -EINVAL;113	}114 115	priv->dev = dev;116	priv->command_transfer = sysconfig_spi_cmd_transfer;117	priv->bitstream_burst_write_init = sysconfig_spi_bitstream_burst_init;118	priv->bitstream_burst_write = sysconfig_spi_bitstream_burst_write;119	priv->bitstream_burst_write_complete = sysconfig_spi_bitstream_burst_complete;120 121	return sysconfig_probe(priv);122}123 124static const struct spi_device_id sysconfig_spi_ids[] = {125	{126		.name = "sysconfig-ecp5",127		.driver_data = (kernel_ulong_t)&ecp5_spi_max_speed_hz,128	}, {},129};130MODULE_DEVICE_TABLE(spi, sysconfig_spi_ids);131 132#if IS_ENABLED(CONFIG_OF)133static const struct of_device_id sysconfig_of_ids[] = {134	{135		.compatible = "lattice,sysconfig-ecp5",136		.data = &ecp5_spi_max_speed_hz,137	}, {},138};139MODULE_DEVICE_TABLE(of, sysconfig_of_ids);140#endif /* IS_ENABLED(CONFIG_OF) */141 142static struct spi_driver lattice_sysconfig_driver = {143	.probe = sysconfig_spi_probe,144	.id_table = sysconfig_spi_ids,145	.driver = {146		.name = "lattice_sysconfig_spi_fpga_mgr",147		.of_match_table = of_match_ptr(sysconfig_of_ids),148	},149};150module_spi_driver(lattice_sysconfig_driver);151 152MODULE_DESCRIPTION("Lattice sysCONFIG Slave SPI FPGA Manager");153MODULE_LICENSE("GPL");154