Skip to content

Commit cce0826

Browse files
theadibhenrikbrixandersen
authored andcommitted
eth_nxp_enet_qos_mac: implement the nxp,unique-mac address feature
This implements to generate the MAC address of the device UUID. The UUID is hashed to reduce the size to 3 bytes. Ideas taken from eth_nxp_enet.c Adding dependencies on: HWInfo and CRC Signed-off-by: Adib Taraben <[email protected]>
1 parent cf91c1b commit cce0826

File tree

4 files changed

+112
-45
lines changed

4 files changed

+112
-45
lines changed

drivers/ethernet/eth_nxp_enet_qos/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ config ETH_NXP_ENET_QOS_MAC
2323

2424
if ETH_NXP_ENET_QOS_MAC
2525

26+
DT_PROP_NXP_ENET_QOS_MAC_UNIQUE_MAC := nxp,unique-mac
27+
28+
config ETH_NXP_ENET_QOS_MAC_UNIQUE_MAC_ADDRESS
29+
bool "Unique MAC address support"
30+
default y if $(dt_compat_any_has_prop,$(DT_COMPAT_NXP_ENET_QOS_MAC),$(DT_PROP_NXP_ENET_QOS_MAC_UNIQUE_MAC),True)
31+
select HWINFO
32+
select CRC
33+
help
34+
Enable Unique MAC address support based on device UUID.
35+
36+
2637
config ETH_NXP_ENET_QOS_TX_BUFFER_DESCRIPTORS
2738
int "Number of tx buffer descriptors"
2839
default 4

drivers/ethernet/eth_nxp_enet_qos/eth_nxp_enet_qos_mac.c

Lines changed: 81 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ LOG_MODULE_REGISTER(eth_nxp_enet_qos_mac, CONFIG_ETHERNET_LOG_LEVEL);
1212
#include <zephyr/net/phy.h>
1313
#include <zephyr/kernel/thread_stack.h>
1414
#include <zephyr/sys_clock.h>
15+
#if defined(CONFIG_ETH_NXP_ENET_QOS_MAC_UNIQUE_MAC_ADDRESS)
16+
#include <zephyr/sys/crc.h>
17+
#include <zephyr/drivers/hwinfo.h>
18+
#endif
1519
#include <ethernet/eth_stats.h>
1620
#include "../eth.h"
1721
#include "nxp_enet_qos_priv.h"
@@ -480,6 +484,33 @@ static inline int enet_qos_rx_desc_init(enet_qos_t *base, struct nxp_enet_qos_rx
480484
return 0;
481485
}
482486

487+
#if defined(CONFIG_ETH_NXP_ENET_QOS_MAC_UNIQUE_MAC_ADDRESS)
488+
/* Note this is not universally unique, it just is probably unique on a network */
489+
static inline void nxp_enet_unique_mac(uint8_t *mac_addr)
490+
{
491+
uint8_t unique_device_ID_16_bytes[16] = {0};
492+
ssize_t uuid_length =
493+
hwinfo_get_device_id(unique_device_ID_16_bytes, sizeof(unique_device_ID_16_bytes));
494+
uint32_t hash = 0;
495+
496+
if (uuid_length > 0) {
497+
hash = crc24_pgp((uint8_t *)unique_device_ID_16_bytes, uuid_length);
498+
} else {
499+
LOG_ERR("No unique MAC can be provided in this platform");
500+
}
501+
502+
/* Setting LAA bit because it is not guaranteed universally unique */
503+
mac_addr[0] = NXP_OUI_BYTE_0 | 0x02;
504+
mac_addr[1] = NXP_OUI_BYTE_1;
505+
mac_addr[2] = NXP_OUI_BYTE_2;
506+
mac_addr[3] = FIELD_GET(0xFF0000, hash);
507+
mac_addr[4] = FIELD_GET(0x00FF00, hash);
508+
mac_addr[5] = FIELD_GET(0x0000FF, hash);
509+
}
510+
#else
511+
#define nxp_enet_unique_mac(arg)
512+
#endif
513+
483514
static int eth_nxp_enet_qos_mac_init(const struct device *dev)
484515
{
485516
const struct nxp_enet_qos_mac_config *config = dev->config;
@@ -501,8 +532,11 @@ static int eth_nxp_enet_qos_mac_init(const struct device *dev)
501532
return ret;
502533
}
503534

