Skip to content

Instantly share code, notes, and snippets.

@zavorka
Last active April 2, 2019 12:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zavorka/b1cd1b688648f259238ef2168c22782d to your computer and use it in GitHub Desktop.
Save zavorka/b1cd1b688648f259238ef2168c22782d to your computer and use it in GitHub Desktop.
burn_ethaddr_to_efuses
&emac {
nvmem-cells = <&ethaddr>;
nvmem-cell-names = "mac-address";
};
&sid {
#address-cells = <1>;
#size-cells = <1>;
ethaddr: ethaddr@ec {
reg = <0xec 0x06>;
};
}
// MAP OF WRITABLE REGIONS
//
// Obtained by sequentially writing 0xff into each byte except
// - CHIPID field (read-only),
// - THERMAL_SENSOR field (already contaminated) and
// - LCJS field (writable but the value is affecting behavior)
//
// I guess the remaining unchanged bits become writable under
// some yet-to-be-found condition.
// I didn't observe any undesirable effect after setting
// the eFuses, can't guarantee there aren't any though.
// (Tried out on hundreds of chips)
//
// 00000000 /* CHIPID */
// 00000010 ff ff ff ff 00 00 00 00 ff ff ff ff ff ff ff ff
// 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 00000030 00 00 00 00 /* THERMAL_SENSOR */ ff ff ff ff
// 00000040 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00
// 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// 000000e0 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff
// 000000f0 ff ff ff ff /* LCJS */ 00 00 00 00 00 00 00 00
#include <cstdio>
#include <endian.h>
#include <cstring>
#include <cassert>
/* Forward declarations */
typedef struct _feldev_handle feldev_handle;
uint32_t fel_readl(feldev_handle *dev, uint32_t addr);
void fel_writel(feldev_handle *dev, uint32_t addr, uint32_t val);
constexpr uint8_t SID_ETH_MAC_OFFSET 0xec;
constexpr uint32_t EFUSES_MAGIC = 0xac00u;
extern "C" uint32_t read_sid(feldev_handle *dev, uint8_t address)
{
uint32_t prctl = (address << 16) | EFUSES_MAGIC | 0x02u;
fel_writel(dev, 0x01c14040, prctl);
uint32_t data = fel_readl(dev, 0x01c14060);
return be32toh(data);
}
extern "C" void write_sid(feldev_handle *dev, uint8_t address, uint32_t value)
{
uint32_t prctl = (address << 16) | EFUSES_MAGIC | 0x01u;
fel_writel(dev, 0x01c14050, htobe32(value));
fel_writel(dev, 0x01c14040, prctl);
}
extern "C" void write_eth_mac(feldev_handle* handle, uint8_t* mac)
{
uint32_t tmp;
memcpy(&tmp, mac, 4);
write_sid(handle, SID_ETH_MAC_OFFSET, tmp);
memcpy(&tmp, mac + 4, 4);
write_sid(handle, SID_ETH_MAC_OFFSET + 4, tmp);
}
extern "C" void print_eth_mac(feldev_handle *dev)
{
uint8_t ether_addr[8];
uint32_t tmp = read_sid(dev, SID_ETH_MAC_OFFSET);
memcpy(ether_addr, &tmp, 4);
tmp = read_sid(dev, SID_ETH_MAC_OFFSET + 4);
memcpy(ether_addr + 4, &tmp, 4);
printf("eth mac is %02X:%02X:%02X:%02X:%02X:%02X\n",
ether_addr[0], ether_addr[1], ether_addr[2],
ether_addr[3], ether_addr[4], ether_addr[5]
);
}
967142cf31f8b20eeec2d5633eeb29ad9104c4ccommit 967142cf31f8b20eeec2d5633eeb29ad9104c4c3
Author: Roman Beránek <roman.beranek@prusa3d.com>
Date: Fri Nov 16 02:19:25 2018 +0100
net: stmmac: enable MAC address to be read from a nvmem cell as is described in Documentation/devicetree/bindings/net/ethernet.txt
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 72da77b94ecd..8a7b804528ef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -25,6 +25,7 @@
#include <linux/of_net.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
+#include <linux/nvmem-consumer.h>
#include "stmmac.h"
#include "stmmac_platform.h"
@@ -375,6 +376,22 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
return 0;
}
+static void *stmmac_get_nvmem_address(struct device *dev)
+{
+ struct nvmem_cell *cell;
+ size_t cell_size;
+ char *mac;
+
+ cell = nvmem_cell_get(dev, "mac-address");
+ if (IS_ERR(cell))
+ return NULL;
+
+ mac = nvmem_cell_read(cell, &cell_size);
+ nvmem_cell_put(cell);
+
+ return mac;
+}
+
/**
* stmmac_probe_config_dt - parse device-tree driver parameters
* @pdev: platform_device structure
@@ -389,13 +406,21 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
struct device_node *np = pdev->dev.of_node;
struct plat_stmmacenet_data *plat;
struct stmmac_dma_cfg *dma_cfg;
+ const u8 *mac_addr;
int rc;
plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
if (!plat)
return ERR_PTR(-ENOMEM);
+ /* U-boot passes a MAC address it found/generated for the
+ interface as a "local-mac-address" attribute in the dt
+ node. Here it is received.
+ */
*mac = of_get_mac_address(np);
+ mac_addr = stmmac_get_nvmem_address(&pdev->dev);
+ if (mac_addr && is_valid_ether_addr(mac_addr))
+ *mac = mac_addr;
plat->interface = of_get_phy_mode(np);
/* Get max speed of operation from device tree */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment