fmc-write-eeprom.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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/module.h>
  11. #include <linux/string.h>
  12. #include <linux/firmware.h>
  13. #include <linux/init.h>
  14. #include <linux/fmc.h>
  15. #include <asm/unaligned.h>
  16. /*
  17. * This module uses the firmware loader to program the whole or part
  18. * of the FMC eeprom. The meat is in the _run functions. However, no
  19. * default file name is provided, to avoid accidental mishaps. Also,
  20. * you must pass the busid argument
  21. */
  22. static struct fmc_driver fwe_drv;
  23. FMC_PARAM_BUSID(fwe_drv);
  24. /* The "file=" is like the generic "gateware=" used elsewhere */
  25. static char *fwe_file[FMC_MAX_CARDS];
  26. static int fwe_file_n;
  27. module_param_array_named(file, fwe_file, charp, &fwe_file_n, 0444);
  28. static int fwe_run_tlv(struct fmc_device *fmc, const struct firmware *fw,
  29. int write)
  30. {
  31. const uint8_t *p = fw->data;
  32. int len = fw->size;
  33. uint16_t thislen, thisaddr;
  34. int err;
  35. /* format is: 'w' addr16 len16 data... */
  36. while (len > 5) {
  37. thisaddr = get_unaligned_le16(p+1);
  38. thislen = get_unaligned_le16(p+3);
  39. if (p[0] != 'w' || thislen + 5 > len) {
  40. dev_err(&fmc->dev, "invalid tlv at offset %ti\n",
  41. p - fw->data);
  42. return -EINVAL;
  43. }
  44. err = 0;
  45. if (write) {
  46. dev_info(&fmc->dev, "write %i bytes at 0x%04x\n",
  47. thislen, thisaddr);
  48. err = fmc->op->write_ee(fmc, thisaddr, p + 5, thislen);
  49. }
  50. if (err < 0) {
  51. dev_err(&fmc->dev, "write failure @0x%04x\n",
  52. thisaddr);
  53. return err;
  54. }
  55. p += 5 + thislen;
  56. len -= 5 + thislen;
  57. }
  58. if (write)
  59. dev_info(&fmc->dev, "write_eeprom: success\n");
  60. return 0;
  61. }
  62. static int fwe_run_bin(struct fmc_device *fmc, const struct firmware *fw)
  63. {
  64. int ret;
  65. dev_info(&fmc->dev, "programming %zi bytes\n", fw->size);
  66. ret = fmc->op->write_ee(fmc, 0, (void *)fw->data, fw->size);
  67. if (ret < 0) {
  68. dev_info(&fmc->dev, "write_eeprom: error %i\n", ret);
  69. return ret;
  70. }
  71. dev_info(&fmc->dev, "write_eeprom: success\n");
  72. return 0;
  73. }
  74. static int fwe_run(struct fmc_device *fmc, const struct firmware *fw, char *s)
  75. {
  76. char *last4 = s + strlen(s) - 4;
  77. int err;
  78. if (!strcmp(last4, ".bin"))
  79. return fwe_run_bin(fmc, fw);
  80. if (!strcmp(last4, ".tlv")) {
  81. err = fwe_run_tlv(fmc, fw, 0);
  82. if (!err)
  83. err = fwe_run_tlv(fmc, fw, 1);
  84. return err;
  85. }
  86. dev_err(&fmc->dev, "invalid file name \"%s\"\n", s);
  87. return -EINVAL;
  88. }
  89. /*
  90. * Programming is done at probe time. Morever, only those listed with
  91. * busid= are programmed.
  92. * card is probed for, only one is programmed. Unfortunately, it's
  93. * difficult to know in advance when probing the first card if others
  94. * are there.
  95. */
  96. static int fwe_probe(struct fmc_device *fmc)
  97. {
  98. int err, index = 0;
  99. const struct firmware *fw;
  100. struct device *dev = &fmc->dev;
  101. char *s;
  102. if (!fwe_drv.busid_n) {
  103. dev_err(dev, "%s: no busid passed, refusing all cards\n",
  104. KBUILD_MODNAME);
  105. return -ENODEV;
  106. }
  107. if (fmc->op->validate)
  108. index = fmc->op->validate(fmc, &fwe_drv);
  109. if (index < 0) {
  110. pr_err("%s: refusing device \"%s\"\n", KBUILD_MODNAME,
  111. dev_name(dev));
  112. return -ENODEV;
  113. }
  114. if (index >= fwe_file_n) {
  115. pr_err("%s: no filename for device index %i\n",
  116. KBUILD_MODNAME, index);
  117. return -ENODEV;
  118. }
  119. s = fwe_file[index];
  120. if (!s) {
  121. pr_err("%s: no filename for \"%s\" not programming\n",
  122. KBUILD_MODNAME, dev_name(dev));
  123. return -ENOENT;
  124. }
  125. err = request_firmware(&fw, s, dev);
  126. if (err < 0) {
  127. dev_err(&fmc->dev, "request firmware \"%s\": error %i\n",
  128. s, err);
  129. return err;
  130. }
  131. fwe_run(fmc, fw, s);
  132. release_firmware(fw);
  133. return 0;
  134. }
  135. static int fwe_remove(struct fmc_device *fmc)
  136. {
  137. return 0;
  138. }
  139. static struct fmc_driver fwe_drv = {
  140. .version = FMC_VERSION,
  141. .driver.name = KBUILD_MODNAME,
  142. .probe = fwe_probe,
  143. .remove = fwe_remove,
  144. /* no table, as the current match just matches everything */
  145. };
  146. static int fwe_init(void)
  147. {
  148. int ret;
  149. ret = fmc_driver_register(&fwe_drv);
  150. return ret;
  151. }
  152. static void fwe_exit(void)
  153. {
  154. fmc_driver_unregister(&fwe_drv);
  155. }
  156. module_init(fwe_init);
  157. module_exit(fwe_exit);
  158. MODULE_LICENSE("GPL");