Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.14.15.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  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");