fpga-mgr.c 19 KB
Newer Older
Alan Tull's avatar
Alan Tull committed
1
// SPDX-License-Identifier: GPL-2.0
Alan Tull's avatar
Alan Tull committed
2 3 4 5
/*
 * FPGA Manager Core
 *
 *  Copyright (C) 2013-2015 Altera Corporation
6
 *  Copyright (C) 2017 Intel Corporation
Alan Tull's avatar
Alan Tull committed
7 8 9 10 11 12 13 14 15 16 17
 *
 * With code from the mailing list:
 * Copyright (C) 2013 Xilinx, Inc.
 */
#include <linux/firmware.h>
#include <linux/fpga/fpga-mgr.h>
#include <linux/idr.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/mutex.h>
#include <linux/slab.h>
18 19
#include <linux/scatterlist.h>
#include <linux/highmem.h>
Alan Tull's avatar
Alan Tull committed
20 21 22 23

static DEFINE_IDA(fpga_mgr_ida);
static struct class *fpga_mgr_class;

Alan Tull's avatar
Alan Tull committed
24 25 26 27 28 29
/**
 * fpga_image_info_alloc - Allocate a FPGA image info struct
 * @dev: owning device
 *
 * Return: struct fpga_image_info or NULL
 */
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
struct fpga_image_info *fpga_image_info_alloc(struct device *dev)
{
	struct fpga_image_info *info;

	get_device(dev);

	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
	if (!info) {
		put_device(dev);
		return NULL;
	}

	info->dev = dev;

	return info;
}
EXPORT_SYMBOL_GPL(fpga_image_info_alloc);

Alan Tull's avatar
Alan Tull committed
48 49 50 51
/**
 * fpga_image_info_free - Free a FPGA image info struct
 * @info: FPGA image info struct to free
 */
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
void fpga_image_info_free(struct fpga_image_info *info)
{
	struct device *dev;

	if (!info)
		return;

	dev = info->dev;
	if (info->firmware_name)
		devm_kfree(dev, info->firmware_name);

	devm_kfree(dev, info);
	put_device(dev);
}
EXPORT_SYMBOL_GPL(fpga_image_info_free);

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
/*
 * Call the low level driver's write_init function.  This will do the
 * device-specific things to get the FPGA into the state where it is ready to
 * receive an FPGA image. The low level driver only gets to see the first
 * initial_header_size bytes in the buffer.
 */
static int fpga_mgr_write_init_buf(struct fpga_manager *mgr,
				   struct fpga_image_info *info,
				   const char *buf, size_t count)
{
	int ret;

	mgr->state = FPGA_MGR_STATE_WRITE_INIT;
	if (!mgr->mops->initial_header_size)
		ret = mgr->mops->write_init(mgr, info, NULL, 0);
	else
		ret = mgr->mops->write_init(
		    mgr, info, buf, min(mgr->mops->initial_header_size, count));

	if (ret) {
		dev_err(&mgr->dev, "Error preparing FPGA for writing\n");
		mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
		return ret;
	}

	return 0;
}

static int fpga_mgr_write_init_sg(struct fpga_manager *mgr,
				  struct fpga_image_info *info,
				  struct sg_table *sgt)
{
	struct sg_mapping_iter miter;
	size_t len;
	char *buf;
	int ret;

	if (!mgr->mops->initial_header_size)
		return fpga_mgr_write_init_buf(mgr, info, NULL, 0);

	/*
	 * First try to use miter to map the first fragment to access the
	 * header, this is the typical path.
	 */
	sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
	if (sg_miter_next(&miter) &&
	    miter.length >= mgr->mops->initial_header_size) {
		ret = fpga_mgr_write_init_buf(mgr, info, miter.addr,
					      miter.length);
		sg_miter_stop(&miter);
		return ret;
	}
	sg_miter_stop(&miter);

