Commit c8f8207c authored by David S. Miller's avatar David S. Miller

Merge branch 'of_net-Add-NVMEM-support-to-of_get_mac_address'

Petr Štetiar says:

====================
of_net: Add NVMEM support to of_get_mac_address

this patch series is a continuation of my previous attempt[1], where I've
tried to wire MTD layer into of_get_mac_address, so it would be possible to
load MAC addresses from various NVMEMs as EEPROMs etc.

Predecessor of this patch which used directly MTD layer has originated in
OpenWrt some time ago and supports already about 497 use cases in 357
device tree files.

During the review process of my 1st attempt I was told, that I shouldn't be
using MTD directly, but that I should rather use new NVMEM subsystem and
during the review process of v2 I was told, that I should handle
EPROBE_DEFFER error as well, during the review process of v3 I was told,
that returning pointer/NULL/ERR_PTR is considered as wrong API design, so
this v4 patch series tries to accommodate all this previous remarks.

First patch is wiring NVMEM support directly into of_get_mac_address as
it's obvious, that adding support for NVMEM into every other driver would
mean adding a lot of repetitive code. This patch allows us to configure MAC
addresses in various devices like ethernet and wireless adapters directly
from of_get_mac_address, which is used by quite a lot of drivers in the
tree already.

Second patch is simply updating documentation with NVMEM bits, and cleaning
up all current binding documentation referencing any of the MAC address
related properties.

Third and fourth patches are simply removing duplicate NVMEM code which is
no longer needed as the first patch has wired NVMEM support directly into
of_get_mac_address.

Patches 5-10 are converting all current users of of_get_mac_address to the
new ERR_PTR encoded error value, as of_get_mac_address could now return
valid pointer, NULL and ERR_PTR.

Just for a better picture, this patch series and one simple patch[2] on top
of it, allows me to configure 8Devices Carambola2 board's MAC addresses
with following DTS (simplified):

 &spi {
 	flash@0 {
 		partitions {
			art: partition@ff0000 {
				label = "art";
				reg = <0xff0000 0x010000>;
				read-only;

				nvmem-cells {
					compatible = "nvmem-cells";
					#address-cells = <1>;
					#size-cells = <1>;

					eth0_addr: eth-mac-addr@0 {
						reg = <0x0 0x6>;
					};

					eth1_addr: eth-mac-addr@6 {
						reg = <0x6 0x6>;
					};

					wmac_addr: wifi-mac-addr@1002 {
						reg = <0x1002 0x6>;
					};
				};
			};
		};
	};
 };

 &eth0 {
	nvmem-cells = <&eth0_addr>;
	nvmem-cell-names = "mac-address";
 };

 &eth1 {
	nvmem-cells = <&eth1_addr>;
	nvmem-cell-names = "mac-address";
 };

 &wmac {
	nvmem-cells = <&wmac_addr>;
	nvmem-cell-names = "mac-address";
 };

