[PATCH v3 1/7] net: mv643xx_eth: add Device Tree bindings
Simon Baatz
gmbnomis at gmail.com
Tue May 21 07:19:31 EST 2013
Hi Sebastian,
On Mon, May 06, 2013 at 05:33:34PM +0200, Sebastian Hesselbarth wrote:
> From: Florian Fainelli <florian at openwrt.org>
>
> This patch adds Device Tree bindings following the already defined
> bindings at Documentation/devicetree/bindings/marvell.txt. The binding
> documentation is also enhanced with new optionnal properties required
> for supporting certain devices (RX/TX queue and SRAM). Since we now have
> proper support for the orion MDIO bus driver, there is no need to fiddle
> around with device tree phandles. PHY-less (MAC connected to switch)
> configurations are supported by not specifying any phy phandle for an
> ethernet node.
>
> Signed-off-by: Florian Fainelli <florian at openwrt.org>
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth at gmail.com>
> ---
> Changelog:
> v2->v3:
> - rebase on top of mv643xx_eth clean-ups
> - do not reparse existing platform_data
> - use managed devm_kzalloc for parsed platform_data
> - use of_property_read_u32 where applicable
> - add phy_node to platform_data
> - use of_connect_phy if DT phy node was found
>
> v1->v2:
> - properly ifdef of_platform_bus_probe with CONFIG_OF
> - handle of_platform_bus_probe errors and cleanup accordingly
> - use of_property_read_u32 where applicable
> - parse "duplex" and "speed" property in PHY-less configuration
>
> Cc: Grant Likely <grant.likely at linaro.org>
> Cc: Rob Herring <rob.herring at calxeda.com>
> Cc: Rob Landley <rob at landley.net>
> Cc: Lennert Buytenhek <buytenh at wantstofly.org>
> Cc: David Miller <davem at davemloft.net>
> Cc: Florian Fainelli <florian at openwrt.org>
> Cc: Arnaud Patard <arnaud.patard at rtp-net.org>
> Cc: Russell King <linux at arm.linux.org.uk>
> Cc: Jason Cooper <jason at lakedaemon.net>
> Cc: Andrew Lunn <andrew at lunn.ch>
> Cc: Jean-Francois Moine <moinejf at free.fr>
> Cc: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
> Cc: Simon Guinot <simon.guinot at sequanux.org>
> Cc: Jamie Lentin <jm at lentin.co.uk>
> Cc: Michael Walle <michael at walle.cc>
> Cc: Eric Hutter <hutter.eric at gmail.com>
> Cc: Joshua Coombs <josh.coombs at gmail.com>
> Cc: Willy Tarreau <w at 1wt.eu>
> Cc: Simon Baatz <gmbnomis at gmail.com>
> Cc: Alan M Butler <alanbutty12 at gmail.com>
> Cc: Nigel Roberts <nigel at nobiscuit.com>
> Cc: Valentin Longchamp <valentin.longchamp at keymile.com>
> Cc: Stefan Peter <s.peter at mpl.ch>
> Cc: Arnaud Ebalard <arno at natisbad.org>
> Cc: Nobuhiro Iwamatsu <iwamatsu at nigauri.org>
> Cc: netdev at vger.kernel.org
> Cc: devicetree-discuss at lists.ozlabs.org
> Cc: linux-doc at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> ---
> Documentation/devicetree/bindings/marvell.txt | 22 +++++-
> drivers/net/ethernet/marvell/mv643xx_eth.c | 108 ++++++++++++++++++++++++-
> include/linux/mv643xx_eth.h | 3 +
> 3 files changed, 128 insertions(+), 5 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/marvell.txt b/Documentation/devicetree/bindings/marvell.txt
> index f7a0da6..73ea12f 100644
> --- a/Documentation/devicetree/bindings/marvell.txt
> +++ b/Documentation/devicetree/bindings/marvell.txt
> @@ -112,11 +112,13 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd.
> Required properties:
> - #address-cells : <1>
> - #size-cells : <0>
> - - compatible : "marvell,mv64360-eth-block"
> + - compatible : "marvell,mv64360-eth-block", "marvell,mv643xx-eth-block"
> - reg : Offset and length of the register set for this block
>
> Optional properties:
> - clocks : Phandle to the clock control device and gate bit
> + - tx-csum-limit : Hardware limit above which transmit checksumming
> + is disabled.
>
> Example Discovery Ethernet block node:
> ethernet-block at 2000 {
> @@ -133,7 +135,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd.
>
> Required properties:
> - device_type : Should be "network".
> - - compatible : Should be "marvell,mv64360-eth".
> + - compatible : Should be "marvell,mv64360-eth", "marvell,mv643xx-eth"
> - reg : Should be <0>, <1>, or <2>, according to which registers
> within the silicon block the device uses.
> - interrupts : <a> where a is the interrupt number for the port.
> @@ -143,6 +145,22 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd.
> controller.
> - local-mac-address : 6 bytes, MAC address
>
> + Optional properties:
> + - clocks : Phandle to the clock control device and gate bit
> + - clock-names : String describing the clock gate bit
> + - speed : Speed to force the link (10, 100, 1000), used when no
> + phy property is defined
> + - duplex : Duplex to force the link (0: half, 1: full), used when no
> + phy property is defined
> + - rx-queue-count : number of RX queues to use
> + - tx-queue-count : number of TX queues to use
> + - rx-queue-size : size of the RX queue (in bytes)
> + - tx-queue-size : size of the TX queue (in bytes)
> + - rx-sram-addr : address of the SRAM for RX path (non 0 means used)
> + - rx-sram-size : size of the SRAM for RX path (non 0 means used)
> + - tx-sram-addr : address of the SRAM for TX path (non 0 means used)
> + - tx-sram-size : size of the SRAM for TX path (non 0 means used)
> +
> Example Discovery Ethernet port node:
> ethernet at 0 {
> device_type = "network";
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index d0afeea..efa5a2f 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -60,6 +60,11 @@
> #include <linux/types.h>
> #include <linux/slab.h>
> #include <linux/clk.h>
> +#include <linux/stringify.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_mdio.h>
> +#include <linux/of_net.h>
>
> static char mv643xx_eth_driver_name[] = "mv643xx_eth";
> static char mv643xx_eth_driver_version[] = "1.4";
> @@ -2450,13 +2455,22 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
> }
> }
>
> +static const struct of_device_id mv643xx_eth_match[] = {
> + { .compatible = "marvell,mv64360-eth" },
> + { .compatible = "marvell,mv643xx-eth" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, mv643xx_eth_match);
> +
> static int mv643xx_eth_shared_probe(struct platform_device *pdev)
> {
> static int mv643xx_eth_version_printed;
> + struct device_node *np = pdev->dev.of_node;
> struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
> struct mv643xx_eth_shared_private *msp;
> const struct mbus_dram_target_info *dram;
> struct resource *res;
> + int tx_csum_limit = 0;
>
> if (!mv643xx_eth_version_printed++)
> pr_notice("MV-643xx 10/100/1000 ethernet driver version %s\n",
> @@ -2485,13 +2499,21 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
> if (dram)
> mv643xx_eth_conf_mbus_windows(msp, dram);
>
> - msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ?
> - pd->tx_csum_limit : 9 * 1024;
> + if (np)
> + of_property_read_u32(np, "tx-csum-limit", &tx_csum_limit);
> + else
> + tx_csum_limit = pd->tx_csum_limit;
> +
> + msp->tx_csum_limit = tx_csum_limit ? tx_csum_limit : 9 * 1024;
> infer_hw_params(msp);
>
> platform_set_drvdata(pdev, msp);
>
> +#ifdef CONFIG_OF
> + return of_platform_bus_probe(np, mv643xx_eth_match, &pdev->dev);
I have tested this on Kirkwood (Sheevaplug eSATA). When using
mv643xx_eth as a module with a built-in mvmdio the GbE port works.
However, when unloading the mv643xx_eth module and loading it again,
the second call to of_platform_bus_probe() results in a warning:
[ 190.542992] WARNING: at fs/sysfs/dir.c:530 sysfs_add_one+0x7c/0xa4()
[ 190.549372] sysfs: cannot create duplicate filename '/devices/ocp.0/f1072000.
ethernet-controller/0.ethernet-port'
(Looks more like a problem of of_platform_bus_probe() than a problem
in the driver?)
> +#else
> return 0;
> +#endif
> }
>
> static int mv643xx_eth_shared_remove(struct platform_device *pdev)
> @@ -2505,12 +2527,20 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static const struct of_device_id mv643xx_eth_shared_match[] = {
> + { .compatible = "marvell,mv64360-eth-block" },
> + { .compatible = "marvell,mv643xx-eth-block" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, mv643xx_eth_shared_match);
> +
> static struct platform_driver mv643xx_eth_shared_driver = {
> .probe = mv643xx_eth_shared_probe,
> .remove = mv643xx_eth_shared_remove,
> .driver = {
> .name = MV643XX_ETH_SHARED_NAME,
> .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(mv643xx_eth_shared_match),
> },
> };
>
> @@ -2669,6 +2699,68 @@ static const struct net_device_ops mv643xx_eth_netdev_ops = {
> #endif
> };
>
> +#ifdef CONFIG_OF
> +static int mv643xx_eth_of_probe(struct platform_device *pdev)
> +{
> + struct mv643xx_eth_platform_data *pd;
> + struct device_node *np = pdev->dev.of_node;
> + struct device_node *shared = of_get_parent(np);
> + const int *prop;
> + const char *mac_addr;
> +
> + if (pdev->dev.platform_data || !pdev->dev.of_node)
> + return 0;
> +
> + pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
> + if (!pd)
> + return -ENOMEM;
> +
> + pdev->dev.platform_data = pd;
> +
> + pd->shared = of_find_device_by_node(shared);
> + if (!pd->shared)
> + return -ENODEV;
> +
> + if (of_property_read_u32(np, "reg", &pd->port_number))
> + return -EINVAL;
> +
> + pd->phy_node = of_parse_phandle(np, "phy", 0);
> + if (!pd->phy_node) {
> + pd->phy_addr = MV643XX_ETH_PHY_NONE;
> +
> + of_property_read_u32(np, "speed", &pd->speed);
> + of_property_read_u32(np, "duplex", &pd->duplex);
> + }
> +
> + mac_addr = of_get_mac_address(np);
> + if (mac_addr)
> + memcpy(pd->mac_addr, mac_addr, ETH_ALEN);
> +
> +#define rx_tx_queue_sram_property(_name) \
> + do { \
> + prop = of_get_property(np, __stringify(_name), NULL); \
> + if (prop) \
> + pd->_name = be32_to_cpup(prop); \
> + } while (0)
> +
> + rx_tx_queue_sram_property(rx_queue_count);
> + rx_tx_queue_sram_property(tx_queue_count);
> + rx_tx_queue_sram_property(rx_queue_size);
> + rx_tx_queue_sram_property(tx_queue_size);
> + rx_tx_queue_sram_property(rx_sram_addr);
> + rx_tx_queue_sram_property(rx_sram_size);
> + rx_tx_queue_sram_property(tx_sram_addr);
> + rx_tx_queue_sram_property(rx_sram_size);
> +
> + return 0;
> +}
> +#else
> +static inline int mv643xx_eth_of_probe(struct platform_device *dev)
> +{
> + return 0;
> +}
> +#endif
> +
> static int mv643xx_eth_probe(struct platform_device *pdev)
> {
> struct mv643xx_eth_platform_data *pd;
> @@ -2677,6 +2769,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
> struct resource *res;
> int err;
>
> + err = mv643xx_eth_of_probe(pdev);
> + if (err)
> + return err;
> +
> pd = pdev->dev.platform_data;
> if (pd == NULL) {
> dev_err(&pdev->dev, "no mv643xx_eth_platform_data\n");
If the clock isn't already enabled (mvmdio and mv643xx_eth both built
as modules), a delay seems to be necessary in mv643xx_eth_probe()
after enabling the clock on my hardware. Otherwise the device hangs.
Andrew found the same in the past (see [1]). udelay(50) seems to be
sufficient in my case.
> @@ -2717,7 +2813,12 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
> netif_set_real_num_rx_queues(dev, mp->rxq_count);
>
> if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {
> - mp->phy = phy_scan(mp, pd->phy_addr);
> + if (pd->phy_node)
> + mp->phy = of_phy_connect(mp->dev, pd->phy_node,
> + mv643xx_eth_adjust_link, 0,
> + PHY_INTERFACE_MODE_GMII);
of_phy_connect() returns NULL in case of an error and no ERR_PTR.
- Simon
[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-June/103521.html
More information about the devicetree-discuss
mailing list