504-
/* Random mac therefore overrides local mac that may have been initialized */
505-
if (config->random_mac) {
535+
if (config->mac_addr_source == NXP_ENET_QOS_MAC_ADDR_SOURCE_LOCAL) {
536+
/* Use the mac address provided in the devicetree */
537+
} else if (config->mac_addr_source == NXP_ENET_QOS_MAC_ADDR_SOURCE_UNIQUE) {
538+
nxp_enet_unique_mac(data->mac_addr.addr);
539+
} else {
506540
gen_random_mac(data->mac_addr.addr,
507541
NXP_OUI_BYTE_0, NXP_OUI_BYTE_1, NXP_OUI_BYTE_2);
508542
}
@@ -626,56 +660,59 @@ static const struct ethernet_api api_funcs = {
626660
.set_config = eth_nxp_enet_qos_set_config,
627661
};
628662

629-
#define NXP_ENET_QOS_NODE_HAS_MAC_ADDR_CHECK(n) \
630-
BUILD_ASSERT(NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(n)) || \
631-
DT_INST_PROP(n, zephyr_random_mac_address), \
632-
"MAC address not specified on ENET QOS DT node");
633-
634-
#define NXP_ENET_QOS_CONNECT_IRQS(node_id, prop, idx) \
635-
do { \
636-
IRQ_CONNECT(DT_IRQN_BY_IDX(node_id, idx), \
637-
DT_IRQ_BY_IDX(node_id, idx, priority), \
638-
eth_nxp_enet_qos_mac_isr, \
639-
DEVICE_DT_GET(node_id), \
640-
0); \
641-
irq_enable(DT_IRQN_BY_IDX(node_id, idx)); \
663+
#define NXP_ENET_QOS_NODE_HAS_MAC_ADDR_CHECK(n) \
664+
BUILD_ASSERT(NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(n)) || \
665+
DT_INST_PROP(n, zephyr_random_mac_address) || \
666+
DT_INST_PROP(n, nxp_unique_mac), \
667+
"MAC address not specified on ENET QOS DT node");
668+
669+
#define NXP_ENET_QOS_MAC_ADDR_SOURCE(n) \
670+
COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), local_mac_address), \
671+
(NXP_ENET_QOS_MAC_ADDR_SOURCE_LOCAL), \
672+
(COND_CODE_1(DT_INST_PROP(n, zephyr_random_mac_address), \
673+
(NXP_ENET_QOS_MAC_ADDR_SOURCE_RANDOM), \
674+
(COND_CODE_1(DT_INST_PROP(n, nxp_unique_mac), \
675+
(NXP_ENET_QOS_MAC_ADDR_SOURCE_UNIQUE), \
676+
(NXP_ENET_QOS_MAC_ADDR_SOURCE_INVALID))))))
677+
678+
#define NXP_ENET_QOS_CONNECT_IRQS(node_id, prop, idx) \
679+
do { \
680+
IRQ_CONNECT(DT_IRQN_BY_IDX(node_id, idx), DT_IRQ_BY_IDX(node_id, idx, priority), \
681+
eth_nxp_enet_qos_mac_isr, DEVICE_DT_GET(node_id), 0); \
682+
irq_enable(DT_IRQN_BY_IDX(node_id, idx)); \
642683
} while (false);
643684

644-
#define NXP_ENET_QOS_IRQ_CONFIG_FUNC(n) \
645-
static void nxp_enet_qos_##n##_irq_config_func(void) \
646-
{ \
647-
DT_FOREACH_PROP_ELEM(DT_DRV_INST(n), \
648-
interrupt_names, \
649-
NXP_ENET_QOS_CONNECT_IRQS) \
685+
#define NXP_ENET_QOS_IRQ_CONFIG_FUNC(n) \
686+
static void nxp_enet_qos_##n##_irq_config_func(void) \
687+
{ \
688+
DT_FOREACH_PROP_ELEM(DT_DRV_INST(n), interrupt_names, NXP_ENET_QOS_CONNECT_IRQS) \
650689
}
651-
652-
#define NXP_ENET_QOS_DRIVER_STRUCTS_INIT(n) \
653-
static const struct nxp_enet_qos_mac_config enet_qos_##n##_mac_config = { \
654-
.enet_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \
655-
.phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, phy_handle)), \
656-
.base = (enet_qos_t *)DT_REG_ADDR(DT_INST_PARENT(n)), \
657-
.hw_info = { \
658-
.max_frame_len = ENET_QOS_MAX_NORMAL_FRAME_LEN, \
659-
}, \
660-
.irq_config_func = nxp_enet_qos_##n##_irq_config_func, \
661-
.random_mac = DT_INST_PROP(n, zephyr_random_mac_address), \
662-
}; \
663-
\
664-
static struct nxp_enet_qos_mac_data enet_qos_##n##_mac_data = \
665-
{ \
666-
.mac_addr.addr = DT_INST_PROP_OR(n, local_mac_address, {0}), \
690+
#define NXP_ENET_QOS_DRIVER_STRUCTS_INIT(n) \
691+
static const struct nxp_enet_qos_mac_config enet_qos_##n##_mac_config = { \
692+
.enet_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \
693+
.phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, phy_handle)), \
694+
.base = (enet_qos_t *)DT_REG_ADDR(DT_INST_PARENT(n)), \
695+
.hw_info = \
696+
{ \
697+
.max_frame_len = ENET_QOS_MAX_NORMAL_FRAME_LEN, \
698+
}, \
699+
.irq_config_func = nxp_enet_qos_##n##_irq_config_func, \
700+
.mac_addr_source = NXP_ENET_QOS_MAC_ADDR_SOURCE(n), \
701+
}; \
702+
static struct nxp_enet_qos_mac_data enet_qos_##n##_mac_data = { \
703+
.mac_addr.addr = DT_INST_PROP_OR(n, local_mac_address, {0}), \
667704
};
668705

