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