	/* Otherwise copy the fragments into temporary memory. */
	buf = kmalloc(mgr->mops->initial_header_size, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	len = sg_copy_to_buffer(sgt->sgl, sgt->nents, buf,
				mgr->mops->initial_header_size);
	ret = fpga_mgr_write_init_buf(mgr, info, buf, len);

	kfree(buf);

	return ret;
}

/*
 * After all the FPGA image has been written, do the device specific steps to
 * finish and set the FPGA into operating mode.
 */
static int fpga_mgr_write_complete(struct fpga_manager *mgr,
				   struct fpga_image_info *info)
{
	int ret;

	mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
	ret = mgr->mops->write_complete(mgr, info);
	if (ret) {
		dev_err(&mgr->dev, "Error after writing image data to FPGA\n");
		mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
		return ret;
	}
	mgr->state = FPGA_MGR_STATE_OPERATING;

	return 0;
}

Alan Tull's avatar
Alan Tull committed
157
/**
158
 * fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list
Alan Tull's avatar
Alan Tull committed
159
 * @mgr:	fpga manager
160
 * @info:	fpga image specific information
161
 * @sgt:	scatterlist table
Alan Tull's avatar
Alan Tull committed
162 163 164
 *
 * Step the low level fpga manager through the device-specific steps of getting
 * an FPGA ready to be configured, writing the image to it, then doing whatever
165
 * post-configuration steps necessary.  This code assumes the caller got the
166 167
 * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is
 * not an error code.
Alan Tull's avatar
Alan Tull committed
168
 *
169 170 171
 * This is the preferred entry point for FPGA programming, it does not require
 * any contiguous kernel memory.
 *
Alan Tull's avatar
Alan Tull committed
172 173
 * Return: 0 on success, negative error code otherwise.
 */
174 175 176
static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr,
				struct fpga_image_info *info,
				struct sg_table *sgt)
Alan Tull's avatar
Alan Tull committed
177 178 179
{
	int ret;

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
	ret = fpga_mgr_write_init_sg(mgr, info, sgt);
	if (ret)
		return ret;

	/* Write the FPGA image to the FPGA. */
	mgr->state = FPGA_MGR_STATE_WRITE;
	if (mgr->mops->write_sg) {
		ret = mgr->mops->write_sg(mgr, sgt);
	} else {
		struct sg_mapping_iter miter;

		sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
		while (sg_miter_next(&miter)) {
			ret = mgr->mops->write(mgr, miter.addr, miter.length);
			if (ret)
				break;
		}
		sg_miter_stop(&miter);
	}

Alan Tull's avatar
Alan Tull committed
200
	if (ret) {
201 202
		dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
		mgr->state = FPGA_MGR_STATE_WRITE_ERR;
Alan Tull's avatar
Alan Tull committed
203 204 205
		return ret;
	}

206 207 208 209 210 211 212 213 214 215 216 217 218
	return fpga_mgr_write_complete(mgr, info);
}

static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr,
				    struct fpga_image_info *info,
				    const char *buf, size_t count)
{
	int ret;

	ret = fpga_mgr_write_init_buf(mgr, info, buf, count);
	if (ret)
		return ret;

Alan Tull's avatar
Alan Tull committed
219 220 221 222 223 224
	/*
	 * Write the FPGA image to the FPGA.
	 */
	mgr->state = FPGA_MGR_STATE_WRITE;
	ret = mgr->mops->write(mgr, buf, count);
	if (ret) {
225
		dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
Alan Tull's avatar
Alan Tull committed
226 227 228 229
		mgr->state = FPGA_MGR_STATE_WRITE_ERR;
		return ret;
	}

230 231 232 233 234 235
	return fpga_mgr_write_complete(mgr, info);
}

