Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.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
 17static int fmc_check_version(unsigned long version, const char *name)
 18{
 19	if (__FMC_MAJOR(version) != FMC_MAJOR) {
 20		pr_err("%s: \"%s\" has wrong major (has %li, expected %i)\n",
 21		       __func__, name, __FMC_MAJOR(version), FMC_MAJOR);
 22		return -EINVAL;
 23	}
 24
 25	if (__FMC_MINOR(version) != FMC_MINOR)
 26		pr_info("%s: \"%s\" has wrong minor (has %li, expected %i)\n",
 27		       __func__, name, __FMC_MINOR(version), FMC_MINOR);
 28	return 0;
 29}
 30
 31static int fmc_uevent(struct device *dev, struct kobj_uevent_env *env)
 32{
 33	/* struct fmc_device *fdev = to_fmc_device(dev); */
 34
 35	/* FIXME: The MODALIAS */
 36	add_uevent_var(env, "MODALIAS=%s", "fmc");
 37	return 0;
 38}
 39
 40static int fmc_probe(struct device *dev)
 41{
 42	struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
 43	struct fmc_device *fdev = to_fmc_device(dev);
 44
 45	return fdrv->probe(fdev);
 46}
 47
 48static int fmc_remove(struct device *dev)
 49{
 50	struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
 51	struct fmc_device *fdev = to_fmc_device(dev);
 52
 53	return fdrv->remove(fdev);
 54}
 55
 56static void fmc_shutdown(struct device *dev)
 57{
 58	/* not implemented but mandatory */
 59}
 60
 61static struct bus_type fmc_bus_type = {
 62	.name = "fmc",
 63	.match = fmc_match,
 64	.uevent = fmc_uevent,
 65	.probe = fmc_probe,
 66	.remove = fmc_remove,
 67	.shutdown = fmc_shutdown,
 68};
 69
 70static void fmc_release(struct device *dev)
 71{
 72	struct fmc_device *fmc = container_of(dev, struct fmc_device, dev);
 73
 74	kfree(fmc);
 75}
 76
 77/*
 78 * The eeprom is exported in sysfs, through a binary attribute
 79 */
 80
 81static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj,
 82			   struct bin_attribute *bin_attr,
 83			   char *buf, loff_t off, size_t count)
 84{
 85	struct device *dev;
 86	struct fmc_device *fmc;
 87	int eelen;
 88
 89	dev = container_of(kobj, struct device, kobj);
 90	fmc = container_of(dev, struct fmc_device, dev);
 91	eelen = fmc->eeprom_len;
 92	if (off > eelen)
 93		return -ESPIPE;
 94	if (off == eelen)
 95		return 0; /* EOF */
 96	if (off + count > eelen)
 97		count = eelen - off;
 98	memcpy(buf, fmc->eeprom + off, count);
 99	return count;
100}
101
102static ssize_t fmc_write_eeprom(struct file *file, struct kobject *kobj,
103				struct bin_attribute *bin_attr,
104				char *buf, loff_t off, size_t count)
105{
106	struct device *dev;
107	struct fmc_device *fmc;
108
109	dev = container_of(kobj, struct device, kobj);
110	fmc = container_of(dev, struct fmc_device, dev);
111	return fmc->op->write_ee(fmc, off, buf, count);
112}
113
114static struct bin_attribute fmc_eeprom_attr = {
115	.attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, },
116	.size = 8192, /* more or less standard */
117	.read = fmc_read_eeprom,
118	.write = fmc_write_eeprom,
119};
120
121/*
122 * Functions for client modules follow
123 */
124
125int fmc_driver_register(struct fmc_driver *drv)
126{
127	if (fmc_check_version(drv->version, drv->driver.name))
128		return -EINVAL;
129	drv->driver.bus = &fmc_bus_type;
130	return driver_register(&drv->driver);
131}
132EXPORT_SYMBOL(fmc_driver_register);
133
134void fmc_driver_unregister(struct fmc_driver *drv)
135{
136	driver_unregister(&drv->driver);
137}
138EXPORT_SYMBOL(fmc_driver_unregister);
139
140/*
141 * When a device set is registered, all eeproms must be read
142 * and all FRUs must be parsed
143 */
144int fmc_device_register_n(struct fmc_device **devs, int n)
145{
146	struct fmc_device *fmc, **devarray;
147	uint32_t device_id;
148	int i, ret = 0;
149
150	if (n < 1)
151		return 0;
152
153	/* Check the version of the first data structure (function prints) */
154	if (fmc_check_version(devs[0]->version, devs[0]->carrier_name))
155		return -EINVAL;
156
157	devarray = kmemdup(devs, n * sizeof(*devs), GFP_KERNEL);
158	if (!devarray)
159		return -ENOMEM;
160
161	/* Make all other checks before continuing, for all devices */
162	for (i = 0; i < n; i++) {
163		fmc = devarray[i];
164		if (!fmc->hwdev) {
165			pr_err("%s: device nr. %i has no hwdev pointer\n",
166			       __func__, i);
167			ret = -EINVAL;
168			break;
169		}
170		if (fmc->flags & FMC_DEVICE_NO_MEZZANINE) {
171			dev_info(fmc->hwdev, "absent mezzanine in slot %d\n",
172				 fmc->slot_id);
173			continue;
174		}
175		if (!fmc->eeprom) {
176			dev_err(fmc->hwdev, "no eeprom provided for slot %i\n",
177				fmc->slot_id);
178			ret = -EINVAL;
179		}
180		if (!fmc->eeprom_addr) {
181			dev_err(fmc->hwdev, "no eeprom_addr for slot %i\n",
182				fmc->slot_id);
183			ret = -EINVAL;
184		}
185		if (!fmc->carrier_name || !fmc->carrier_data ||
186		    !fmc->device_id) {
187			dev_err(fmc->hwdev,
188				"deivce nr %i: carrier name, "
189				"data or dev_id not set\n", i);
190			ret = -EINVAL;
191		}
192		if (ret)
193			break;
194
195	}
196	if (ret) {
197		kfree(devarray);
198		return ret;
199	}
200
201	/* Validation is ok. Now init and register the devices */
202	for (i = 0; i < n; i++) {
203		fmc = devarray[i];
204
205		fmc->nr_slots = n; /* each slot must know how many are there */
206		fmc->devarray = devarray;
207
208		device_initialize(&fmc->dev);
209		fmc->dev.release = fmc_release;
210		fmc->dev.parent = fmc->hwdev;
211
212		/* Fill the identification stuff (may fail) */
213		fmc_fill_id_info(fmc);
214
215		fmc->dev.bus = &fmc_bus_type;
216
217		/* Name from mezzanine info or carrier info. Or 0,1,2.. */
218		device_id = fmc->device_id;
219		if (!fmc->mezzanine_name)
220			dev_set_name(&fmc->dev, "fmc-%04x", device_id);
221		else
222			dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name,
223				     device_id);
224		ret = device_add(&fmc->dev);
225		if (ret < 0) {
226			dev_err(fmc->hwdev, "Slot %i: Failed in registering "
227				"\"%s\"\n", fmc->slot_id, fmc->dev.kobj.name);
228			goto out;
229		}
230		ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr);
231		if (ret < 0) {
232			dev_err(&fmc->dev, "Failed in registering eeprom\n");
233			goto out1;
234		}
235		/* This device went well, give information to the user */
236		fmc_dump_eeprom(fmc);
237		fmc_dump_sdb(fmc);
238	}
239	return 0;
240
241out1:
242	device_del(&fmc->dev);
243out:
244	fmc_free_id_info(fmc);
245	put_device(&fmc->dev);
246
247	kfree(devarray);
248	for (i--; i >= 0; i--) {
249		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
250		device_del(&devs[i]->dev);
251		fmc_free_id_info(devs[i]);
252		put_device(&devs[i]->dev);
253	}
254	return ret;
255
256}
257EXPORT_SYMBOL(fmc_device_register_n);
258
259int fmc_device_register(struct fmc_device *fmc)
260{
261	return fmc_device_register_n(&fmc, 1);
262}
263EXPORT_SYMBOL(fmc_device_register);
264
265void fmc_device_unregister_n(struct fmc_device **devs, int n)
266{
267	int i;
268
269	if (n < 1)
270		return;
271
272	/* Free devarray first, not used by the later loop */
273	kfree(devs[0]->devarray);
274
275	for (i = 0; i < n; i++) {
276		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
277		device_del(&devs[i]->dev);
278		fmc_free_id_info(devs[i]);
279		put_device(&devs[i]->dev);
280	}
281}
282EXPORT_SYMBOL(fmc_device_unregister_n);
283
284void fmc_device_unregister(struct fmc_device *fmc)
285{
286	fmc_device_unregister_n(&fmc, 1);
287}
288EXPORT_SYMBOL(fmc_device_unregister);
289
290/* Init and exit are trivial */
291static int fmc_init(void)
292{
293	return bus_register(&fmc_bus_type);
294}
295
296static void fmc_exit(void)
297{
298	bus_unregister(&fmc_bus_type);
299}
300
301module_init(fmc_init);
302module_exit(fmc_exit);
303
304MODULE_LICENSE("GPL");