brintos

brintos / linux-shallow public Read only

0
0
Text · 8.7 KiB · ba51a60 Raw
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