/**
 * fpga_mgr_buf_load - load fpga from image in buffer
 * @mgr:	fpga manager
Alan Tull's avatar
Alan Tull committed
236
 * @info:	fpga image info
237 238 239 240 241 242 243 244 245 246
 * @buf:	buffer contain fpga image
 * @count:	byte count of buf
 *
 * Step the low level fpga manager through the device-specific steps of getting
 * an FPGA ready to be configured, writing the image to it, then doing whatever
 * post-configuration steps necessary.  This code assumes the caller got the
 * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code.
 *
 * Return: 0 on success, negative error code otherwise.
 */
247 248 249
static int fpga_mgr_buf_load(struct fpga_manager *mgr,
			     struct fpga_image_info *info,
			     const char *buf, size_t count)
250 251 252 253 254 255 256 257
{
	struct page **pages;
	struct sg_table sgt;
	const void *p;
	int nr_pages;
	int index;
	int rc;

Alan Tull's avatar
Alan Tull committed
258
	/*
259 260 261
	 * This is just a fast path if the caller has already created a
	 * contiguous kernel buffer and the driver doesn't require SG, non-SG
	 * drivers will still work on the slow path.
Alan Tull's avatar
Alan Tull committed
262
	 */
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
	if (mgr->mops->write)
		return fpga_mgr_buf_load_mapped(mgr, info, buf, count);

	/*
	 * Convert the linear kernel pointer into a sg_table of pages for use
	 * by the driver.
	 */
	nr_pages = DIV_ROUND_UP((unsigned long)buf + count, PAGE_SIZE) -
		   (unsigned long)buf / PAGE_SIZE;
	pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
	if (!pages)
		return -ENOMEM;

	p = buf - offset_in_page(buf);
	for (index = 0; index < nr_pages; index++) {
		if (is_vmalloc_addr(p))
			pages[index] = vmalloc_to_page(p);
		else
			pages[index] = kmap_to_page((void *)p);
		if (!pages[index]) {
			kfree(pages);
			return -EFAULT;
		}
		p += PAGE_SIZE;
Alan Tull's avatar
Alan Tull committed
287 288
	}

289 290 291 292 293 294 295 296 297 298 299 300 301 302
	/*
	 * The temporary pages list is used to code share the merging algorithm
	 * in sg_alloc_table_from_pages
	 */
	rc = sg_alloc_table_from_pages(&sgt, pages, index, offset_in_page(buf),
				       count, GFP_KERNEL);
	kfree(pages);
	if (rc)
		return rc;

	rc = fpga_mgr_buf_load_sg(mgr, info, &sgt);
	sg_free_table(&sgt);

	return rc;
Alan Tull's avatar
Alan Tull committed
303 304 305 306 307
}

/**
 * fpga_mgr_firmware_load - request firmware and load to fpga
 * @mgr:	fpga manager
308
 * @info:	fpga image specific information
Alan Tull's avatar
Alan Tull committed
309 310 311 312
 * @image_name:	name of image file on the firmware search path
 *
 * Request an FPGA image using the firmware class, then write out to the FPGA.
 * Update the state before each step to provide info on what step failed if
313
 * there is a failure.  This code assumes the caller got the mgr pointer
314 315
 * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error
 * code.
Alan Tull's avatar
Alan Tull committed
316 317 318
 *
 * Return: 0 on success, negative error code otherwise.
 */
319 320 321
static int fpga_mgr_firmware_load(struct fpga_manager *mgr,
				  struct fpga_image_info *info,
				  const char *image_name)
Alan Tull's avatar
Alan Tull committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
{
	struct device *dev = &mgr->dev;
	const struct firmware *fw;
	int ret;

	dev_info(dev, "writing %s to %s\n", image_name, mgr->name);

	mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;

	ret = request_firmware(&fw, image_name, dev);
	if (ret) {
		mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
		dev_err(dev, "Error requesting firmware %s\n", image_name);
		return ret;
	}

338
	ret = fpga_mgr_buf_load(mgr, info, fw->data, fw->size);
Alan Tull's avatar
Alan Tull committed
339 340 341

	release_firmware(fw);

342
	return ret;
Alan Tull's avatar
Alan Tull committed
343
}
344

