diff options
Diffstat (limited to 'drivers')
50 files changed, 701 insertions, 2845 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index e8231663f201..61cf4ea2c229 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -188,8 +188,6 @@ source "drivers/ipack/Kconfig" source "drivers/reset/Kconfig" -source "drivers/fmc/Kconfig" - source "drivers/phy/Kconfig" source "drivers/powercap/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 28b030d7988d..6d37564e783c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -168,7 +168,6 @@ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_IPACK_BUS) += ipack/ obj-$(CONFIG_NTB) += ntb/ -obj-$(CONFIG_FMC) += fmc/ obj-$(CONFIG_POWERCAP) += powercap/ obj-$(CONFIG_MCB) += mcb/ obj-$(CONFIG_PERF_EVENTS) += perf/ diff --git a/drivers/fmc/Kconfig b/drivers/fmc/Kconfig deleted file mode 100644 index ae3d7f634932..000000000000 --- a/drivers/fmc/Kconfig +++ /dev/null @@ -1,52 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# FMC (ANSI-VITA 57.1) bus support -# - -menuconfig FMC - tristate "FMC support" - help - - FMC (FPGA Mezzanine Carrier) is a mechanical and electrical - standard for mezzanine cards that plug into a carrier board. - This kernel subsystem supports the matching between carrier - and mezzanine based on identifiers stored in the internal I2C - EEPROM, as well as having carrier-independent drivers. - - The framework was born outside of the kernel and at this time - the off-tree code base is more complete. Code and documentation - is at git://ohwr.org/fmc-projects/fmc-bus.git . - -if FMC - -config FMC_FAKEDEV - tristate "FMC fake device (software testing)" - help - This is a fake carrier, bringing a default EEPROM content - that can be rewritten at run time and usef for matching - mezzanines. - -config FMC_TRIVIAL - tristate "FMC trivial mezzanine driver (software testing)" - help - This is a fake mezzanine driver, to show how FMC works and test it. - The driver also handles interrupts (we used it with a real carrier - before the mezzanines were produced) - -config FMC_WRITE_EEPROM - tristate "FMC mezzanine driver to write I2C EEPROM" - help - This driver matches every mezzanine device and can write the - internal EEPROM of the PCB, using the firmware loader to get - its binary and the function carrier->reprogram to actually do it. - It is useful when the mezzanines are produced. - -config FMC_CHARDEV - tristate "FMC mezzanine driver that registers a char device" - help - This driver matches every mezzanine device and allows user - space to read and write registers using a char device. It - can be used to write user-space drivers, or just get - acquainted with a mezzanine before writing its specific driver. - -endif # FMC diff --git a/drivers/fmc/Makefile b/drivers/fmc/Makefile deleted file mode 100644 index e3da6192cf39..000000000000 --- a/drivers/fmc/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-$(CONFIG_FMC) += fmc.o - -fmc-y = fmc-core.o -fmc-y += fmc-match.o -fmc-y += fmc-sdb.o -fmc-y += fru-parse.o -fmc-y += fmc-dump.o -fmc-y += fmc-debug.o - -obj-$(CONFIG_FMC_FAKEDEV) += fmc-fakedev.o -obj-$(CONFIG_FMC_TRIVIAL) += fmc-trivial.o -obj-$(CONFIG_FMC_WRITE_EEPROM) += fmc-write-eeprom.o -obj-$(CONFIG_FMC_CHARDEV) += fmc-chardev.o diff --git a/drivers/fmc/fmc-chardev.c b/drivers/fmc/fmc-chardev.c deleted file mode 100644 index 7d2091b5e978..000000000000 --- a/drivers/fmc/fmc-chardev.c +++ /dev/null @@ -1,199 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2012 CERN (www.cern.ch) - * Author: Alessandro Rubini <rubini@gnudd.com> - * - * This work is part of the White Rabbit project, a research effort led - * by CERN, the European Institute for Nuclear Research. - */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/spinlock.h> -#include <linux/fmc.h> -#include <linux/uaccess.h> - -static LIST_HEAD(fc_devices); -static DEFINE_SPINLOCK(fc_lock); - -struct fc_instance { - struct list_head list; - struct fmc_device *fmc; - struct miscdevice misc; -}; - -/* at open time, we must identify our device */ -static int fc_open(struct inode *ino, struct file *f) -{ - struct fmc_device *fmc; - struct fc_instance *fc; - int minor = iminor(ino); - - list_for_each_entry(fc, &fc_devices, list) - if (fc->misc.minor == minor) - break; - if (fc->misc.minor != minor) - return -ENODEV; - fmc = fc->fmc; - if (try_module_get(fmc->owner) == 0) - return -ENODEV; - - f->private_data = fmc; - return 0; -} - -static int fc_release(struct inode *ino, struct file *f) -{ - struct fmc_device *fmc = f->private_data; - module_put(fmc->owner); - return 0; -} - -/* read and write are simple after the default llseek has been used */ -static ssize_t fc_read(struct file *f, char __user *buf, size_t count, - loff_t *offp) -{ - struct fmc_device *fmc = f->private_data; - unsigned long addr; - uint32_t val; - - if (count < sizeof(val)) - return -EINVAL; - count = sizeof(val); - - addr = *offp; - if (addr > fmc->memlen) - return -ESPIPE; /* Illegal seek */ - val = fmc_readl(fmc, addr); - if (copy_to_user(buf, &val, count)) - return -EFAULT; - *offp += count; - return count; -} - -static ssize_t fc_write(struct file *f, const char __user *buf, size_t count, - loff_t *offp) -{ - struct fmc_device *fmc = f->private_data; - unsigned long addr; - uint32_t val; - - if (count < sizeof(val)) - return -EINVAL; - count = sizeof(val); - - addr = *offp; - if (addr > fmc->memlen) - return -ESPIPE; /* Illegal seek */ - if (copy_from_user(&val, buf, count)) - return -EFAULT; - fmc_writel(fmc, val, addr); - *offp += count; - return count; -} - -static const struct file_operations fc_fops = { - .owner = THIS_MODULE, - .open = fc_open, - .release = fc_release, - .llseek = generic_file_llseek, - .read = fc_read, - .write = fc_write, -}; - - -/* Device part .. */ -static int fc_probe(struct fmc_device *fmc); -static int fc_remove(struct fmc_device *fmc); - -static struct fmc_driver fc_drv = { - .version = FMC_VERSION, - .driver.name = KBUILD_MODNAME, - .probe = fc_probe, - .remove = fc_remove, - /* no table: we want to match everything */ -}; - -/* We accept the generic busid parameter */ -FMC_PARAM_BUSID(fc_drv); - -/* probe and remove must allocate and release a misc device */ -static int fc_probe(struct fmc_device *fmc) -{ - int ret; - int index = 0; - - struct fc_instance *fc; - - index = fmc_validate(fmc, &fc_drv); - if (index < 0) - return -EINVAL; /* not our device: invalid */ - - /* Create a char device: we want to create it anew */ - fc = kzalloc(sizeof(*fc), GFP_KERNEL); - if (!fc) - return -ENOMEM; - fc->fmc = fmc; - fc->misc.minor = MISC_DYNAMIC_MINOR; - fc->misc.fops = &fc_fops; - fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); - - ret = misc_register(&fc->misc); - if (ret < 0) - goto out; - spin_lock(&fc_lock); - list_add(&fc->list, &fc_devices); - spin_unlock(&fc_lock); - dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", - fc->misc.name); - return 0; - -out: - kfree(fc->misc.name); - kfree(fc); - return ret; -} - -static int fc_remove(struct fmc_device *fmc) -{ - struct fc_instance *fc; - - list_for_each_entry(fc, &fc_devices, list) - if (fc->fmc == fmc) - break; - if (fc->fmc != fmc) { - dev_err(&fmc->dev, "remove called but not found\n"); - return -ENODEV; - } - - spin_lock(&fc_lock); - list_del(&fc->list); - spin_unlock(&fc_lock); - misc_deregister(&fc->misc); - kfree(fc->misc.name); - kfree(fc); - - return 0; -} - - -static int fc_init(void) -{ - int ret; - - ret = fmc_driver_register(&fc_drv); - return ret; -} - -static void fc_exit(void) -{ - fmc_driver_unregister(&fc_drv); -} - -module_init(fc_init); -module_exit(fc_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/fmc/fmc-core.c b/drivers/fmc/fmc-core.c deleted file mode 100644 index 573f5471f680..000000000000 --- a/drivers/fmc/fmc-core.c +++ /dev/null @@ -1,388 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2012 CERN (www.cern.ch) - * Author: Alessandro Rubini <rubini@gnudd.com> - * - * This work is part of the White Rabbit project, a research effort led - * by CERN, the European Institute for Nuclear Research. - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/fmc.h> -#include <linux/fmc-sdb.h> - -#include "fmc-private.h" - -static int fmc_check_version(unsigned long version, const char *name) -{ - if (__FMC_MAJOR(version) != FMC_MAJOR) { - pr_err("%s: \"%s\" has wrong major (has %li, expected %i)\n", - __func__, name, __FMC_MAJOR(version), FMC_MAJOR); - return -EINVAL; - } - - if (__FMC_MINOR(version) != FMC_MINOR) - pr_info("%s: \"%s\" has wrong minor (has %li, expected %i)\n", - __func__, name, __FMC_MINOR(version), FMC_MINOR); - return 0; -} - -static int fmc_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - /* struct fmc_device *fdev = to_fmc_device(dev); */ - - /* FIXME: The MODALIAS */ - add_uevent_var(env, "MODALIAS=%s", "fmc"); - return 0; -} - -static int fmc_probe(struct device *dev) -{ - struct fmc_driver *fdrv = to_fmc_driver(dev->driver); - struct fmc_device *fdev = to_fmc_device(dev); - - return fdrv->probe(fdev); -} - -static int fmc_remove(struct device *dev) -{ - struct fmc_driver *fdrv = to_fmc_driver(dev->driver); - struct fmc_device *fdev = to_fmc_device(dev); - - return fdrv->remove(fdev); -} - -static void fmc_shutdown(struct device *dev) -{ - /* not implemented but mandatory */ -} - -static struct bus_type fmc_bus_type = { - .name = "fmc", - .match = fmc_match, - .uevent = fmc_uevent, - .probe = fmc_probe, - .remove = fmc_remove, - .shutdown = fmc_shutdown, -}; - -static void fmc_release(struct device *dev) -{ - struct fmc_device *fmc = container_of(dev, struct fmc_device, dev); - - kfree(fmc); -} - -/* - * The eeprom is exported in sysfs, through a binary attribute - */ - -static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev; - struct fmc_device *fmc; - int eelen; - - dev = container_of(kobj, struct device, kobj); - fmc = container_of(dev, struct fmc_device, dev); - eelen = fmc->eeprom_len; - if (off > eelen) - return -ESPIPE; - if (off == eelen) - return 0; /* EOF */ - if (off + count > eelen) - count = eelen - off; - memcpy(buf, fmc->eeprom + off, count); - return count; -} - -static ssize_t fmc_write_eeprom(struct file *file, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev; - struct fmc_device *fmc; - - dev = container_of(kobj, struct device, kobj); - fmc = container_of(dev, struct fmc_device, dev); - return fmc->op->write_ee(fmc, off, buf, count); -} - -static struct bin_attribute fmc_eeprom_attr = { - .attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, }, - .size = 8192, /* more or less standard */ - .read = fmc_read_eeprom, - .write = fmc_write_eeprom, -}; - -int fmc_irq_request(struct fmc_device *fmc, irq_handler_t h, - char *name, int flags) -{ - if (fmc->op->irq_request) - return fmc->op->irq_request(fmc, h, name, flags); - return -EPERM; -} -EXPORT_SYMBOL(fmc_irq_request); - -void fmc_irq_free(struct fmc_device *fmc) -{ - if (fmc->op->irq_free) - fmc->op->irq_free(fmc); -} -EXPORT_SYMBOL(fmc_irq_free); - -void fmc_irq_ack(struct fmc_device *fmc) -{ - if (likely(fmc->op->irq_ack)) - fmc->op->irq_ack(fmc); -} -EXPORT_SYMBOL(fmc_irq_ack); - -int fmc_validate(struct fmc_device *fmc, struct fmc_driver *drv) -{ - if (fmc->op->validate) - return fmc->op->validate(fmc, drv); - return -EPERM; -} -EXPORT_SYMBOL(fmc_validate); - -int fmc_gpio_config(struct fmc_device *fmc, struct fmc_gpio *gpio, int ngpio) -{ - if (fmc->op->gpio_config) - return fmc->op->gpio_config(fmc, gpio, ngpio); - return -EPERM; -} -EXPORT_SYMBOL(fmc_gpio_config); - -int fmc_read_ee(struct fmc_device *fmc, int pos, void *d, int l) -{ - if (fmc->op->read_ee) - return fmc->op->read_ee(fmc, pos, d, l); - return -EPERM; -} -EXPORT_SYMBOL(fmc_read_ee); - -int fmc_write_ee(struct fmc_device *fmc, int pos, const void *d, int l) -{ - if (fmc->op->write_ee) - return fmc->op->write_ee(fmc, pos, d, l); - return -EPERM; -} -EXPORT_SYMBOL(fmc_write_ee); - -/* - * Functions for client modules follow - */ - -int fmc_driver_register(struct fmc_driver *drv) -{ - if (fmc_check_version(drv->version, drv->driver.name)) - return -EINVAL; - drv->driver.bus = &fmc_bus_type; - return driver_register(&drv->driver); -} -EXPORT_SYMBOL(fmc_driver_register); - -void fmc_driver_unregister(struct fmc_driver *drv) -{ - driver_unregister(&drv->driver); -} -EXPORT_SYMBOL(fmc_driver_unregister); - -/* - * When a device set is registered, all eeproms must be read - * and all FRUs must be parsed - */ -int fmc_device_register_n_gw(struct fmc_device **devs, int n, - struct fmc_gateware *gw) -{ - struct fmc_device *fmc, **devarray; - uint32_t device_id; - int i, ret = 0; - - if (n < 1) - return 0; - - /* Check the version of the first data structure (function prints) */ - if (fmc_check_version(devs[0]->version, devs[0]->carrier_name)) - return -EINVAL; - - devarray = kmemdup(devs, n * sizeof(*devs), GFP_KERNEL); - if (!devarray) - return -ENOMEM; - - /* Make all other checks before continuing, for all devices */ - for (i = 0; i < n; i++) { - fmc = devarray[i]; - if (!fmc->hwdev) { - pr_err("%s: device nr. %i has no hwdev pointer\n", - __func__, i); - ret = -EINVAL; - break; - } - if (fmc->flags & FMC_DEVICE_NO_MEZZANINE) { - dev_info(fmc->hwdev, "absent mezzanine in slot %d\n", - fmc->slot_id); - continue; - } - if (!fmc->eeprom) { - dev_err(fmc->hwdev, "no eeprom provided for slot %i\n", - fmc->slot_id); - ret = -EINVAL; - } - if (!fmc->eeprom_addr) { - dev_err(fmc->hwdev, "no eeprom_addr for slot %i\n", - fmc->slot_id); - ret = -EINVAL; - } - if (!fmc->carrier_name || !fmc->carrier_data || - !fmc->device_id) { - dev_err(fmc->hwdev, - "device nr %i: carrier name, " - "data or dev_id not set\n", i); - ret = -EINVAL; - } - if (ret) - break; - - } - if (ret) { - kfree(devarray); - return ret; - } - - /* Validation is ok. Now init and register the devices */ - for (i = 0; i < n; i++) { - fmc = devarray[i]; - - fmc->nr_slots = n; /* each slot must know how many are there */ - fmc->devarray = devarray; - - device_initialize(&fmc->dev); - fmc->dev.release = fmc_release; - fmc->dev.parent = fmc->hwdev; - - /* Fill the identification stuff (may fail) */ - fmc_fill_id_info(fmc); - - fmc->dev.bus = &fmc_bus_type; - - /* Name from mezzanine info or carrier info. Or 0,1,2.. */ - device_id = fmc->device_id; - if (!fmc->mezzanine_name) - dev_set_name(&fmc->dev, "fmc-%04x", device_id); - else - dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name, - device_id); - - if (gw) { - /* - * The carrier already know the bitstream to load - * for this set of FMC mezzanines. - */ - ret = fmc->op->reprogram_raw(fmc, NULL, - gw->bitstream, gw->len); - if (ret) { - dev_warn(fmc->hwdev, - "Invalid gateware for FMC mezzanine\n"); - goto out; - } - } - - ret = device_add(&fmc->dev); - if (ret < 0) { - dev_err(fmc->hwdev, "Slot %i: Failed in registering " - "\"%s\"\n", fmc->slot_id, fmc->dev.kobj.name); - goto out; - } - ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr); - if (ret < 0) { - dev_err(&fmc->dev, "Failed in registering eeprom\n"); - goto out1; - } - /* This device went well, give information to the user */ - fmc_dump_eeprom(fmc); - fmc_debug_init(fmc); - } - return 0; - -out1: - device_del(&fmc->dev); -out: - kfree(devarray); - for (i--; i >= 0; i--) { - fmc_debug_exit(devs[i]); - sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr); - device_del(&devs[i]->dev); - fmc_free_id_info(devs[i]); - put_device(&devs[i]->dev); - } - return ret; - -} -EXPORT_SYMBOL(fmc_device_register_n_gw); - -int fmc_device_register_n(struct fmc_device **devs, int n) -{ - return fmc_device_register_n_gw(devs, n, NULL); -} -EXPORT_SYMBOL(fmc_device_register_n); - -int fmc_device_register_gw(struct fmc_device *fmc, struct fmc_gateware *gw) -{ - return fmc_device_register_n_gw(&fmc, 1, gw); -} -EXPORT_SYMBOL(fmc_device_register_gw); - -int fmc_device_register(struct fmc_device *fmc) -{ - return fmc_device_register_n(&fmc, 1); -} -EXPORT_SYMBOL(fmc_device_register); - -void fmc_device_unregister_n(struct fmc_device **devs, int n) -{ - int i; - - if (n < 1) - return; - - /* Free devarray first, not used by the later loop */ - kfree(devs[0]->devarray); - - for (i = 0; i < n; i++) { - fmc_debug_exit(devs[i]); - sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr); - device_del(&devs[i]->dev); - fmc_free_id_info(devs[i]); - put_device(&devs[i]->dev); - } -} -EXPORT_SYMBOL(fmc_device_unregister_n); - -void fmc_device_unregister(struct fmc_device *fmc) -{ - fmc_device_unregister_n(&fmc, 1); -} -EXPORT_SYMBOL(fmc_device_unregister); - -/* Init and exit are trivial */ -static int fmc_init(void) -{ - return bus_register(&fmc_bus_type); -} - -static void fmc_exit(void) -{ - bus_unregister(&fmc_bus_type); -} - -module_init(fmc_init); -module_exit(fmc_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/fmc/fmc-debug.c b/drivers/fmc/fmc-debug.c deleted file mode 100644 index 1734c7cf0e76..000000000000 --- a/drivers/fmc/fmc-debug.c +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2015 CERN (www.cern.ch) - * Author: Federico Vaga <federico.vaga@cern.ch> - */ - -#include <linux/module.h> -#include <linux/device.h> -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <asm/byteorder.h> - -#include <linux/fmc.h> -#include <linux/sdb.h> -#include <linux/fmc-sdb.h> - -#define FMC_DBG_SDB_DUMP "dump_sdb" - -static char *__strip_trailing_space(char *buf, char *str, int len) -{ - int i = len - 1; - - memcpy(buf, str, len); - buf[len] = '\0'; - while (i >= 0 && buf[i] == ' ') - buf[i--] = '\0'; - return buf; -} - -#define __sdb_string(buf, field) ({ \ - BUILD_BUG_ON(sizeof(buf) < sizeof(field)); \ - __strip_trailing_space(buf, (void *)(field), sizeof(field)); \ - }) - -/** - * We do not check seq_printf() errors because we want to see things in any case - */ -static void fmc_sdb_dump_recursive(struct fmc_device *fmc, struct seq_file *s, - const struct sdb_array *arr) -{ - unsigned long base = arr->baseaddr; - int i, j, n = arr->len, level = arr->level; - char tmp[64]; - - for (i = 0; i < n; i++) { - union sdb_record *r; - struct sdb_product *p; - struct sdb_component *c; - - r = &arr->record[i]; - c = &r->dev.sdb_component; - p = &c->product; - - for (j = 0; j < level; j++) - seq_printf(s, " "); - switch (r->empty.record_type) { - case sdb_type_interconnect: - seq_printf(s, "%08llx:%08x %.19s\n", - __be64_to_cpu(p->vendor_id), - __be32_to_cpu(p->device_id), - p->name); - break; - case sdb_type_device: - seq_printf(s, "%08llx:%08x %.19s (%08llx-%08llx)\n", - __be64_to_cpu(p->vendor_id), - __be32_to_cpu(p->device_id), - p->name, - __be64_to_cpu(c->addr_first) + base, - __be64_to_cpu(c->addr_last) + base); - break; - case sdb_type_bridge: - seq_printf(s, "%08llx:%08x %.19s (bridge: %08llx)\n", - __be64_to_cpu(p->vendor_id), - __be32_to_cpu(p->device_id), - p->name, - __be64_to_cpu(c->addr_first) + base); - if (IS_ERR(arr->subtree[i])) { - seq_printf(s, "SDB: (bridge error %li)\n", - PTR_ERR(arr->subtree[i])); - break; - } - fmc_sdb_dump_recursive(fmc, s, arr->subtree[i]); - break; - case sdb_type_integration: - seq_printf(s, "integration\n"); - break; - case sdb_type_repo_url: - seq_printf(s, "Synthesis repository: %s\n", - __sdb_string(tmp, r->repo_url.repo_url)); - break; - case sdb_type_synthesis: - seq_printf(s, "Bitstream '%s' ", - __sdb_string(tmp, r->synthesis.syn_name)); - seq_printf(s, "synthesized %08x by %s ", - __be32_to_cpu(r->synthesis.date), - __sdb_string(tmp, r->synthesis.user_name)); - seq_printf(s, "(%s version %x), ", - __sdb_string(tmp, r->synthesis.tool_name), - __be32_to_cpu(r->synthesis.tool_version)); - seq_printf(s, "commit %pm\n", |