Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v4.18-rc1 389 lines 9.1 kB view raw
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");