669-
#define NXP_ENET_QOS_DRIVER_INIT(n) \
670-
NXP_ENET_QOS_NODE_HAS_MAC_ADDR_CHECK(n) \
671-
NXP_ENET_QOS_IRQ_CONFIG_FUNC(n) \
706+
#define NXP_ENET_QOS_DRIVER_INIT(n) \
707+
NXP_ENET_QOS_NODE_HAS_MAC_ADDR_CHECK(n) \
708+
NXP_ENET_QOS_IRQ_CONFIG_FUNC(n) \
672709
NXP_ENET_QOS_DRIVER_STRUCTS_INIT(n)
673710

674711
DT_INST_FOREACH_STATUS_OKAY(NXP_ENET_QOS_DRIVER_INIT)
675712

676-
#define NXP_ENET_QOS_MAC_DEVICE_DEFINE(n) \
677-
ETH_NET_DEVICE_DT_INST_DEFINE(n, eth_nxp_enet_qos_mac_init, NULL, \
678-
&enet_qos_##n##_mac_data, &enet_qos_##n##_mac_config, \
679-
CONFIG_ETH_INIT_PRIORITY, &api_funcs, NET_ETH_MTU);
713+
#define NXP_ENET_QOS_MAC_DEVICE_DEFINE(n) \
714+
ETH_NET_DEVICE_DT_INST_DEFINE(n, eth_nxp_enet_qos_mac_init, NULL, \
715+
&enet_qos_##n##_mac_data, &enet_qos_##n##_mac_config, \
716+
CONFIG_ETH_INIT_PRIORITY, &api_funcs, NET_ETH_MTU);
680717

681718
DT_INST_FOREACH_STATUS_OKAY(NXP_ENET_QOS_MAC_DEVICE_DEFINE)

drivers/ethernet/eth_nxp_enet_qos/nxp_enet_qos_priv.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,20 @@ struct nxp_enet_qos_hw_info {
8585
uint16_t max_frame_len;
8686
};
8787

88+
enum mac_address_source {
89+
NXP_ENET_QOS_MAC_ADDR_SOURCE_LOCAL,
90+
NXP_ENET_QOS_MAC_ADDR_SOURCE_RANDOM,
91+
NXP_ENET_QOS_MAC_ADDR_SOURCE_UNIQUE,
92+
NXP_ENET_QOS_MAC_ADDR_SOURCE_INVALID,
93+
};
94+
8895
struct nxp_enet_qos_mac_config {
8996
const struct device *enet_dev;
9097
const struct device *phy_dev;
9198
enet_qos_t *base;
9299
struct nxp_enet_qos_hw_info hw_info;
93100
void (*irq_config_func)(void);
94-
bool random_mac;
101+
enum mac_address_source mac_addr_source;
95102
};
96103

97104
struct nxp_enet_qos_tx_data {

dts/bindings/ethernet/nxp,enet-qos-mac.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,15 @@ properties:
1313

1414
interrupt-names:
1515
required: true
16+
17+
nxp,unique-mac:
18+
type: boolean
19+
description: |
20+
Use part of the unique silicon ID to generate the MAC.
21+
This property will be overridden if the node has
22+
zephyr,random-mac-address or local-mac-address also.
23+
This option is intended for cases where a very low likelihood
24+
that the mac address is the same as another on the network
25+
is sufficient, such as, testing, bringup, demos, etc.
26+
The first 3 bytes will be the freescale OUI and the next
27+
3 bytes will come from the chip's unique ID.

0 commit comments

Comments
 (0)