From 844c273286f328acf0dab5fbd5d864366b4904dc Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Tue, 30 Mar 2021 18:21:14 +0200 Subject: [PATCH] of_net: add mac-address-increment support Lots of embedded devices use the mac-address of other interface extracted from nvmem cells and increments it by one or two. Add two bindings to integrate this and directly use the right mac-address for the interface. Some example are some routers that use the gmac mac-address stored in the art partition and increments it by one for the wifi. mac-address-increment-byte bindings is used to tell what byte of the mac-address has to be increased (if not defined the last byte is increased) and mac-address-increment tells how much the byte decided early has to be increased. Signed-off-by: Ansuel Smith --- drivers/of/of_net.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c @@ -115,27 +115,62 @@ static int of_get_mac_addr_nvmem(struct * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists * but is all zeros. * + * DT can tell the system to increment the mac-address after is extracted by + * using: + * - mac-address-increment-byte to decide what byte to increase + * (if not defined is increased the last byte) + * - mac-address-increment to decide how much to increase. The value WILL + * overflow to other bytes if the increment is over 255 or the total + * increment will exceed 255 of the current byte. + * (example 00:01:02:03:04:ff + 1 == 00:01:02:03:05:00) + * (example 00:01:02:03:04:fe + 5 == 00:01:02:03:05:03) + * * Return: 0 on success and errno in case of error. */ int of_get_mac_address(struct device_node *np, u8 *addr) { + u32 inc_idx, mac_inc, mac_val; int ret; + /* Check first if the increment byte is present and valid. + * If not set assume to increment the last byte if found. + */ + if (of_property_read_u32(np, "mac-address-increment-byte", &inc_idx)) + inc_idx = 5; + if (inc_idx < 3 || inc_idx > 5) + return -EINVAL; + if (!np) return -ENODEV; ret = of_get_mac_addr(np, "mac-address", addr); if (!ret) - return 0; + goto found; ret = of_get_mac_addr(np, "local-mac-address", addr); if (!ret) - return 0; + goto found; ret = of_get_mac_addr(np, "address", addr); if (!ret) - return 0; + goto found; + + ret = of_get_mac_addr_nvmem(np, addr); + if (ret) + return ret; + +found: + if (!of_property_read_u32(np, "mac-address-increment", &mac_inc)) { + /* Convert to a contiguous value */ + mac_val = (addr[3] << 16) + (addr[4] << 8) + addr[5]; + mac_val += mac_inc << 8 * (5-inc_idx); + + /* Apply the incremented value handling overflow case */ + addr[3] = (mac_val >> 16) & 0xff; + addr[4] = (mac_val >> 8) & 0xff; + addr[5] = (mac_val >> 0) & 0xff; + } - return of_get_mac_addr_nvmem(np, addr); + return ret; } EXPORT_SYMBOL(of_get_mac_address); e1828bde5b50bb08205639f6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182