123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- /*
- * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- #include <linux/of.h>
- #include <linux/of_net.h>
- #include <linux/mtd/mtd.h>
- #include <linux/mtd/partitions.h>
- #include <linux/etherdevice.h>
- #include "mt76.h"
- static int
- mt76_get_of_eeprom(struct mt76_dev *dev, int len)
- {
- #if defined(CONFIG_OF) && defined(CONFIG_MTD)
- struct device_node *np = dev->dev->of_node;
- struct mtd_info *mtd;
- const __be32 *list;
- const char *part;
- phandle phandle;
- int offset = 0;
- int size;
- size_t retlen;
- int ret;
- if (!np)
- return -ENOENT;
- list = of_get_property(np, "mediatek,mtd-eeprom", &size);
- if (!list)
- return -ENOENT;
- phandle = be32_to_cpup(list++);
- if (!phandle)
- return -ENOENT;
- np = of_find_node_by_phandle(phandle);
- if (!np)
- return -EINVAL;
- part = of_get_property(np, "label", NULL);
- if (!part)
- part = np->name;
- mtd = get_mtd_device_nm(part);
- if (IS_ERR(mtd))
- return PTR_ERR(mtd);
- if (size <= sizeof(*list))
- return -EINVAL;
- offset = be32_to_cpup(list);
- ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data);
- put_mtd_device(mtd);
- if (ret)
- return ret;
- if (retlen < len)
- return -EINVAL;
- return 0;
- #else
- return -ENOENT;
- #endif
- }
- void
- mt76_eeprom_override(struct mt76_dev *dev)
- {
- #ifdef CONFIG_OF
- struct device_node *np = dev->dev->of_node;
- const u8 *mac;
- if (!np)
- return;
- mac = of_get_mac_address(np);
- if (mac)
- memcpy(dev->macaddr, mac, ETH_ALEN);
- #endif
- if (!is_valid_ether_addr(dev->macaddr)) {
- eth_random_addr(dev->macaddr);
- dev_info(dev->dev,
- "Invalid MAC address, using random address %pM\n",
- dev->macaddr);
- }
- }
- EXPORT_SYMBOL_GPL(mt76_eeprom_override);
- int
- mt76_eeprom_init(struct mt76_dev *dev, int len)
- {
- dev->eeprom.size = len;
- dev->eeprom.data = devm_kzalloc(dev->dev, len, GFP_KERNEL);
- if (!dev->eeprom.data)
- return -ENOMEM;
- return !mt76_get_of_eeprom(dev, len);
- }
- EXPORT_SYMBOL_GPL(mt76_eeprom_init);
|