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