1*463dd43bSIvan Bornyakov // SPDX-License-Identifier: GPL-2.0
2*463dd43bSIvan Bornyakov /*
3*463dd43bSIvan Bornyakov * Lattice FPGA sysCONFIG interface functions independent of port type.
4*463dd43bSIvan Bornyakov */
5*463dd43bSIvan Bornyakov
6*463dd43bSIvan Bornyakov #include <linux/delay.h>
7*463dd43bSIvan Bornyakov #include <linux/fpga/fpga-mgr.h>
8*463dd43bSIvan Bornyakov #include <linux/gpio/consumer.h>
9*463dd43bSIvan Bornyakov #include <linux/iopoll.h>
10*463dd43bSIvan Bornyakov
11*463dd43bSIvan Bornyakov #include "lattice-sysconfig.h"
12*463dd43bSIvan Bornyakov
sysconfig_cmd_write(struct sysconfig_priv * priv,const void * buf,size_t buf_len)13*463dd43bSIvan Bornyakov static int sysconfig_cmd_write(struct sysconfig_priv *priv, const void *buf,
14*463dd43bSIvan Bornyakov size_t buf_len)
15*463dd43bSIvan Bornyakov {
16*463dd43bSIvan Bornyakov return priv->command_transfer(priv, buf, buf_len, NULL, 0);
17*463dd43bSIvan Bornyakov }
18*463dd43bSIvan Bornyakov
sysconfig_cmd_read(struct sysconfig_priv * priv,const void * tx_buf,size_t tx_len,void * rx_buf,size_t rx_len)19*463dd43bSIvan Bornyakov static int sysconfig_cmd_read(struct sysconfig_priv *priv, const void *tx_buf,
20*463dd43bSIvan Bornyakov size_t tx_len, void *rx_buf, size_t rx_len)
21*463dd43bSIvan Bornyakov {
22*463dd43bSIvan Bornyakov return priv->command_transfer(priv, tx_buf, tx_len, rx_buf, rx_len);
23*463dd43bSIvan Bornyakov }
24*463dd43bSIvan Bornyakov
sysconfig_read_busy(struct sysconfig_priv * priv)25*463dd43bSIvan Bornyakov static int sysconfig_read_busy(struct sysconfig_priv *priv)
26*463dd43bSIvan Bornyakov {
27*463dd43bSIvan Bornyakov const u8 lsc_check_busy[] = SYSCONFIG_LSC_CHECK_BUSY;
28*463dd43bSIvan Bornyakov u8 busy;
29*463dd43bSIvan Bornyakov int ret;
30*463dd43bSIvan Bornyakov
31*463dd43bSIvan Bornyakov ret = sysconfig_cmd_read(priv, lsc_check_busy, sizeof(lsc_check_busy),
32*463dd43bSIvan Bornyakov &busy, sizeof(busy));
33*463dd43bSIvan Bornyakov
34*463dd43bSIvan Bornyakov return ret ? : busy;
35*463dd43bSIvan Bornyakov }
36*463dd43bSIvan Bornyakov
sysconfig_poll_busy(struct sysconfig_priv * priv)37*463dd43bSIvan Bornyakov static int sysconfig_poll_busy(struct sysconfig_priv *priv)
38*463dd43bSIvan Bornyakov {
39*463dd43bSIvan Bornyakov int ret, busy;
40*463dd43bSIvan Bornyakov
41*463dd43bSIvan Bornyakov ret = read_poll_timeout(sysconfig_read_busy, busy, busy <= 0,
42*463dd43bSIvan Bornyakov SYSCONFIG_POLL_INTERVAL_US,
43*463dd43bSIvan Bornyakov SYSCONFIG_POLL_BUSY_TIMEOUT_US, false, priv);
44*463dd43bSIvan Bornyakov
45*463dd43bSIvan Bornyakov return ret ? : busy;
46*463dd43bSIvan Bornyakov }
47*463dd43bSIvan Bornyakov
sysconfig_read_status(struct sysconfig_priv * priv,u32 * status)48*463dd43bSIvan Bornyakov static int sysconfig_read_status(struct sysconfig_priv *priv, u32 *status)
49*463dd43bSIvan Bornyakov {
50*463dd43bSIvan Bornyakov const u8 lsc_read_status[] = SYSCONFIG_LSC_READ_STATUS;
51*463dd43bSIvan Bornyakov __be32 device_status;
52*463dd43bSIvan Bornyakov int ret;
53*463dd43bSIvan Bornyakov
54*463dd43bSIvan Bornyakov ret = sysconfig_cmd_read(priv, lsc_read_status, sizeof(lsc_read_status),
55*463dd43bSIvan Bornyakov &device_status, sizeof(device_status));
56*463dd43bSIvan Bornyakov if (ret)
57*463dd43bSIvan Bornyakov return ret;
58*463dd43bSIvan Bornyakov
59*463dd43bSIvan Bornyakov *status = be32_to_cpu(device_status);
60*463dd43bSIvan Bornyakov
61*463dd43bSIvan Bornyakov return 0;
62*463dd43bSIvan Bornyakov }
63*463dd43bSIvan Bornyakov
sysconfig_poll_status(struct sysconfig_priv * priv,u32 * status)64*463dd43bSIvan Bornyakov static int sysconfig_poll_status(struct sysconfig_priv *priv, u32 *status)
65*463dd43bSIvan Bornyakov {
66*463dd43bSIvan Bornyakov int ret = sysconfig_poll_busy(priv);
67*463dd43bSIvan Bornyakov
68*463dd43bSIvan Bornyakov if (ret)
69*463dd43bSIvan Bornyakov return ret;
70*463dd43bSIvan Bornyakov
71*463dd43bSIvan Bornyakov return sysconfig_read_status(priv, status);
72*463dd43bSIvan Bornyakov }
73*463dd43bSIvan Bornyakov
sysconfig_poll_gpio(struct gpio_desc * gpio,bool is_active)74*463dd43bSIvan Bornyakov static int sysconfig_poll_gpio(struct gpio_desc *gpio, bool is_active)
75*463dd43bSIvan Bornyakov {
76*463dd43bSIvan Bornyakov int ret, val;
77*463dd43bSIvan Bornyakov
78*463dd43bSIvan Bornyakov ret = read_poll_timeout(gpiod_get_value, val,
79*463dd43bSIvan Bornyakov val < 0 || !!val == is_active,
80*463dd43bSIvan Bornyakov SYSCONFIG_POLL_INTERVAL_US,
81*463dd43bSIvan Bornyakov SYSCONFIG_POLL_GPIO_TIMEOUT_US, false, gpio);
82*463dd43bSIvan Bornyakov
83*463dd43bSIvan Bornyakov if (val < 0)
84*463dd43bSIvan Bornyakov return val;
85*463dd43bSIvan Bornyakov
86*463dd43bSIvan Bornyakov return ret;
87*463dd43bSIvan Bornyakov }
88*463dd43bSIvan Bornyakov
sysconfig_gpio_refresh(struct sysconfig_priv * priv)89*463dd43bSIvan Bornyakov static int sysconfig_gpio_refresh(struct sysconfig_priv *priv)
90*463dd43bSIvan Bornyakov {
91*463dd43bSIvan Bornyakov struct gpio_desc *program = priv->program;
92*463dd43bSIvan Bornyakov struct gpio_desc *init = priv->init;
93*463dd43bSIvan Bornyakov struct gpio_desc *done = priv->done;
94*463dd43bSIvan Bornyakov int ret;
95*463dd43bSIvan Bornyakov
96*463dd43bSIvan Bornyakov /* Enter init mode */
97*463dd43bSIvan Bornyakov gpiod_set_value(program, 1);
98*463dd43bSIvan Bornyakov
99*463dd43bSIvan Bornyakov ret = sysconfig_poll_gpio(init, true);
100*463dd43bSIvan Bornyakov if (!ret)
101*463dd43bSIvan Bornyakov ret = sysconfig_poll_gpio(done, false);
102*463dd43bSIvan Bornyakov
103*463dd43bSIvan Bornyakov if (ret)
104*463dd43bSIvan Bornyakov return ret;
105*463dd43bSIvan Bornyakov
106*463dd43bSIvan Bornyakov /* Enter program mode */
107*463dd43bSIvan Bornyakov gpiod_set_value(program, 0);
108*463dd43bSIvan Bornyakov
109*463dd43bSIvan Bornyakov return sysconfig_poll_gpio(init, false);
110*463dd43bSIvan Bornyakov }
111*463dd43bSIvan Bornyakov
sysconfig_lsc_refresh(struct sysconfig_priv * priv)112*463dd43bSIvan Bornyakov static int sysconfig_lsc_refresh(struct sysconfig_priv *priv)
113*463dd43bSIvan Bornyakov {
114*463dd43bSIvan Bornyakov static const u8 lsc_refresh[] = SYSCONFIG_LSC_REFRESH;
115*463dd43bSIvan Bornyakov int ret;
116*463dd43bSIvan Bornyakov
117*463dd43bSIvan Bornyakov ret = sysconfig_cmd_write(priv, lsc_refresh, sizeof(lsc_refresh));
118*463dd43bSIvan Bornyakov if (ret)
119*463dd43bSIvan Bornyakov return ret;
120*463dd43bSIvan Bornyakov
121*463dd43bSIvan Bornyakov usleep_range(4000, 8000);
122*463dd43bSIvan Bornyakov
123*463dd43bSIvan Bornyakov return 0;
124*463dd43bSIvan Bornyakov }
125*463dd43bSIvan Bornyakov
sysconfig_refresh(struct sysconfig_priv * priv)126*463dd43bSIvan Bornyakov static int sysconfig_refresh(struct sysconfig_priv *priv)
127*463dd43bSIvan Bornyakov {
128*463dd43bSIvan Bornyakov struct gpio_desc *program = priv->program;
129*463dd43bSIvan Bornyakov struct gpio_desc *init = priv->init;
130*463dd43bSIvan Bornyakov struct gpio_desc *done = priv->done;
131*463dd43bSIvan Bornyakov
132*463dd43bSIvan Bornyakov if (program && init && done)
133*463dd43bSIvan Bornyakov return sysconfig_gpio_refresh(priv);
134*463dd43bSIvan Bornyakov
135*463dd43bSIvan Bornyakov return sysconfig_lsc_refresh(priv);
136*463dd43bSIvan Bornyakov }
137*463dd43bSIvan Bornyakov
sysconfig_isc_enable(struct sysconfig_priv * priv)138*463dd43bSIvan Bornyakov static int sysconfig_isc_enable(struct sysconfig_priv *priv)
139*463dd43bSIvan Bornyakov {
140*463dd43bSIvan Bornyakov u8 isc_enable[] = SYSCONFIG_ISC_ENABLE;
141*463dd43bSIvan Bornyakov u32 status;
142*463dd43bSIvan Bornyakov int ret;
143*463dd43bSIvan Bornyakov
144*463dd43bSIvan Bornyakov ret = sysconfig_cmd_write(priv, isc_enable, sizeof(isc_enable));
145*463dd43bSIvan Bornyakov if (ret)
146*463dd43bSIvan Bornyakov return ret;
147*463dd43bSIvan Bornyakov
148*463dd43bSIvan Bornyakov ret = sysconfig_poll_status(priv, &status);
149*463dd43bSIvan Bornyakov if (ret)
150*463dd43bSIvan Bornyakov return ret;
151*463dd43bSIvan Bornyakov
152*463dd43bSIvan Bornyakov if (status & SYSCONFIG_STATUS_FAIL)
153*463dd43bSIvan Bornyakov return -EFAULT;
154*463dd43bSIvan Bornyakov
155*463dd43bSIvan Bornyakov return 0;
156*463dd43bSIvan Bornyakov }
157*463dd43bSIvan Bornyakov
sysconfig_isc_erase(struct sysconfig_priv * priv)158*463dd43bSIvan Bornyakov static int sysconfig_isc_erase(struct sysconfig_priv *priv)
159*463dd43bSIvan Bornyakov {
160*463dd43bSIvan Bornyakov u8 isc_erase[] = SYSCONFIG_ISC_ERASE;
161*463dd43bSIvan Bornyakov u32 status;
162*463dd43bSIvan Bornyakov int ret;
163*463dd43bSIvan Bornyakov
164*463dd43bSIvan Bornyakov ret = sysconfig_cmd_write(priv, isc_erase, sizeof(isc_erase));
165*463dd43bSIvan Bornyakov if (ret)
166*463dd43bSIvan Bornyakov return ret;
167*463dd43bSIvan Bornyakov
168*463dd43bSIvan Bornyakov ret = sysconfig_poll_status(priv, &status);
169*463dd43bSIvan Bornyakov if (ret)
170*463dd43bSIvan Bornyakov return ret;
171*463dd43bSIvan Bornyakov
172*463dd43bSIvan Bornyakov if (status & SYSCONFIG_STATUS_FAIL)
173*463dd43bSIvan Bornyakov return -EFAULT;
174*463dd43bSIvan Bornyakov
175*463dd43bSIvan Bornyakov return 0;
176*463dd43bSIvan Bornyakov }
177*463dd43bSIvan Bornyakov
sysconfig_isc_init(struct sysconfig_priv * priv)178*463dd43bSIvan Bornyakov static int sysconfig_isc_init(struct sysconfig_priv *priv)
179*463dd43bSIvan Bornyakov {
180*463dd43bSIvan Bornyakov int ret = sysconfig_isc_enable(priv);
181*463dd43bSIvan Bornyakov
182*463dd43bSIvan Bornyakov if (ret)
183*463dd43bSIvan Bornyakov return ret;
184*463dd43bSIvan Bornyakov
185*463dd43bSIvan Bornyakov return sysconfig_isc_erase(priv);
186*463dd43bSIvan Bornyakov }
187*463dd43bSIvan Bornyakov
sysconfig_lsc_init_addr(struct sysconfig_priv * priv)188*463dd43bSIvan Bornyakov static int sysconfig_lsc_init_addr(struct sysconfig_priv *priv)
189*463dd43bSIvan Bornyakov {
190*463dd43bSIvan Bornyakov const u8 lsc_init_addr[] = SYSCONFIG_LSC_INIT_ADDR;
191*463dd43bSIvan Bornyakov
192*463dd43bSIvan Bornyakov return sysconfig_cmd_write(priv, lsc_init_addr, sizeof(lsc_init_addr));
193*463dd43bSIvan Bornyakov }
194*463dd43bSIvan Bornyakov
sysconfig_burst_write_init(struct sysconfig_priv * priv)195*463dd43bSIvan Bornyakov static int sysconfig_burst_write_init(struct sysconfig_priv *priv)
196*463dd43bSIvan Bornyakov {
197*463dd43bSIvan Bornyakov return priv->bitstream_burst_write_init(priv);
198*463dd43bSIvan Bornyakov }
199*463dd43bSIvan Bornyakov
sysconfig_burst_write_complete(struct sysconfig_priv * priv)200*463dd43bSIvan Bornyakov static int sysconfig_burst_write_complete(struct sysconfig_priv *priv)
201*463dd43bSIvan Bornyakov {
202*463dd43bSIvan Bornyakov return priv->bitstream_burst_write_complete(priv);
203*463dd43bSIvan Bornyakov }
204*463dd43bSIvan Bornyakov
sysconfig_bitstream_burst_write(struct sysconfig_priv * priv,const char * buf,size_t count)205*463dd43bSIvan Bornyakov static int sysconfig_bitstream_burst_write(struct sysconfig_priv *priv,
206*463dd43bSIvan Bornyakov const char *buf, size_t count)
207*463dd43bSIvan Bornyakov {
208*463dd43bSIvan Bornyakov int ret = priv->bitstream_burst_write(priv, buf, count);
209*463dd43bSIvan Bornyakov
210*463dd43bSIvan Bornyakov if (ret)
211*463dd43bSIvan Bornyakov sysconfig_burst_write_complete(priv);
212*463dd43bSIvan Bornyakov
213*463dd43bSIvan Bornyakov return ret;
214*463dd43bSIvan Bornyakov }
215*463dd43bSIvan Bornyakov
sysconfig_isc_disable(struct sysconfig_priv * priv)216*463dd43bSIvan Bornyakov static int sysconfig_isc_disable(struct sysconfig_priv *priv)
217*463dd43bSIvan Bornyakov {
218*463dd43bSIvan Bornyakov const u8 isc_disable[] = SYSCONFIG_ISC_DISABLE;
219*463dd43bSIvan Bornyakov
220*463dd43bSIvan Bornyakov return sysconfig_cmd_write(priv, isc_disable, sizeof(isc_disable));
221*463dd43bSIvan Bornyakov }
222*463dd43bSIvan Bornyakov
sysconfig_cleanup(struct sysconfig_priv * priv)223*463dd43bSIvan Bornyakov static void sysconfig_cleanup(struct sysconfig_priv *priv)
224*463dd43bSIvan Bornyakov {
225*463dd43bSIvan Bornyakov sysconfig_isc_erase(priv);
226*463dd43bSIvan Bornyakov sysconfig_refresh(priv);
227*463dd43bSIvan Bornyakov }
228*463dd43bSIvan Bornyakov
sysconfig_isc_finish(struct sysconfig_priv * priv)229*463dd43bSIvan Bornyakov static int sysconfig_isc_finish(struct sysconfig_priv *priv)
230*463dd43bSIvan Bornyakov {
231*463dd43bSIvan Bornyakov struct gpio_desc *done_gpio = priv->done;
232*463dd43bSIvan Bornyakov u32 status;
233*463dd43bSIvan Bornyakov int ret;
234*463dd43bSIvan Bornyakov
235*463dd43bSIvan Bornyakov if (done_gpio) {
236*463dd43bSIvan Bornyakov ret = sysconfig_isc_disable(priv);
237*463dd43bSIvan Bornyakov if (ret)
238*463dd43bSIvan Bornyakov return ret;
239*463dd43bSIvan Bornyakov
240*463dd43bSIvan Bornyakov return sysconfig_poll_gpio(done_gpio, true);
241*463dd43bSIvan Bornyakov }
242*463dd43bSIvan Bornyakov
243*463dd43bSIvan Bornyakov ret = sysconfig_poll_status(priv, &status);
244*463dd43bSIvan Bornyakov if (ret)
245*463dd43bSIvan Bornyakov return ret;
246*463dd43bSIvan Bornyakov
247*463dd43bSIvan Bornyakov if ((status & SYSCONFIG_STATUS_DONE) &&
248*463dd43bSIvan Bornyakov !(status & SYSCONFIG_STATUS_BUSY) &&
249*463dd43bSIvan Bornyakov !(status & SYSCONFIG_STATUS_ERR))
250*463dd43bSIvan Bornyakov return sysconfig_isc_disable(priv);
251*463dd43bSIvan Bornyakov
252*463dd43bSIvan Bornyakov return -EFAULT;
253*463dd43bSIvan Bornyakov }
254*463dd43bSIvan Bornyakov
sysconfig_ops_state(struct fpga_manager * mgr)255*463dd43bSIvan Bornyakov static enum fpga_mgr_states sysconfig_ops_state(struct fpga_manager *mgr)
256*463dd43bSIvan Bornyakov {
257*463dd43bSIvan Bornyakov struct sysconfig_priv *priv = mgr->priv;
258*463dd43bSIvan Bornyakov struct gpio_desc *done = priv->done;
259*463dd43bSIvan Bornyakov u32 status;
260*463dd43bSIvan Bornyakov int ret;
261*463dd43bSIvan Bornyakov
262*463dd43bSIvan Bornyakov if (done && (gpiod_get_value(done) > 0))
263*463dd43bSIvan Bornyakov return FPGA_MGR_STATE_OPERATING;
264*463dd43bSIvan Bornyakov
265*463dd43bSIvan Bornyakov ret = sysconfig_read_status(priv, &status);
266*463dd43bSIvan Bornyakov if (!ret && (status & SYSCONFIG_STATUS_DONE))
267*463dd43bSIvan Bornyakov return FPGA_MGR_STATE_OPERATING;
268*463dd43bSIvan Bornyakov
269*463dd43bSIvan Bornyakov return FPGA_MGR_STATE_UNKNOWN;
270*463dd43bSIvan Bornyakov }
271*463dd43bSIvan Bornyakov
sysconfig_ops_write_init(struct fpga_manager * mgr,struct fpga_image_info * info,const char * buf,size_t count)272*463dd43bSIvan Bornyakov static int sysconfig_ops_write_init(struct fpga_manager *mgr,
273*463dd43bSIvan Bornyakov struct fpga_image_info *info,
274*463dd43bSIvan Bornyakov const char *buf, size_t count)
275*463dd43bSIvan Bornyakov {
276*463dd43bSIvan Bornyakov struct sysconfig_priv *priv = mgr->priv;
277*463dd43bSIvan Bornyakov struct device *dev = &mgr->dev;
278*463dd43bSIvan Bornyakov int ret;
279*463dd43bSIvan Bornyakov
280*463dd43bSIvan Bornyakov if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
281*463dd43bSIvan Bornyakov dev_err(dev, "Partial reconfiguration is not supported\n");
282*463dd43bSIvan Bornyakov return -EOPNOTSUPP;
283*463dd43bSIvan Bornyakov }
284*463dd43bSIvan Bornyakov
285*463dd43bSIvan Bornyakov /* Enter program mode */
286*463dd43bSIvan Bornyakov ret = sysconfig_refresh(priv);
287*463dd43bSIvan Bornyakov if (ret) {
288*463dd43bSIvan Bornyakov dev_err(dev, "Failed to go to program mode\n");
289*463dd43bSIvan Bornyakov return ret;
290*463dd43bSIvan Bornyakov }
291*463dd43bSIvan Bornyakov
292*463dd43bSIvan Bornyakov /* Enter ISC mode */
293*463dd43bSIvan Bornyakov ret = sysconfig_isc_init(priv);
294*463dd43bSIvan Bornyakov if (ret) {
295*463dd43bSIvan Bornyakov dev_err(dev, "Failed to go to ISC mode\n");
296*463dd43bSIvan Bornyakov return ret;
297*463dd43bSIvan Bornyakov }
298*463dd43bSIvan Bornyakov
299*463dd43bSIvan Bornyakov /* Initialize the Address Shift Register */
300*463dd43bSIvan Bornyakov ret = sysconfig_lsc_init_addr(priv);
301*463dd43bSIvan Bornyakov if (ret) {
302*463dd43bSIvan Bornyakov dev_err(dev,
303*463dd43bSIvan Bornyakov "Failed to initialize the Address Shift Register\n");
304*463dd43bSIvan Bornyakov return ret;
305*463dd43bSIvan Bornyakov }
306*463dd43bSIvan Bornyakov
307*463dd43bSIvan Bornyakov /* Prepare for bitstream burst write */
308*463dd43bSIvan Bornyakov ret = sysconfig_burst_write_init(priv);
309*463dd43bSIvan Bornyakov if (ret)
310*463dd43bSIvan Bornyakov dev_err(dev, "Failed to prepare for bitstream burst write\n");
311*463dd43bSIvan Bornyakov
312*463dd43bSIvan Bornyakov return ret;
313*463dd43bSIvan Bornyakov }
314*463dd43bSIvan Bornyakov
sysconfig_ops_write(struct fpga_manager * mgr,const char * buf,size_t count)315*463dd43bSIvan Bornyakov static int sysconfig_ops_write(struct fpga_manager *mgr, const char *buf,
316*463dd43bSIvan Bornyakov size_t count)
317*463dd43bSIvan Bornyakov {
318*463dd43bSIvan Bornyakov return sysconfig_bitstream_burst_write(mgr->priv, buf, count);
319*463dd43bSIvan Bornyakov }
320*463dd43bSIvan Bornyakov
sysconfig_ops_write_complete(struct fpga_manager * mgr,struct fpga_image_info * info)321*463dd43bSIvan Bornyakov static int sysconfig_ops_write_complete(struct fpga_manager *mgr,
322*463dd43bSIvan Bornyakov struct fpga_image_info *info)
323*463dd43bSIvan Bornyakov {
324*463dd43bSIvan Bornyakov struct sysconfig_priv *priv = mgr->priv;
325*463dd43bSIvan Bornyakov struct device *dev = &mgr->dev;
326*463dd43bSIvan Bornyakov int ret;
327*463dd43bSIvan Bornyakov
328*463dd43bSIvan Bornyakov ret = sysconfig_burst_write_complete(priv);
329*463dd43bSIvan Bornyakov if (!ret)
330*463dd43bSIvan Bornyakov ret = sysconfig_poll_busy(priv);
331*463dd43bSIvan Bornyakov
332*463dd43bSIvan Bornyakov if (ret) {
333*463dd43bSIvan Bornyakov dev_err(dev, "Error while waiting bitstream write to finish\n");
334*463dd43bSIvan Bornyakov goto fail;
335*463dd43bSIvan Bornyakov }
336*463dd43bSIvan Bornyakov
337*463dd43bSIvan Bornyakov ret = sysconfig_isc_finish(priv);
338*463dd43bSIvan Bornyakov
339*463dd43bSIvan Bornyakov fail:
340*463dd43bSIvan Bornyakov if (ret)
341*463dd43bSIvan Bornyakov sysconfig_cleanup(priv);
342*463dd43bSIvan Bornyakov
343*463dd43bSIvan Bornyakov return ret;
344*463dd43bSIvan Bornyakov }
345*463dd43bSIvan Bornyakov
346*463dd43bSIvan Bornyakov static const struct fpga_manager_ops sysconfig_fpga_mgr_ops = {
347*463dd43bSIvan Bornyakov .state = sysconfig_ops_state,
348*463dd43bSIvan Bornyakov .write_init = sysconfig_ops_write_init,
349*463dd43bSIvan Bornyakov .write = sysconfig_ops_write,
350*463dd43bSIvan Bornyakov .write_complete = sysconfig_ops_write_complete,
351*463dd43bSIvan Bornyakov };
352*463dd43bSIvan Bornyakov
sysconfig_probe(struct sysconfig_priv * priv)353*463dd43bSIvan Bornyakov int sysconfig_probe(struct sysconfig_priv *priv)
354*463dd43bSIvan Bornyakov {
355*463dd43bSIvan Bornyakov struct gpio_desc *program, *init, *done;
356*463dd43bSIvan Bornyakov struct device *dev = priv->dev;
357*463dd43bSIvan Bornyakov struct fpga_manager *mgr;
358*463dd43bSIvan Bornyakov
359*463dd43bSIvan Bornyakov if (!dev)
360*463dd43bSIvan Bornyakov return -ENODEV;
361*463dd43bSIvan Bornyakov
362*463dd43bSIvan Bornyakov if (!priv->command_transfer ||
363*463dd43bSIvan Bornyakov !priv->bitstream_burst_write_init ||
364*463dd43bSIvan Bornyakov !priv->bitstream_burst_write ||
365*463dd43bSIvan Bornyakov !priv->bitstream_burst_write_complete) {
366*463dd43bSIvan Bornyakov dev_err(dev, "Essential callback is missing\n");
367*463dd43bSIvan Bornyakov return -EINVAL;
368*463dd43bSIvan Bornyakov }
369*463dd43bSIvan Bornyakov
370*463dd43bSIvan Bornyakov program = devm_gpiod_get_optional(dev, "program", GPIOD_OUT_LOW);
371*463dd43bSIvan Bornyakov if (IS_ERR(program))
372*463dd43bSIvan Bornyakov return dev_err_probe(dev, PTR_ERR(program),
373*463dd43bSIvan Bornyakov "Failed to get PROGRAM GPIO\n");
374*463dd43bSIvan Bornyakov
375*463dd43bSIvan Bornyakov init = devm_gpiod_get_optional(dev, "init", GPIOD_IN);
376*463dd43bSIvan Bornyakov if (IS_ERR(init))
377*463dd43bSIvan Bornyakov return dev_err_probe(dev, PTR_ERR(init),
378*463dd43bSIvan Bornyakov "Failed to get INIT GPIO\n");
379*463dd43bSIvan Bornyakov
380*463dd43bSIvan Bornyakov done = devm_gpiod_get_optional(dev, "done", GPIOD_IN);
381*463dd43bSIvan Bornyakov if (IS_ERR(done))
382*463dd43bSIvan Bornyakov return dev_err_probe(dev, PTR_ERR(done),
383*463dd43bSIvan Bornyakov "Failed to get DONE GPIO\n");
384*463dd43bSIvan Bornyakov
385*463dd43bSIvan Bornyakov priv->program = program;
386*463dd43bSIvan Bornyakov priv->init = init;
387*463dd43bSIvan Bornyakov priv->done = done;
388*463dd43bSIvan Bornyakov
389*463dd43bSIvan Bornyakov mgr = devm_fpga_mgr_register(dev, "Lattice sysCONFIG FPGA Manager",
390*463dd43bSIvan Bornyakov &sysconfig_fpga_mgr_ops, priv);
391*463dd43bSIvan Bornyakov
392*463dd43bSIvan Bornyakov return PTR_ERR_OR_ZERO(mgr);
393*463dd43bSIvan Bornyakov }
394*463dd43bSIvan Bornyakov EXPORT_SYMBOL(sysconfig_probe);
395*463dd43bSIvan Bornyakov
396*463dd43bSIvan Bornyakov MODULE_DESCRIPTION("Lattice sysCONFIG FPGA Manager Core");
397*463dd43bSIvan Bornyakov MODULE_LICENSE("GPL");
398