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");
154