Alan Tull's avatar
Alan Tull committed
345 346 347 348 349 350 351 352 353 354
/**
 * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware
 * @mgr:	fpga manager
 * @info:	fpga image information.
 *
 * Load the FPGA from an image which is indicated in @info.  If successful, the
 * FPGA ends up in operating mode.
 *
 * Return: 0 on success, negative error code otherwise.
 */
355 356 357 358 359 360 361 362 363 364 365
int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info)
{
	if (info->sgt)
		return fpga_mgr_buf_load_sg(mgr, info, info->sgt);
	if (info->buf && info->count)
		return fpga_mgr_buf_load(mgr, info, info->buf, info->count);
	if (info->firmware_name)
		return fpga_mgr_firmware_load(mgr, info, info->firmware_name);
	return -EINVAL;
}
EXPORT_SYMBOL_GPL(fpga_mgr_load);
Alan Tull's avatar
Alan Tull committed
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408

static const char * const state_str[] = {
	[FPGA_MGR_STATE_UNKNOWN] =		"unknown",
	[FPGA_MGR_STATE_POWER_OFF] =		"power off",
	[FPGA_MGR_STATE_POWER_UP] =		"power up",
	[FPGA_MGR_STATE_RESET] =		"reset",

	/* requesting FPGA image from firmware */
	[FPGA_MGR_STATE_FIRMWARE_REQ] =		"firmware request",
	[FPGA_MGR_STATE_FIRMWARE_REQ_ERR] =	"firmware request error",

	/* Preparing FPGA to receive image */
	[FPGA_MGR_STATE_WRITE_INIT] =		"write init",
	[FPGA_MGR_STATE_WRITE_INIT_ERR] =	"write init error",

	/* Writing image to FPGA */
	[FPGA_MGR_STATE_WRITE] =		"write",
	[FPGA_MGR_STATE_WRITE_ERR] =		"write error",

	/* Finishing configuration after image has been written */
	[FPGA_MGR_STATE_WRITE_COMPLETE] =	"write complete",
	[FPGA_MGR_STATE_WRITE_COMPLETE_ERR] =	"write complete error",

	/* FPGA reports to be in normal operating mode */
	[FPGA_MGR_STATE_OPERATING] =		"operating",
};

static ssize_t name_show(struct device *dev,
			 struct device_attribute *attr, char *buf)
{
	struct fpga_manager *mgr = to_fpga_manager(dev);

	return sprintf(buf, "%s\n", mgr->name);
}

static ssize_t state_show(struct device *dev,
			  struct device_attribute *attr, char *buf)
{
	struct fpga_manager *mgr = to_fpga_manager(dev);

	return sprintf(buf, "%s\n", state_str[mgr->state]);
}

409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
static ssize_t status_show(struct device *dev,
			   struct device_attribute *attr, char *buf)
{
	struct fpga_manager *mgr = to_fpga_manager(dev);
	u64 status;
	int len = 0;

	if (!mgr->mops->status)
		return -ENOENT;

	status = mgr->mops->status(mgr);

	if (status & FPGA_MGR_STATUS_OPERATION_ERR)
		len += sprintf(buf + len, "reconfig operation error\n");
	if (status & FPGA_MGR_STATUS_CRC_ERR)
		len += sprintf(buf + len, "reconfig CRC error\n");
	if (status & FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR)
		len += sprintf(buf + len, "reconfig incompatible image\n");
	if (status & FPGA_MGR_STATUS_IP_PROTOCOL_ERR)
		len += sprintf(buf + len, "reconfig IP protocol error\n");
	if (status & FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR)
		len += sprintf(buf + len, "reconfig fifo overflow error\n");

	return len;
}

Alan Tull's avatar
Alan Tull committed
435 436
static DEVICE_ATTR_RO(name);
static DEVICE_ATTR_RO(state);
437
static DEVICE_ATTR_RO(status);
Alan Tull's avatar
Alan Tull committed
438 439 440 441

