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