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 | |
11 | static const u32 ecp5_spi_max_speed_hz = 60000000; |
12 | |
13 | static 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(dev: priv->dev); |
18 | |
19 | return spi_write_then_read(spi, txbuf: tx_buf, n_tx: tx_len, rxbuf: rx_buf, n_rx: rx_len); |
20 | } |
21 | |
22 | static 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(dev: 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(p: lsc_bitstream_burst, size: 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(m: &msg, xfers: &xfer, num_xfers: 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(ctlr: spi->controller); |
49 | |
50 | ret = spi_sync_locked(spi, message: &msg); |
51 | if (ret) |
52 | spi_bus_unlock(ctlr: spi->controller); |
53 | |
54 | kfree(objp: buf); |
55 | |
56 | return ret; |
57 | } |
58 | |
59 | static 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(dev: 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(m: &msg, xfers: &xfer, num_xfers: 1); |
71 | |
72 | return spi_sync_locked(spi, message: &msg); |
73 | } |
74 | |
75 | static int sysconfig_spi_bitstream_burst_complete(struct sysconfig_priv *priv) |
76 | { |
77 | struct spi_device *spi = to_spi_device(dev: priv->dev); |
78 | |
79 | /* Bitstream burst write is done, release SPI bus */ |
80 | spi_bus_unlock(ctlr: spi->controller); |
81 | |
82 | /* Toggle CS to finish bitstream write */ |
83 | return spi_write(spi, NULL, len: 0); |
84 | } |
85 | |
86 | static 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, size: 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(sdev: 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 | |
124 | static 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 | }; |
130 | MODULE_DEVICE_TABLE(spi, sysconfig_spi_ids); |
131 | |
132 | #if IS_ENABLED(CONFIG_OF) |
133 | static const struct of_device_id sysconfig_of_ids[] = { |
134 | { |
135 | .compatible = "lattice,sysconfig-ecp5" , |
136 | .data = &ecp5_spi_max_speed_hz, |
137 | }, {}, |
138 | }; |
139 | MODULE_DEVICE_TABLE(of, sysconfig_of_ids); |
140 | #endif /* IS_ENABLED(CONFIG_OF) */ |
141 | |
142 | static 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 | }; |
150 | module_spi_driver(lattice_sysconfig_driver); |
151 | |
152 | MODULE_DESCRIPTION("Lattice sysCONFIG Slave SPI FPGA Manager" ); |
153 | MODULE_LICENSE("GPL" ); |
154 | |