brintos

brintos / linux-shallow public Read only

0
0
Text · 11.8 KiB · 2c0def7 Raw
502 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * FPGA Manager Driver for Intel Stratix10 SoC4 *5 *  Copyright (C) 2018 Intel Corporation6 */7#include <linux/completion.h>8#include <linux/fpga/fpga-mgr.h>9#include <linux/firmware/intel/stratix10-svc-client.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/of_platform.h>13#include <linux/platform_device.h>14 15/*16 * FPGA programming requires a higher level of privilege (EL3), per the SoC17 * design.18 */19#define NUM_SVC_BUFS	420#define SVC_BUF_SIZE	SZ_512K21 22/* Indicates buffer is in use if set */23#define SVC_BUF_LOCK	024 25#define S10_BUFFER_TIMEOUT (msecs_to_jiffies(SVC_RECONFIG_BUFFER_TIMEOUT_MS))26#define S10_RECONFIG_TIMEOUT (msecs_to_jiffies(SVC_RECONFIG_REQUEST_TIMEOUT_MS))27 28/*29 * struct s10_svc_buf30 * buf:  virtual address of buf provided by service layer31 * lock: locked if buffer is in use32 */33struct s10_svc_buf {34	char *buf;35	unsigned long lock;36};37 38struct s10_priv {39	struct stratix10_svc_chan *chan;40	struct stratix10_svc_client client;41	struct completion status_return_completion;42	struct s10_svc_buf svc_bufs[NUM_SVC_BUFS];43	unsigned long status;44};45 46static int s10_svc_send_msg(struct s10_priv *priv,47			    enum stratix10_svc_command_code command,48			    void *payload, u32 payload_length)49{50	struct stratix10_svc_chan *chan = priv->chan;51	struct device *dev = priv->client.dev;52	struct stratix10_svc_client_msg msg;53	int ret;54 55	dev_dbg(dev, "%s cmd=%d payload=%p length=%d\n",56		__func__, command, payload, payload_length);57 58	msg.command = command;59	msg.payload = payload;60	msg.payload_length = payload_length;61 62	ret = stratix10_svc_send(chan, &msg);63	dev_dbg(dev, "stratix10_svc_send returned status %d\n", ret);64 65	return ret;66}67 68/*69 * Free buffers allocated from the service layer's pool that are not in use.70 * Return true when all buffers are freed.71 */72static bool s10_free_buffers(struct fpga_manager *mgr)73{74	struct s10_priv *priv = mgr->priv;75	uint num_free = 0;76	uint i;77 78	for (i = 0; i < NUM_SVC_BUFS; i++) {79		if (!priv->svc_bufs[i].buf) {80			num_free++;81			continue;82		}83 84		if (!test_and_set_bit_lock(SVC_BUF_LOCK,85					   &priv->svc_bufs[i].lock)) {86			stratix10_svc_free_memory(priv->chan,87						  priv->svc_bufs[i].buf);88			priv->svc_bufs[i].buf = NULL;89			num_free++;90		}91	}92 93	return num_free == NUM_SVC_BUFS;94}95 96/*97 * Returns count of how many buffers are not in use.98 */99static uint s10_free_buffer_count(struct fpga_manager *mgr)100{101	struct s10_priv *priv = mgr->priv;102	uint num_free = 0;103	uint i;104 105	for (i = 0; i < NUM_SVC_BUFS; i++)106		if (!priv->svc_bufs[i].buf)107			num_free++;108 109	return num_free;110}111 112/*113 * s10_unlock_bufs114 * Given the returned buffer address, match that address to our buffer struct115 * and unlock that buffer.  This marks it as available to be refilled and sent116 * (or freed).117 * priv: private data118 * kaddr: kernel address of buffer that was returned from service layer119 */120static void s10_unlock_bufs(struct s10_priv *priv, void *kaddr)121{122	uint i;123 124	if (!kaddr)125		return;126 127	for (i = 0; i < NUM_SVC_BUFS; i++)128		if (priv->svc_bufs[i].buf == kaddr) {129			clear_bit_unlock(SVC_BUF_LOCK,130					 &priv->svc_bufs[i].lock);131			return;132		}133 134	WARN(1, "Unknown buffer returned from service layer %p\n", kaddr);135}136 137/*138 * s10_receive_callback - callback for service layer to use to provide client139 * (this driver) messages received through the mailbox.140 * client: service layer client struct141 * data: message from service layer142 */143static void s10_receive_callback(struct stratix10_svc_client *client,144				 struct stratix10_svc_cb_data *data)145{146	struct s10_priv *priv = client->priv;147	u32 status;148	int i;149 150	WARN_ONCE(!data, "%s: stratix10_svc_rc_data = NULL", __func__);151 152	status = data->status;153 154	/*155	 * Here we set status bits as we receive them.  Elsewhere, we always use156	 * test_and_clear_bit() to check status in priv->status157	 */158	for (i = 0; i <= SVC_STATUS_ERROR; i++)159		if (status & (1 << i))160			set_bit(i, &priv->status);161 162	if (status & BIT(SVC_STATUS_BUFFER_DONE)) {163		s10_unlock_bufs(priv, data->kaddr1);164		s10_unlock_bufs(priv, data->kaddr2);165		s10_unlock_bufs(priv, data->kaddr3);166	}167 168	complete(&priv->status_return_completion);169}170 171/*172 * s10_ops_write_init - prepare for FPGA reconfiguration by requesting173 * partial reconfig and allocating buffers from the service layer.174 */175static int s10_ops_write_init(struct fpga_manager *mgr,176			      struct fpga_image_info *info,177			      const char *buf, size_t count)178{179	struct s10_priv *priv = mgr->priv;180	struct device *dev = priv->client.dev;181	struct stratix10_svc_command_config_type ctype;182	char *kbuf;183	uint i;184	int ret;185 186	ctype.flags = 0;187	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {188		dev_dbg(dev, "Requesting partial reconfiguration.\n");189		ctype.flags |= BIT(COMMAND_RECONFIG_FLAG_PARTIAL);190	} else {191		dev_dbg(dev, "Requesting full reconfiguration.\n");192	}193 194	reinit_completion(&priv->status_return_completion);195	ret = s10_svc_send_msg(priv, COMMAND_RECONFIG,196			       &ctype, sizeof(ctype));197	if (ret < 0)198		goto init_done;199 200	ret = wait_for_completion_timeout(201		&priv->status_return_completion, S10_RECONFIG_TIMEOUT);202	if (!ret) {203		dev_err(dev, "timeout waiting for RECONFIG_REQUEST\n");204		ret = -ETIMEDOUT;205		goto init_done;206	}207 208	ret = 0;209	if (!test_and_clear_bit(SVC_STATUS_OK, &priv->status)) {210		ret = -ETIMEDOUT;211		goto init_done;212	}213 214	/* Allocate buffers from the service layer's pool. */215	for (i = 0; i < NUM_SVC_BUFS; i++) {216		kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE);217		if (IS_ERR(kbuf)) {218			s10_free_buffers(mgr);219			ret = PTR_ERR(kbuf);220			goto init_done;221		}222 223		priv->svc_bufs[i].buf = kbuf;224		priv->svc_bufs[i].lock = 0;225	}226 227init_done:228	stratix10_svc_done(priv->chan);229	return ret;230}231 232/*233 * s10_send_buf - send a buffer to the service layer queue234 * mgr: fpga manager struct235 * buf: fpga image buffer236 * count: size of buf in bytes237 * Returns # of bytes transferred or -ENOBUFS if the all the buffers are in use238 * or if the service queue is full. Never returns 0.239 */240static int s10_send_buf(struct fpga_manager *mgr, const char *buf, size_t count)241{242	struct s10_priv *priv = mgr->priv;243	struct device *dev = priv->client.dev;244	void *svc_buf;245	size_t xfer_sz;246	int ret;247	uint i;248 249	/* get/lock a buffer that that's not being used */250	for (i = 0; i < NUM_SVC_BUFS; i++)251		if (!test_and_set_bit_lock(SVC_BUF_LOCK,252					   &priv->svc_bufs[i].lock))253			break;254 255	if (i == NUM_SVC_BUFS)256		return -ENOBUFS;257 258	xfer_sz = count < SVC_BUF_SIZE ? count : SVC_BUF_SIZE;259 260	svc_buf = priv->svc_bufs[i].buf;261	memcpy(svc_buf, buf, xfer_sz);262	ret = s10_svc_send_msg(priv, COMMAND_RECONFIG_DATA_SUBMIT,263			       svc_buf, xfer_sz);264	if (ret < 0) {265		dev_err(dev,266			"Error while sending data to service layer (%d)", ret);267		clear_bit_unlock(SVC_BUF_LOCK, &priv->svc_bufs[i].lock);268		return ret;269	}270 271	return xfer_sz;272}273 274/*275 * Send an FPGA image to privileged layers to write to the FPGA.  When done276 * sending, free all service layer buffers we allocated in write_init.277 */278static int s10_ops_write(struct fpga_manager *mgr, const char *buf,279			 size_t count)280{281	struct s10_priv *priv = mgr->priv;282	struct device *dev = priv->client.dev;283	long wait_status;284	int sent = 0;285	int ret = 0;286 287	/*288	 * Loop waiting for buffers to be returned.  When a buffer is returned,289	 * reuse it to send more data or free if if all data has been sent.290	 */291	while (count > 0 || s10_free_buffer_count(mgr) != NUM_SVC_BUFS) {292		reinit_completion(&priv->status_return_completion);293 294		if (count > 0) {295			sent = s10_send_buf(mgr, buf, count);296			if (sent < 0)297				continue;298 299			count -= sent;300			buf += sent;301		} else {302			if (s10_free_buffers(mgr))303				return 0;304 305			ret = s10_svc_send_msg(306				priv, COMMAND_RECONFIG_DATA_CLAIM,307				NULL, 0);308			if (ret < 0)309				break;310		}311 312		/*313		 * If callback hasn't already happened, wait for buffers to be314		 * returned from service layer315		 */316		wait_status = 1; /* not timed out */317		if (!priv->status)318			wait_status = wait_for_completion_timeout(319				&priv->status_return_completion,320				S10_BUFFER_TIMEOUT);321 322		if (test_and_clear_bit(SVC_STATUS_BUFFER_DONE, &priv->status) ||323		    test_and_clear_bit(SVC_STATUS_BUFFER_SUBMITTED,324				       &priv->status)) {325			ret = 0;326			continue;327		}328 329		if (test_and_clear_bit(SVC_STATUS_ERROR, &priv->status)) {330			dev_err(dev, "ERROR - giving up - SVC_STATUS_ERROR\n");331			ret = -EFAULT;332			break;333		}334 335		if (!wait_status) {336			dev_err(dev, "timeout waiting for svc layer buffers\n");337			ret = -ETIMEDOUT;338			break;339		}340	}341 342	if (!s10_free_buffers(mgr))343		dev_err(dev, "%s not all buffers were freed\n", __func__);344 345	return ret;346}347 348static int s10_ops_write_complete(struct fpga_manager *mgr,349				  struct fpga_image_info *info)350{351	struct s10_priv *priv = mgr->priv;352	struct device *dev = priv->client.dev;353	unsigned long timeout;354	int ret;355 356	timeout = usecs_to_jiffies(info->config_complete_timeout_us);357 358	do {359		reinit_completion(&priv->status_return_completion);360 361		ret = s10_svc_send_msg(priv, COMMAND_RECONFIG_STATUS, NULL, 0);362		if (ret < 0)363			break;364 365		ret = wait_for_completion_timeout(366			&priv->status_return_completion, timeout);367		if (!ret) {368			dev_err(dev,369				"timeout waiting for RECONFIG_COMPLETED\n");370			ret = -ETIMEDOUT;371			break;372		}373		/* Not error or timeout, so ret is # of jiffies until timeout */374		timeout = ret;375		ret = 0;376 377		if (test_and_clear_bit(SVC_STATUS_COMPLETED, &priv->status))378			break;379 380		if (test_and_clear_bit(SVC_STATUS_ERROR, &priv->status)) {381			dev_err(dev, "ERROR - giving up - SVC_STATUS_ERROR\n");382			ret = -EFAULT;383			break;384		}385	} while (1);386 387	stratix10_svc_done(priv->chan);388 389	return ret;390}391 392static const struct fpga_manager_ops s10_ops = {393	.write_init = s10_ops_write_init,394	.write = s10_ops_write,395	.write_complete = s10_ops_write_complete,396};397 398static int s10_probe(struct platform_device *pdev)399{400	struct device *dev = &pdev->dev;401	struct s10_priv *priv;402	struct fpga_manager *mgr;403	int ret;404 405	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);406	if (!priv)407		return -ENOMEM;408 409	priv->client.dev = dev;410	priv->client.receive_cb = s10_receive_callback;411	priv->client.priv = priv;412 413	priv->chan = stratix10_svc_request_channel_byname(&priv->client,414							  SVC_CLIENT_FPGA);415	if (IS_ERR(priv->chan)) {416		dev_err(dev, "couldn't get service channel (%s)\n",417			SVC_CLIENT_FPGA);418		return PTR_ERR(priv->chan);419	}420 421	init_completion(&priv->status_return_completion);422 423	mgr = fpga_mgr_register(dev, "Stratix10 SOC FPGA Manager",424				&s10_ops, priv);425	if (IS_ERR(mgr)) {426		dev_err(dev, "unable to register FPGA manager\n");427		ret = PTR_ERR(mgr);428		goto probe_err;429	}430 431	platform_set_drvdata(pdev, mgr);432	return 0;433 434probe_err:435	stratix10_svc_free_channel(priv->chan);436	return ret;437}438 439static void s10_remove(struct platform_device *pdev)440{441	struct fpga_manager *mgr = platform_get_drvdata(pdev);442	struct s10_priv *priv = mgr->priv;443 444	fpga_mgr_unregister(mgr);445	stratix10_svc_free_channel(priv->chan);446}447 448static const struct of_device_id s10_of_match[] = {449	{.compatible = "intel,stratix10-soc-fpga-mgr"},450	{.compatible = "intel,agilex-soc-fpga-mgr"},451	{},452};453 454MODULE_DEVICE_TABLE(of, s10_of_match);455 456static struct platform_driver s10_driver = {457	.probe = s10_probe,458	.remove_new = s10_remove,459	.driver = {460		.name	= "Stratix10 SoC FPGA manager",461		.of_match_table = of_match_ptr(s10_of_match),462	},463};464 465static int __init s10_init(void)466{467	struct device_node *fw_np;468	struct device_node *np;469	int ret;470 471	fw_np = of_find_node_by_name(NULL, "svc");472	if (!fw_np)473		return -ENODEV;474 475	of_node_get(fw_np);476	np = of_find_matching_node(fw_np, s10_of_match);477	if (!np) {478		of_node_put(fw_np);479		return -ENODEV;480	}481 482	of_node_put(np);483	ret = of_platform_populate(fw_np, s10_of_match, NULL, NULL);484	of_node_put(fw_np);485	if (ret)486		return ret;487 488	return platform_driver_register(&s10_driver);489}490 491static void __exit s10_exit(void)492{493	return platform_driver_unregister(&s10_driver);494}495 496module_init(s10_init);497module_exit(s10_exit);498 499MODULE_AUTHOR("Alan Tull <atull@kernel.org>");500MODULE_DESCRIPTION("Intel Stratix 10 SOC FPGA Manager");501MODULE_LICENSE("GPL v2");502