1. https://patchwork.ozlabs.org/patch/1086628/
2. https://patchwork.ozlabs.org/patch/890738/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8ef5cc4f ea168cdf
......@@ -46,9 +46,8 @@ Required properties:
- reg: phy id used to communicate to phy.
- device_type: Must be "ethernet-phy".
Optional properties:
- local-mac-address: See ethernet.txt in the same directory.
- max-frame-size: See ethernet.txt in the same directory.
The MAC address will be determined using the optional properties defined in
ethernet.txt.
Example:
......
......@@ -24,8 +24,6 @@ Required properties:
- phy-mode: See ethernet.txt file in the same directory
Optional properties:
- mac-address: mac address to be assigned to the device. Can be overridden
by UEFI.
- dma-coherent: Present if dma operations are coherent
- amd,per-channel-interrupt: Indicates that Rx and Tx complete will generate
a unique interrupt for each DMA channel - this requires an additional
......@@ -34,6 +32,9 @@ Optional properties:
0 - 1GbE and 10GbE (default)
1 - 2.5GbE and 10GbE
The MAC address will be determined using the optional properties defined in
ethernet.txt.
The following optional properties are represented by an array with each
value corresponding to a particular speed. The first array value represents
the setting for the 1GbE speed, the second value for the 2.5GbE speed and
......
......@@ -16,8 +16,8 @@ Required properties:
registers (required for Northstar2)
- interrupts: Interrupt number
Optional properties:
- mac-address: See ethernet.txt file in the same directory
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Examples:
......
......@@ -49,10 +49,12 @@ Required properties:
Optional properties:
- dual_emac_res_vlan : Specifies VID to be used to segregate the ports
- mac-address : See ethernet.txt file in the same directory
- phy_id : Specifies slave phy id (deprecated, use phy-handle)
- phy-handle : See ethernet.txt file in the same directory
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Slave sub-nodes:
- fixed-link : See fixed-link.txt file in the same directory
......
......@@ -20,11 +20,12 @@ Required properties:
Optional properties:
- phy-handle: See ethernet.txt file in the same directory.
If absent, davinci_emac driver defaults to 100/FULL.
- nvmem-cells: phandle, reference to an nvmem node for the MAC address
- nvmem-cell-names: string, should be "mac-address" if nvmem is to be used
- ti,davinci-rmii-en: 1 byte, 1 means use RMII
- ti,davinci-no-bd-ram: boolean, does EMAC have BD RAM?
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Example (enbw_cmc board):
eth0: emac@1e20000 {
compatible = "ti,davinci-dm6467-emac";
......
......@@ -65,9 +65,8 @@ properties, described in binding documents:
Documentation/devicetree/bindings/net/fixed-link.txt
for details.
- local-mac-address : See
Documentation/devicetree/bindings/net/ethernet.txt
for details.
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Example
......
......@@ -4,12 +4,14 @@ NOTE: All 'phy*' properties documented below are Ethernet specific. For the
generic PHY 'phys' property, see
Documentation/devicetree/bindings/phy/phy-bindings.txt.
- local-mac-address: array of 6 bytes, specifies the MAC address that was
assigned to the network device;
- mac-address: array of 6 bytes, specifies the MAC address that was last used by
the boot program; should be used in cases where the MAC address assigned to
the device by the boot program is different from the "local-mac-address"
property;
- local-mac-address: array of 6 bytes, specifies the MAC address that was
assigned to the network device;
- nvmem-cells: phandle, reference to an nvmem node for the MAC address
- nvmem-cell-names: string, should be "mac-address" if nvmem is to be used
- max-speed: number, specifies maximum speed in Mbit/s supported by the device;
- max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than
the maximum frame size (there's contradiction in the Devicetree
......
......@@ -14,7 +14,6 @@ Required properties:
the PHY reset signal(optional).
- reset-names: should contain the reset signal name "mac"(required)
and "phy"(optional).
- mac-address: see ethernet.txt [1].
- phy-mode: see ethernet.txt [1].
- phy-handle: see ethernet.txt [1].
- hisilicon,phy-reset-delays-us: triplet of delays if PHY reset signal given.
......@@ -22,6 +21,9 @@ Required properties:
The 2nd cell is reset pulse in micro seconds.
The 3rd cell is reset post-delay in micro seconds.
The MAC address will be determined using the optional properties
defined in ethernet.txt[1].
[1] Documentation/devicetree/bindings/net/ethernet.txt
Example:
......
......@@ -18,7 +18,6 @@ Required properties:
- #size-cells: must be <0>.
- phy-mode: see ethernet.txt [1].
- phy-handle: see ethernet.txt [1].
- mac-address: see ethernet.txt [1].
- clocks: clock phandle and specifier pair.
- clock-names: contain the clock name "mac_core"(required) and "mac_ifc"(optional).
- resets: should contain the phandle to the MAC core reset signal(optional),
......@@ -31,6 +30,9 @@ Required properties:
The 2nd cell is reset pulse in micro seconds.
The 3rd cell is reset post-delay in micro seconds.
The MAC address will be determined using the properties defined in
ethernet.txt[1].
- PHY subnode: inherits from phy binding [2]
[1] Documentation/devicetree/bindings/net/ethernet.txt
......
......@@ -135,14 +135,14 @@ Optional properties:
are swapped. The netcp driver will swap the two DWORDs
back to the proper order when this property is set to 2
when it obtains the mac address from efuse.
- local-mac-address: the driver is designed to use the of_get_mac_address api
only if efuse-mac is 0. When efuse-mac is 0, the MAC
address is obtained from local-mac-address. If this
attribute is not present, then the driver will use a
random MAC address.
- "netcp-device label": phandle to the device specification for each of NetCP
sub-module attached to this interface.
The MAC address will be determined using the optional properties defined in
ethernet.txt, as provided by the of_get_mac_address API and only if efuse-mac
is set to 0. If any of the optional MAC address properties are not present,
then the driver will use random MAC address.
Example binding:
netcp: netcp@2000000 {
......
......@@ -26,9 +26,8 @@ Required properties:
Optional elements: 'tsu_clk'
- clocks: Phandles to input clocks.
Optional properties:
- nvmem-cells: phandle, reference to an nvmem node for the MAC address
- nvmem-cell-names: string, should be "mac-address" if nvmem is to be used
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Optional properties for PHY child node:
- reset-gpios : Should specify the gpio for phy reset
......
......@@ -11,7 +11,9 @@ Optional properties:
- #address-cells: must be 1 when using sub-nodes.
- #size-cells: must be 0 when using sub-nodes.
- phy-handle: see ethernet.txt file in the same directory.
- local-mac-address: see ethernet.txt file in the same directory.
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Sub-nodes:
Each PHY can be represented as a sub-node. This is not mandatory.
......
......@@ -21,8 +21,9 @@ Optional properties:
- spi-max-frequency: Maximum frequency of the SPI bus when accessing the ENC28J60.
According to the ENC28J80 datasheet, the chip allows a maximum of 20 MHz, however,
board designs may need to limit this value.
- local-mac-address: See ethernet.txt in the same directory.
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Example (for NXP i.MX28 with pin control stuff for GPIO irq):
......
......@@ -7,9 +7,8 @@ The Device Tree properties, if present, override the OTP and EEPROM.
Required properties:
- compatible: Should be one of "usb424,7800", "usb424,7801" or "usb424,7850".
Optional properties:
- local-mac-address: see ethernet.txt
- mac-address: see ethernet.txt
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Optional properties of the embedded PHY:
- microchip,led-modes: a 0..4 element vector, with each element configuring
......
......@@ -23,7 +23,6 @@ Optional properties:
Numbers smaller than 1000000 or greater than 16000000
are invalid. Missing the property will set the SPI
frequency to 8000000 Hertz.
- local-mac-address : see ./ethernet.txt
- qca,legacy-mode : Set the SPI data transfer of the QCA7000 to legacy mode.
In this mode the SPI master must toggle the chip select
between each data word. In burst mode these gaps aren't
......@@ -31,6 +30,9 @@ Optional properties:
the QCA7000 is setup via GPIO pin strapping. If the
property is missing the driver defaults to burst mode.
The MAC address will be determined using the optional properties
defined in ethernet.txt.
SPI Example:
/* Freescale i.MX28 SPI master*/
......
......@@ -21,10 +21,12 @@ Required properties:
range.
Optional properties:
- mac-address: 6 bytes, mac address
- max-frame-size: Maximum Transfer Unit (IEEE defined MTU), rather
than the maximum frame size.
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Example:
aliases {
......
......@@ -103,8 +103,6 @@ Required properties:
Optional properties:
- dma-coherent: Present if dma operations are coherent
- mac-address: See ethernet.txt in the same directory
- local-mac-address: See ethernet.txt in the same directory
- phy-reset-gpios: Phandle and specifier for any GPIO used to reset the PHY.
See ../gpio/gpio.txt.
- snps,en-lpi: If present it enables use of the AXI low-power interface
......@@ -133,6 +131,9 @@ Optional properties:
- device_type: Must be "ethernet-phy".
- fixed-mode device tree subnode: see fixed-link.txt in the same directory
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Examples:
ethernet2@40010000 {
clock-names = "phy_ref_clk", "apb_pclk";
......
......@@ -31,8 +31,8 @@ Required properties:
- socionext,syscon-phy-mode: A phandle to syscon with one argument
that configures phy mode. The argument is the ID of MAC instance.
Optional properties:
- local-mac-address: See ethernet.txt in the same directory.
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Required subnode:
- mdio: A container for child nodes representing phy nodes.
......
......@@ -26,11 +26,12 @@ Required properties:
Optional properties: (See ethernet.txt file in the same directory)
- dma-coherent: Boolean property, must only be present if memory
accesses performed by the device are cache coherent.
- local-mac-address: See ethernet.txt in the same directory.
- mac-address: See ethernet.txt in the same directory.
- max-speed: See ethernet.txt in the same directory.
- max-frame-size: See ethernet.txt in the same directory.
The MAC address will be determined using the optional properties
defined in ethernet.txt.
Example:
eth0: ethernet@522d0000 {
compatible = "socionext,synquacer-netsec";
......
......@@ -13,11 +13,12 @@ properties:
Optional properties:
- mac-address: See ethernet.txt in the parent directory
- local-mac-address: See ethernet.txt in the parent directory
- ieee80211-freq-limit: See ieee80211.txt
- mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data
The driver is using of_get_mac_address API, so the MAC address can be as well
be set with corresponding optional properties defined in net/ethernet.txt.
Optional nodes:
- led: Properties for a connected LED
Optional properties:
......
......@@ -34,9 +34,9 @@ Optional properties:
ath9k wireless chip (in this case the calibration /
EEPROM data will be loaded from userspace using the
kernel firmware loader).
- mac-address: See ethernet.txt in the parent directory
- local-mac-address: See ethernet.txt in the parent directory
The MAC address will be determined using the optional properties defined in
net/ethernet.txt.
In this example, the node is defined as child node of the PCI controller:
&pci0 {
......
......@@ -92,7 +92,8 @@ static void __init kirkwood_dt_eth_fixup(void)
continue;
/* skip disabled nodes or nodes with valid MAC address*/
if (!of_device_is_available(pnp) || of_get_mac_address(np))
if (!of_device_is_available(pnp) ||
!IS_ERR(of_get_mac_address(np)))
goto eth_fixup_skip;
clk = of_clk_get(pnp, 0);
......
......@@ -105,7 +105,7 @@ static int __init tsi108_eth_of_init(void)
}
mac_addr = of_get_mac_address(np);
if (mac_addr)
if (!IS_ERR(mac_addr))
memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
ph = of_get_property(np, "mdio-handle", NULL);
......
......@@ -4137,16 +4137,14 @@ static int macb_probe(struct platform_device *pdev)
bp->rx_intr_mask |= MACB_BIT(RXUBR);
mac = of_get_mac_address(np);
if (mac) {
if (PTR_ERR(mac) == -EPROBE_DEFER) {
err = -EPROBE_DEFER;
goto err_out_free_netdev;
} else if (!IS_ERR(mac)) {
ether_addr_copy(bp->dev->dev_addr, mac);
} else {
err = nvmem_get_mac_address(&pdev->dev, bp->dev->dev_addr);
if (err) {
if (err == -EPROBE_DEFER)
goto err_out_free_netdev;
macb_get_hwaddr(bp);
}
}
err = of_get_phy_mode(np);
if (err < 0)
......
......@@ -1700,7 +1700,7 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
if (!is_valid_ether_addr(pdata->mac_addr)) {
mac_addr = of_get_mac_address(np);
if (mac_addr)
if (!IS_ERR(mac_addr))
ether_addr_copy(pdata->mac_addr, mac_addr);
}
......@@ -1898,16 +1898,12 @@ static int davinci_emac_probe(struct platform_device *pdev)
ether_addr_copy(ndev->dev_addr, priv->mac_addr);
if (!is_valid_ether_addr(priv->mac_addr)) {
/* Try nvmem if MAC wasn't passed over pdata or DT. */
rc = nvmem_get_mac_address(&pdev->dev, priv->mac_addr);
if (rc) {
/* Use random MAC if still none obtained. */
eth_hw_addr_random(ndev);
memcpy(priv->mac_addr, ndev->dev_addr, ndev->addr_len);
dev_warn(&pdev->dev, "using random MAC addr: %pM\n",
priv->mac_addr);
}
}
ndev->netdev_ops = &emac_netdev_ops;
ndev->ethtool_ops = &ethtool_ops;
......
......@@ -774,7 +774,7 @@ static void smsc75xx_init_mac_address(struct usbnet *dev)
/* maybe the boot loader passed the MAC address in devicetree */
mac_addr = of_get_mac_address(dev->udev->dev.of_node);
if (mac_addr) {
if (!IS_ERR(mac_addr)) {
memcpy(dev->net->dev_addr, mac_addr, ETH_ALEN);
return;
}
......
......@@ -917,7 +917,7 @@ static void smsc95xx_init_mac_address(struct usbnet *dev)
/* maybe the boot loader passed the MAC address in devicetree */
mac_addr = of_get_mac_address(dev->udev->dev.of_node);
if (mac_addr) {
if (!IS_ERR(mac_addr)) {
memcpy(dev->net->dev_addr, mac_addr, ETH_ALEN);
return;
}
......
......@@ -642,7 +642,7 @@ static int ath9k_of_init(struct ath_softc *sc)
}
mac = of_get_mac_address(np);
if (mac)
if (!IS_ERR(mac))
ether_addr_copy(common->macaddr, mac);
return 0;
......
......@@ -94,7 +94,7 @@ mt76_eeprom_override(struct mt76_dev *dev)
return;
mac = of_get_mac_address(np);
if (mac)
if (!IS_ERR(mac))
memcpy(dev->macaddr, mac, ETH_ALEN);
#endif
......
......@@ -1007,7 +1007,7 @@ void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr
const char *mac_addr;
mac_addr = of_get_mac_address(rt2x00dev->dev->of_node);
if (mac_addr)
if (!IS_ERR(mac_addr))
ether_addr_copy(eeprom_mac_addr, mac_addr);
if (!is_valid_ether_addr(eeprom_mac_addr)) {
......
......@@ -8,8 +8,10 @@
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
#include <linux/export.h>
#include <linux/device.h>
/**
* of_get_phy_mode - Get phy mode for given device_node
......@@ -47,12 +49,52 @@ static const void *of_get_mac_addr(struct device_node *np, const char *name)
return NULL;
}
static const void *of_get_mac_addr_nvmem(struct device_node *np)
{
int ret;
u8 mac[ETH_ALEN];
struct property *pp;
struct platform_device *pdev = of_find_device_by_node(np);
if (!pdev)
return ERR_PTR(-ENODEV);
ret = nvmem_get_mac_address(&pdev->dev, &mac);
if (ret)
return ERR_PTR(ret);
pp = devm_kzalloc(&pdev->dev, sizeof(*pp), GFP_KERNEL);
if (!pp)
return ERR_PTR(-ENOMEM);
pp->name = "nvmem-mac-address";
pp->length = ETH_ALEN;
pp->value = devm_kmemdup(&pdev->dev, mac, ETH_ALEN, GFP_KERNEL);
if (!pp->value) {
ret = -ENOMEM;
goto free;
}
ret = of_add_property(np, pp);
if (ret)
goto free;
return pp->value;
free:
devm_kfree(&pdev->dev, pp->value);
devm_kfree(&pdev->dev, pp);
return ERR_PTR(ret);
}
/**
* Search the device tree for the best MAC address to use. 'mac-address' is
* checked first, because that is supposed to contain to "most recent" MAC
* address. If that isn't set, then 'local-mac-address' is checked next,
* because that is the default address. If that isn't set, then the obsolete
* 'address' is checked, just in case we're using an old device tree.
* 'address' is checked, just in case we're using an old device tree. If any
* of the above isn't set, then try to get MAC address from nvmem cell named
* 'mac-address'.
*
* Note that the 'address' property is supposed to contain a virtual address of
* the register set, but some DTS files have redefined that property to be the
......@@ -64,6 +106,8 @@ static const void *of_get_mac_addr(struct device_node *np, const char *name)
* addresses. Some older U-Boots only initialized 'local-mac-address'. In
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
* but is all zeros.
*
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
*/
const void *of_get_mac_address(struct device_node *np)
{
......@@ -77,6 +121,10 @@ const void *of_get_mac_address(struct device_node *np)
if (addr)
return addr;
return of_get_mac_addr(np, "address");
addr = of_get_mac_addr(np, "address");
if (addr)
return addr;
return of_get_mac_addr_nvmem(np);
}
EXPORT_SYMBOL(of_get_mac_address);
......@@ -421,7 +421,7 @@ int cvm_oct_common_init(struct net_device *dev)
if (priv->of_node)
mac = of_get_mac_address(priv->of_node);
if (mac)
if (!IS_ERR(mac))
ether_addr_copy(dev->dev_addr, mac);
else
eth_hw_addr_random(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment