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
sysconfig_spi_cmd_transfer(struct sysconfig_priv * priv,const void * tx_buf,size_t tx_len,void * rx_buf,size_t rx_len)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
sysconfig_spi_bitstream_burst_init(struct sysconfig_priv * priv)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
sysconfig_spi_bitstream_burst_write(struct sysconfig_priv * priv,const char * buf,size_t len)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
sysconfig_spi_bitstream_burst_complete(struct sysconfig_priv * priv)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
sysconfig_spi_probe(struct spi_device * spi)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