static struct attribute *fpga_mgr_attrs[] = {
	&dev_attr_name.attr,
	&dev_attr_state.attr,
442
	&dev_attr_status.attr,
Alan Tull's avatar
Alan Tull committed
443 444 445 446
	NULL,
};
ATTRIBUTE_GROUPS(fpga_mgr);

447
static struct fpga_manager *__fpga_mgr_get(struct device *dev)
Alan Tull's avatar
Alan Tull committed
448 449 450 451 452
{
	struct fpga_manager *mgr;

	mgr = to_fpga_manager(dev);

453
	if (!try_module_get(dev->parent->driver->owner))
454
		goto err_dev;
455

Alan Tull's avatar
Alan Tull committed
456
	return mgr;
457 458 459

err_dev:
	put_device(dev);
460
	return ERR_PTR(-ENODEV);
Alan Tull's avatar
Alan Tull committed
461
}
462 463 464 465 466 467 468

static int fpga_mgr_dev_match(struct device *dev, const void *data)
{
	return dev->parent == data;
}

/**
Alan Tull's avatar
Alan Tull committed
469
 * fpga_mgr_get - Given a device, get a reference to a fpga mgr.
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
 * @dev:	parent device that fpga mgr was registered with
 *
 * Return: fpga manager struct or IS_ERR() condition containing error code.
 */
struct fpga_manager *fpga_mgr_get(struct device *dev)
{
	struct device *mgr_dev = class_find_device(fpga_mgr_class, NULL, dev,
						   fpga_mgr_dev_match);
	if (!mgr_dev)
		return ERR_PTR(-ENODEV);

	return __fpga_mgr_get(mgr_dev);
}
EXPORT_SYMBOL_GPL(fpga_mgr_get);

/**
Alan Tull's avatar
Alan Tull committed
486
 * of_fpga_mgr_get - Given a device node, get a reference to a fpga mgr.
487
 *
Alan Tull's avatar
Alan Tull committed
488
 * @node:	device node
489 490 491 492 493 494 495
 *
 * Return: fpga manager struct or IS_ERR() condition containing error code.
 */
struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
{
	struct device *dev;

496
	dev = class_find_device_by_of_node(fpga_mgr_class, node);
497 498 499 500 501
	if (!dev)
		return ERR_PTR(-ENODEV);

	return __fpga_mgr_get(dev);
}
Alan Tull's avatar
Alan Tull committed
502 503 504 505 506 507 508 509
EXPORT_SYMBOL_GPL(of_fpga_mgr_get);

/**
 * fpga_mgr_put - release a reference to a fpga manager
 * @mgr:	fpga manager structure
 */
void fpga_mgr_put(struct fpga_manager *mgr)
{
510 511
	module_put(mgr->dev.parent->driver->owner);
	put_device(&mgr->dev);
Alan Tull's avatar
Alan Tull committed
512 513 514
}
EXPORT_SYMBOL_GPL(fpga_mgr_put);

515 516 517 518 519
/**
 * fpga_mgr_lock - Lock FPGA manager for exclusive use
 * @mgr:	fpga manager
 *
 * Given a pointer to FPGA Manager (from fpga_mgr_get() or
Alan Tull's avatar
Alan Tull committed
520 521 522 523
 * of_fpga_mgr_put()) attempt to get the mutex. The user should call
 * fpga_mgr_lock() and verify that it returns 0 before attempting to
 * program the FPGA.  Likewise, the user should call fpga_mgr_unlock
 * when done programming the FPGA.
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
 *
 * Return: 0 for success or -EBUSY
 */
