Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  1/*
  2 * Copyright (C) 2012 CERN (www.cern.ch)
  3 * Author: Alessandro Rubini <rubini@gnudd.com>
  4 *
  5 * Released according to the GNU GPL, version 2 or any later version.
  6 *
  7 * This work is part of the White Rabbit project, a research effort led
  8 * by CERN, the European Institute for Nuclear Research.
  9 */
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/slab.h>
 13#include <linux/init.h>
 14#include <linux/device.h>
 15#include <linux/fmc.h>
 16#include <linux/fmc-sdb.h>
 17
 18#include "fmc-private.h"
 19
 20static int fmc_check_version(unsigned long version, const char *name)
 21{
 22	if (__FMC_MAJOR(version) != FMC_MAJOR) {
 23		pr_err("%s: \"%s\" has wrong major (has %li, expected %i)\n",
 24		       __func__, name, __FMC_MAJOR(version), FMC_MAJOR);
 25		return -EINVAL;
 26	}
 27
 28	if (__FMC_MINOR(version) != FMC_MINOR)
 29		pr_info("%s: \"%s\" has wrong minor (has %li, expected %i)\n",
 30		       __func__, name, __FMC_MINOR(version), FMC_MINOR);
 31	return 0;
 32}
 33
 34static int fmc_uevent(struct device *dev, struct kobj_uevent_env *env)
 35{
 36	/* struct fmc_device *fdev = to_fmc_device(dev); */
 37
 38	/* FIXME: The MODALIAS */
 39	add_uevent_var(env, "MODALIAS=%s", "fmc");
 40	return 0;
 41}
 42
 43static int fmc_probe(struct device *dev)
 44{
 45	struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
 46	struct fmc_device *fdev = to_fmc_device(dev);
 47
 48	return fdrv->probe(fdev);
 49}
 50
 51static int fmc_remove(struct device *dev)
 52{
 53	struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
 54	struct fmc_device *fdev = to_fmc_device(dev);
 55
 56	return fdrv->remove(fdev);
 57}
 58
 59static void fmc_shutdown(struct device *dev)
 60{
 61	/* not implemented but mandatory */
 62}
 63
 64static struct bus_type fmc_bus_type = {
 65	.name = "fmc",
 66	.match = fmc_match,
 67	.uevent = fmc_uevent,
 68	.probe = fmc_probe,
 69	.remove = fmc_remove,
 70	.shutdown = fmc_shutdown,
 71};
 72
 73static void fmc_release(struct device *dev)
 74{
 75	struct fmc_device *fmc = container_of(dev, struct fmc_device, dev);
 76
 77	kfree(fmc);
 78}
 79
 80/*
 81 * The eeprom is exported in sysfs, through a binary attribute
 82 */
 83
 84static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj,
 85			   struct bin_attribute *bin_attr,
 86			   char *buf, loff_t off, size_t count)
 87{
 88	struct device *dev;
 89	struct fmc_device *fmc;
 90	int eelen;
 91
 92	dev = container_of(kobj, struct device, kobj);
 93	fmc = container_of(dev, struct fmc_device, dev);
 94	eelen = fmc->eeprom_len;
 95	if (off > eelen)
 96		return -ESPIPE;
 97	if (off == eelen)
 98		return 0; /* EOF */
 99	if (off + count > eelen)
100		count = eelen - off;
101	memcpy(buf, fmc->eeprom + off, count);
102	return count;
103}
104
105static ssize_t fmc_write_eeprom(struct file *file, struct kobject *kobj,
106				struct bin_attribute *bin_attr,
107				char *buf, loff_t off, size_t count)
108{
109	struct device *dev;
110	struct fmc_device *fmc;
111
112	dev = container_of(kobj, struct device, kobj);
113	fmc = container_of(dev, struct fmc_device, dev);
114	return fmc->op->write_ee(fmc, off, buf, count);
115}
116
117static struct bin_attribute fmc_eeprom_attr = {
118	.attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, },
119	.size = 8192, /* more or less standard */
120	.read = fmc_read_eeprom,
121	.write = fmc_write_eeprom,
122};
123
124int fmc_irq_request(struct fmc_device *fmc, irq_handler_t h,
125		    char *name, int flags)
126{
127	if (fmc->op->irq_request)
128		return fmc->op->irq_request(fmc, h, name, flags);
129	return -EPERM;
130}
131EXPORT_SYMBOL(fmc_irq_request);
132
133void fmc_irq_free(struct fmc_device *fmc)
134{
135	if (fmc->op->irq_free)
136		fmc->op->irq_free(fmc);
137}
138EXPORT_SYMBOL(fmc_irq_free);
139
140void fmc_irq_ack(struct fmc_device *fmc)
141{
142	if (likely(fmc->op->irq_ack))
143		fmc->op->irq_ack(fmc);
144}
145EXPORT_SYMBOL(fmc_irq_ack);
146
147int fmc_validate(struct fmc_device *fmc, struct fmc_driver *drv)
148{
149	if (fmc->op->validate)
150		return fmc->op->validate(fmc, drv);
151	return -EPERM;
152}
153EXPORT_SYMBOL(fmc_validate);
154
155int fmc_gpio_config(struct fmc_device *fmc, struct fmc_gpio *gpio, int ngpio)
156{
157	if (fmc->op->gpio_config)
158		return fmc->op->gpio_config(fmc, gpio, ngpio);
159	return -EPERM;
160}
161EXPORT_SYMBOL(fmc_gpio_config);
162
163int fmc_read_ee(struct fmc_device *fmc, int pos, void *d, int l)
164{
165	if (fmc->op->read_ee)
166		return fmc->op->read_ee(fmc, pos, d, l);
167	return -EPERM;
168}
169EXPORT_SYMBOL(fmc_read_ee);
170
171int fmc_write_ee(struct fmc_device *fmc, int pos, const void *d, int l)
172{
173	if (fmc->op->write_ee)
174		return fmc->op->write_ee(fmc, pos, d, l);
175	return -EPERM;
176}
177EXPORT_SYMBOL(fmc_write_ee);
178
179/*
180 * Functions for client modules follow
181 */
182
183int fmc_driver_register(struct fmc_driver *drv)
184{
185	if (fmc_check_version(drv->version, drv->driver.name))
186		return -EINVAL;
187	drv->driver.bus = &fmc_bus_type;
188	return driver_register(&drv->driver);
189}
190EXPORT_SYMBOL(fmc_driver_register);
191
192void fmc_driver_unregister(struct fmc_driver *drv)
193{
194	driver_unregister(&drv->driver);
195}
196EXPORT_SYMBOL(fmc_driver_unregister);
197
198/*
199 * When a device set is registered, all eeproms must be read
200 * and all FRUs must be parsed
201 */
202int fmc_device_register_n_gw(struct fmc_device **devs, int n,
203			  struct fmc_gateware *gw)
204{
205	struct fmc_device *fmc, **devarray;
206	uint32_t device_id;
207	int i, ret = 0;
208
209	if (n < 1)
210		return 0;
211
212	/* Check the version of the first data structure (function prints) */
213	if (fmc_check_version(devs[0]->version, devs[0]->carrier_name))
214		return -EINVAL;
215
216	devarray = kmemdup(devs, n * sizeof(*devs), GFP_KERNEL);
217	if (!devarray)
218		return -ENOMEM;
219
220	/* Make all other checks before continuing, for all devices */
221	for (i = 0; i < n; i++) {
222		fmc = devarray[i];
223		if (!fmc->hwdev) {
224			pr_err("%s: device nr. %i has no hwdev pointer\n",
225			       __func__, i);
226			ret = -EINVAL;
227			break;
228		}
229		if (fmc->flags & FMC_DEVICE_NO_MEZZANINE) {
230			dev_info(fmc->hwdev, "absent mezzanine in slot %d\n",
231				 fmc->slot_id);
232			continue;
233		}
234		if (!fmc->eeprom) {
235			dev_err(fmc->hwdev, "no eeprom provided for slot %i\n",
236				fmc->slot_id);
237			ret = -EINVAL;
238		}
239		if (!fmc->eeprom_addr) {
240			dev_err(fmc->hwdev, "no eeprom_addr for slot %i\n",
241				fmc->slot_id);
242			ret = -EINVAL;
243		}
244		if (!fmc->carrier_name || !fmc->carrier_data ||
245		    !fmc->device_id) {
246			dev_err(fmc->hwdev,
247				"device nr %i: carrier name, "
248				"data or dev_id not set\n", i);
249			ret = -EINVAL;
250		}
251		if (ret)
252			break;
253
254	}
255	if (ret) {
256		kfree(devarray);
257		return ret;
258	}
259
260	/* Validation is ok. Now init and register the devices */
261	for (i = 0; i < n; i++) {
262		fmc = devarray[i];
263
264		fmc->nr_slots = n; /* each slot must know how many are there */
265		fmc->devarray = devarray;
266
267		device_initialize(&fmc->dev);
268		fmc->dev.release = fmc_release;
269		fmc->dev.parent = fmc->hwdev;
270
271		/* Fill the identification stuff (may fail) */
272		fmc_fill_id_info(fmc);
273
274		fmc->dev.bus = &fmc_bus_type;
275
276		/* Name from mezzanine info or carrier info. Or 0,1,2.. */
277		device_id = fmc->device_id;
278		if (!fmc->mezzanine_name)
279			dev_set_name(&fmc->dev, "fmc-%04x", device_id);
280		else
281			dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name,
282				     device_id);
283
284		if (gw) {
285			/*
286			 * The carrier already know the bitstream to load
287			 * for this set of FMC mezzanines.
288			 */
289			ret = fmc->op->reprogram_raw(fmc, NULL,
290						     gw->bitstream, gw->len);
291			if (ret) {
292				dev_warn(fmc->hwdev,
293					 "Invalid gateware for FMC mezzanine\n");
294				goto out;
295			}
296		}
297
298		ret = device_add(&fmc->dev);
299		if (ret < 0) {
300			dev_err(fmc->hwdev, "Slot %i: Failed in registering "
301				"\"%s\"\n", fmc->slot_id, fmc->dev.kobj.name);
302			goto out;
303		}
304		ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr);
305		if (ret < 0) {
306			dev_err(&fmc->dev, "Failed in registering eeprom\n");
307			goto out1;
308		}
309		/* This device went well, give information to the user */
310		fmc_dump_eeprom(fmc);
311		fmc_debug_init(fmc);
312	}
313	return 0;
314
315out1:
316	device_del(&fmc->dev);
317out:
318	kfree(devarray);
319	for (i--; i >= 0; i--) {
320		fmc_debug_exit(devs[i]);
321		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
322		device_del(&devs[i]->dev);
323		fmc_free_id_info(devs[i]);
324		put_device(&devs[i]->dev);
325	}
326	return ret;
327
328}
329EXPORT_SYMBOL(fmc_device_register_n_gw);
330
331int fmc_device_register_n(struct fmc_device **devs, int n)
332{
333	return fmc_device_register_n_gw(devs, n, NULL);
334}
335EXPORT_SYMBOL(fmc_device_register_n);
336
337int fmc_device_register_gw(struct fmc_device *fmc, struct fmc_gateware *gw)
338{
339	return fmc_device_register_n_gw(&fmc, 1, gw);
340}
341EXPORT_SYMBOL(fmc_device_register_gw);
342
343int fmc_device_register(struct fmc_device *fmc)
344{
345	return fmc_device_register_n(&fmc, 1);
346}
347EXPORT_SYMBOL(fmc_device_register);
348
349void fmc_device_unregister_n(struct fmc_device **devs, int n)
350{
351	int i;
352
353	if (n < 1)
354		return;
355
356	/* Free devarray first, not used by the later loop */
357	kfree(devs[0]->devarray);
358
359	for (i = 0; i < n; i++) {
360		fmc_debug_exit(devs[i]);
361		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
362		device_del(&devs[i]->dev);
363		fmc_free_id_info(devs[i]);
364		put_device(&devs[i]->dev);
365	}
366}
367EXPORT_SYMBOL(fmc_device_unregister_n);
368
369void fmc_device_unregister(struct fmc_device *fmc)
370{
371	fmc_device_unregister_n(&fmc, 1);
372}
373EXPORT_SYMBOL(fmc_device_unregister);
374
375/* Init and exit are trivial */
376static int fmc_init(void)
377{
378	return bus_register(&fmc_bus_type);
379}
380
381static void fmc_exit(void)
382{
383	bus_unregister(&fmc_bus_type);
384}
385
386module_init(fmc_init);
387module_exit(fmc_exit);
388
389MODULE_LICENSE("GPL");