eeprom.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/of.h>
  17. #include <linux/of_net.h>
  18. #include <linux/mtd/mtd.h>
  19. #include <linux/mtd/partitions.h>
  20. #include <linux/etherdevice.h>
  21. #include "mt76.h"
  22. static int
  23. mt76_get_of_eeprom(struct mt76_dev *dev, int len)
  24. {
  25. #if defined(CONFIG_OF) && defined(CONFIG_MTD)
  26. struct device_node *np = dev->dev->of_node;
  27. struct mtd_info *mtd;
  28. const __be32 *list;
  29. const char *part;
  30. phandle phandle;
  31. int offset = 0;
  32. int size;
  33. size_t retlen;
  34. int ret;
  35. if (!np)
  36. return -ENOENT;
  37. list = of_get_property(np, "mediatek,mtd-eeprom", &size);
  38. if (!list)
  39. return -ENOENT;
  40. phandle = be32_to_cpup(list++);
  41. if (!phandle)
  42. return -ENOENT;
  43. np = of_find_node_by_phandle(phandle);
  44. if (!np)
  45. return -EINVAL;
  46. part = of_get_property(np, "label", NULL);
  47. if (!part)
  48. part = np->name;
  49. mtd = get_mtd_device_nm(part);
  50. if (IS_ERR(mtd))
  51. return PTR_ERR(mtd);
  52. if (size <= sizeof(*list))
  53. return -EINVAL;
  54. offset = be32_to_cpup(list);
  55. ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data);
  56. put_mtd_device(mtd);
  57. if (ret)
  58. return ret;
  59. if (retlen < len)
  60. return -EINVAL;
  61. return 0;
  62. #else
  63. return -ENOENT;
  64. #endif
  65. }
  66. void
  67. mt76_eeprom_override(struct mt76_dev *dev)
  68. {
  69. #ifdef CONFIG_OF
  70. struct device_node *np = dev->dev->of_node;
  71. const u8 *mac;
  72. if (!np)
  73. return;
  74. mac = of_get_mac_address(np);
  75. if (mac)
  76. memcpy(dev->macaddr, mac, ETH_ALEN);
  77. #endif
  78. if (!is_valid_ether_addr(dev->macaddr)) {
  79. eth_random_addr(dev->macaddr);
  80. dev_info(dev->dev,
  81. "Invalid MAC address, using random address %pM\n",
  82. dev->macaddr);
  83. }
  84. }
  85. EXPORT_SYMBOL_GPL(mt76_eeprom_override);
  86. int
  87. mt76_eeprom_init(struct mt76_dev *dev, int len)
  88. {
  89. dev->eeprom.size = len;
  90. dev->eeprom.data = devm_kzalloc(dev->dev, len, GFP_KERNEL);
  91. if (!dev->eeprom.data)
  92. return -ENOMEM;
  93. return !mt76_get_of_eeprom(dev, len);
  94. }
  95. EXPORT_SYMBOL_GPL(mt76_eeprom_init);