fmc-write-eeprom.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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_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_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. index = fmc_validate(fmc, &fwe_drv);
  108. if (index < 0) {
  109. pr_err("%s: refusing device \"%s\"\n", KBUILD_MODNAME,
  110. dev_name(dev));
  111. return -ENODEV;
  112. }
  113. if (index >= fwe_file_n) {
  114. pr_err("%s: no filename for device index %i\n",
  115. KBUILD_MODNAME, index);
  116. return -ENODEV;
  117. }
  118. s = fwe_file[index];
  119. if (!s) {
  120. pr_err("%s: no filename for \"%s\" not programming\n",
  121. KBUILD_MODNAME, dev_name(dev));
  122. return -ENOENT;
  123. }
  124. err = request_firmware(&fw, s, dev);
  125. if (err < 0) {
  126. dev_err(&fmc->dev, "request firmware \"%s\": error %i\n",
  127. s, err);
  128. return err;
  129. }
  130. fwe_run(fmc, fw, s);
  131. release_firmware(fw);
  132. return 0;
  133. }
  134. static int fwe_remove(struct fmc_device *fmc)
  135. {
  136. return 0;
  137. }
  138. static struct fmc_driver fwe_drv = {
  139. .version = FMC_VERSION,
  140. .driver.name = KBUILD_MODNAME,
  141. .probe = fwe_probe,
  142. .remove = fwe_remove,
  143. /* no table, as the current match just matches everything */
  144. };
  145. static int fwe_init(void)
  146. {
  147. int ret;
  148. ret = fmc_driver_register(&fwe_drv);
  149. return ret;
  150. }
  151. static void fwe_exit(void)
  152. {
  153. fmc_driver_unregister(&fwe_drv);
  154. }
  155. module_init(fwe_init);
  156. module_exit(fwe_exit);
  157. MODULE_LICENSE("GPL");