int fpga_mgr_lock(struct fpga_manager *mgr)
{
	if (!mutex_trylock(&mgr->ref_mutex)) {
		dev_err(&mgr->dev, "FPGA manager is in use.\n");
		return -EBUSY;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(fpga_mgr_lock);

/**
Alan Tull's avatar
Alan Tull committed
539
 * fpga_mgr_unlock - Unlock FPGA manager after done programming
540 541 542 543 544 545 546 547
 * @mgr:	fpga manager
 */
void fpga_mgr_unlock(struct fpga_manager *mgr)
{
	mutex_unlock(&mgr->ref_mutex);
}
EXPORT_SYMBOL_GPL(fpga_mgr_unlock);

Alan Tull's avatar
Alan Tull committed
548
/**
549
 * fpga_mgr_create - create and initialize a FPGA manager struct
Alan Tull's avatar
Alan Tull committed
550 551 552 553 554
 * @dev:	fpga manager device from pdev
 * @name:	fpga manager name
 * @mops:	pointer to structure of fpga manager ops
 * @priv:	fpga manager private data
 *
555 556 557
 * The caller of this function is responsible for freeing the struct with
 * fpga_mgr_free().  Using devm_fpga_mgr_create() instead is recommended.
 *
558
 * Return: pointer to struct fpga_manager or NULL
Alan Tull's avatar
Alan Tull committed
559
 */
560 561 562
struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name,
				     const struct fpga_manager_ops *mops,
				     void *priv)
Alan Tull's avatar
Alan Tull committed
563 564 565 566
{
	struct fpga_manager *mgr;
	int id, ret;

567 568 569
	if (!mops || !mops->write_complete || !mops->state ||
	    !mops->write_init || (!mops->write && !mops->write_sg) ||
	    (mops->write && mops->write_sg)) {
Alan Tull's avatar
Alan Tull committed
570
		dev_err(dev, "Attempt to register without fpga_manager_ops\n");
571
		return NULL;
Alan Tull's avatar
Alan Tull committed
572 573 574 575
	}

	if (!name || !strlen(name)) {
		dev_err(dev, "Attempt to register with no name!\n");
576
		return NULL;
Alan Tull's avatar
Alan Tull committed
577 578 579 580
	}

	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
	if (!mgr)
581
		return NULL;
Alan Tull's avatar
Alan Tull committed
582 583

	id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
Tom Rix's avatar
Tom Rix committed
584
	if (id < 0)
Alan Tull's avatar
Alan Tull committed
585 586 587 588 589 590 591 592 593 594
		goto error_kfree;

	mutex_init(&mgr->ref_mutex);

	mgr->name = name;
	mgr->mops = mops;
	mgr->priv = priv;

	device_initialize(&mgr->dev);
	mgr->dev.class = fpga_mgr_class;
Alan Tull's avatar
Alan Tull committed
595
	mgr->dev.groups = mops->groups;
Alan Tull's avatar
Alan Tull committed
596 597 598 599
	mgr->dev.parent = dev;
	mgr->dev.of_node = dev->of_node;
	mgr->dev.id = id;

Alan Tull's avatar
Alan Tull committed
600 601 602
	ret = dev_set_name(&mgr->dev, "fpga%d", id);
	if (ret)
		goto error_device;
Alan Tull's avatar
Alan Tull committed
603

604 605 606 607 608 609 610 611 612 613 614 615
	return mgr;

error_device:
	ida_simple_remove(&fpga_mgr_ida, id);
error_kfree:
	kfree(mgr);

	return NULL;
}
EXPORT_SYMBOL_GPL(fpga_mgr_create);

/**
616 617
 * fpga_mgr_free - free a FPGA manager created with fpga_mgr_create()
 * @mgr:	fpga manager struct
618 619 620 621 622 623 624 625
 */
void fpga_mgr_free(struct fpga_manager *mgr)
{
	ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
	kfree(mgr);
}
EXPORT_SYMBOL_GPL(fpga_mgr_free);

626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
static void devm_fpga_mgr_release(struct device *dev, void *res)
{
	struct fpga_manager *mgr = *(struct fpga_manager **)res;

	fpga_mgr_free(mgr);
}

/**
 * devm_fpga_mgr_create - create and initialize a managed FPGA manager struct
 * @dev:	fpga manager device from pdev
 * @name:	fpga manager name
 * @mops:	pointer to structure of fpga manager ops
 * @priv:	fpga manager private data
 *
 * This function is intended for use in a FPGA manager driver's probe function.
 * After the manager driver creates the manager struct with
 * devm_fpga_mgr_create(), it should register it with fpga_mgr_register().  The
 * manager driver's remove function should call fpga_mgr_unregister().  The
 * manager struct allocated with this function will be freed automatically on
 * driver detach.  This includes the case of a probe function returning error
 * before calling fpga_mgr_register(), the struct will still get cleaned up.
 *
 * Return: pointer to struct fpga_manager or NULL
 */
struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name,
					  const struct fpga_manager_ops *mops,
					  void *priv)
{
	struct fpga_manager **ptr, *mgr;

	ptr = devres_alloc(devm_fpga_mgr_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return NULL;

	mgr = fpga_mgr_create(dev, name, mops, priv);
	if (!mgr) {
		devres_free(ptr);
	} else {
		*ptr = mgr;
		devres_add(dev, ptr);
	}

	return mgr;
}
EXPORT_SYMBOL_GPL(devm_fpga_mgr_create);

672 673
/**
 * fpga_mgr_register - register a FPGA manager
674
 * @mgr: fpga manager struct
675 676 677 678 679 680 681 682 683 684 685 686 687 688
 *
 * Return: 0 on success, negative error code otherwise.
 */
int fpga_mgr_register(struct fpga_manager *mgr)
{
	int ret;

	/*
	 * Initialize framework state by requesting low level driver read state
	 * from device.  FPGA may be in reset mode or may have been programmed
	 * by bootloader or EEPROM.
	 */
	mgr->state = mgr->mops->state(mgr);

Alan Tull's avatar
Alan Tull committed
689 690 691 692 693 694 695 696 697
	ret = device_add(&mgr->dev);
	if (ret)
		goto error_device;

	dev_info(&mgr->dev, "%s registered\n", mgr->name);

	return 0;

error_device:
698
	ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
Alan Tull's avatar
Alan Tull committed
699 700 701 702 703 704

	return ret;
}
EXPORT_SYMBOL_GPL(fpga_mgr_register);

/**
705 706 707 708
 * fpga_mgr_unregister - unregister a FPGA manager
 * @mgr: fpga manager struct
 *
 * This function is intended for use in a FPGA manager driver's remove function.
Alan Tull's avatar
Alan Tull committed
709
 */
710
void fpga_mgr_unregister(struct fpga_manager *mgr)
Alan Tull's avatar
Alan Tull committed
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
{
	dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name);

	/*
	 * If the low level driver provides a method for putting fpga into
	 * a desired state upon unregister, do it.
	 */
	if (mgr->mops->fpga_remove)
		mgr->mops->fpga_remove(mgr);

	device_unregister(&mgr->dev);
}
EXPORT_SYMBOL_GPL(fpga_mgr_unregister);

static void fpga_mgr_dev_release(struct device *dev)
{
}

static int __init fpga_mgr_class_init(void)
{
	pr_info("FPGA manager framework\n");

	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
	if (IS_ERR(fpga_mgr_class))
		return PTR_ERR(fpga_mgr_class);

	fpga_mgr_class->dev_groups = fpga_mgr_groups;
	fpga_mgr_class->dev_release = fpga_mgr_dev_release;

	return 0;
}

static void __exit fpga_mgr_class_exit(void)
{
	class_destroy(fpga_mgr_class);
	ida_destroy(&fpga_mgr_ida);
}

749
MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
Alan Tull's avatar
Alan Tull committed
750 751 752 753 754
MODULE_DESCRIPTION("FPGA manager framework");
MODULE_LICENSE("GPL v2");

subsys_initcall(fpga_mgr_class_init);
module_exit(fpga_mgr_class_exit);