diff mbox series

[U-Boot,v4,1/2] dm: mdio: add a uclass for MDIO

Message ID 1530776059-9295-2-git-send-email-make@marvell.com
State Changes Requested
Delegated to: Joe Hershberger
Headers show
Series Add MDIO driver model support | expand

Commit Message

Ken Ma July 5, 2018, 7:34 a.m. UTC
From: Ken Ma <make@marvell.com>

Add a uclass which provides access to MDIO busses and includes
operations required by MDIO.
The implementation is based on the existing mii/phy/mdio data
structures and APIs.
This patch also adds device tree binding for MDIO bus.

Signed-off-by: Ken Ma <make@marvell.com>
Reviewed-by: sjg@chromium.org, joe.hershberger@ni.com
---

Changes in v4:
- Minor updates for comments and Maintainer.

Changes in v3:
- Move mdio uclass implementation to driver/net folder;
- Replace flat-tree functions with livetree functions and update codes
  and comments to be consistent with driver-model codes style;
- Put struct mii_dev to uclass platdata to avoid the mdio alloc and
  let driver model framework to alloc the memroy automatically,
  meanwhile the mii bus link initialization is added.

Changes in v2:
- Fix error printing:
- Change some debug to pr_err;
- mii bus has no parent member and it is not a udevice, so dev_err
  is changed to pr_err for mii bus error printings.

 MAINTAINERS                               |   1 +
 doc/device-tree-bindings/net/mdio-bus.txt |  54 ++++++++++++++
 drivers/Kconfig                           |   2 +
 drivers/net/Makefile                      |   1 +
 drivers/net/mdio/Kconfig                  |  18 +++++
 drivers/net/mdio/Makefile                 |   6 ++
 drivers/net/mdio/mdio-uclass.c            | 112 ++++++++++++++++++++++++++++++
 include/dm/uclass-id.h                    |   1 +
 include/net/mdio.h                        |  62 +++++++++++++++++
 9 files changed, 257 insertions(+)
 create mode 100644 doc/device-tree-bindings/net/mdio-bus.txt
 create mode 100644 drivers/net/mdio/Kconfig
 create mode 100644 drivers/net/mdio/Makefile
 create mode 100644 drivers/net/mdio/mdio-uclass.c
 create mode 100644 include/net/mdio.h

Comments

Stefan Roese July 5, 2018, 7:48 a.m. UTC | #1
On 05.07.2018 09:34, make@marvell.com wrote:
> From: Ken Ma <make@marvell.com>
> 
> Add a uclass which provides access to MDIO busses and includes
> operations required by MDIO.
> The implementation is based on the existing mii/phy/mdio data
> structures and APIs.
> This patch also adds device tree binding for MDIO bus.
> 
> Signed-off-by: Ken Ma <make@marvell.com>
> Reviewed-by: sjg@chromium.org, joe.hershberger@ni.com
> ---
> 
> Changes in v4:
> - Minor updates for comments and Maintainer.
> 
> Changes in v3:
> - Move mdio uclass implementation to driver/net folder;
> - Replace flat-tree functions with livetree functions and update codes
>    and comments to be consistent with driver-model codes style;
> - Put struct mii_dev to uclass platdata to avoid the mdio alloc and
>    let driver model framework to alloc the memroy automatically,
>    meanwhile the mii bus link initialization is added.
> 
> Changes in v2:
> - Fix error printing:
> - Change some debug to pr_err;
> - mii bus has no parent member and it is not a udevice, so dev_err
>    is changed to pr_err for mii bus error printings.
> 
>   MAINTAINERS                               |   1 +
>   doc/device-tree-bindings/net/mdio-bus.txt |  54 ++++++++++++++
>   drivers/Kconfig                           |   2 +
>   drivers/net/Makefile                      |   1 +
>   drivers/net/mdio/Kconfig                  |  18 +++++
>   drivers/net/mdio/Makefile                 |   6 ++
>   drivers/net/mdio/mdio-uclass.c            | 112 ++++++++++++++++++++++++++++++
>   include/dm/uclass-id.h                    |   1 +
>   include/net/mdio.h                        |  62 +++++++++++++++++
>   9 files changed, 257 insertions(+)
>   create mode 100644 doc/device-tree-bindings/net/mdio-bus.txt
>   create mode 100644 drivers/net/mdio/Kconfig
>   create mode 100644 drivers/net/mdio/Makefile
>   create mode 100644 drivers/net/mdio/mdio-uclass.c
>   create mode 100644 include/net/mdio.h

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan
Michal Simek July 9, 2018, 8:05 a.m. UTC | #2
On 5.7.2018 09:34, make@marvell.com wrote:
> From: Ken Ma <make@marvell.com>
> 
> Add a uclass which provides access to MDIO busses and includes
> operations required by MDIO.
> The implementation is based on the existing mii/phy/mdio data
> structures and APIs.
> This patch also adds device tree binding for MDIO bus.
> 
> Signed-off-by: Ken Ma <make@marvell.com>
> Reviewed-by: sjg@chromium.org, joe.hershberger@ni.com
> ---
> 
> Changes in v4:
> - Minor updates for comments and Maintainer.
> 
> Changes in v3:
> - Move mdio uclass implementation to driver/net folder;
> - Replace flat-tree functions with livetree functions and update codes
>   and comments to be consistent with driver-model codes style;
> - Put struct mii_dev to uclass platdata to avoid the mdio alloc and
>   let driver model framework to alloc the memroy automatically,
>   meanwhile the mii bus link initialization is added.
> 
> Changes in v2:
> - Fix error printing:
> - Change some debug to pr_err;
> - mii bus has no parent member and it is not a udevice, so dev_err
>   is changed to pr_err for mii bus error printings.
> 
>  MAINTAINERS                               |   1 +
>  doc/device-tree-bindings/net/mdio-bus.txt |  54 ++++++++++++++
>  drivers/Kconfig                           |   2 +
>  drivers/net/Makefile                      |   1 +
>  drivers/net/mdio/Kconfig                  |  18 +++++
>  drivers/net/mdio/Makefile                 |   6 ++
>  drivers/net/mdio/mdio-uclass.c            | 112 ++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h                    |   1 +
>  include/net/mdio.h                        |  62 +++++++++++++++++
>  9 files changed, 257 insertions(+)
>  create mode 100644 doc/device-tree-bindings/net/mdio-bus.txt
>  create mode 100644 drivers/net/mdio/Kconfig
>  create mode 100644 drivers/net/mdio/Makefile
>  create mode 100644 drivers/net/mdio/mdio-uclass.c
>  create mode 100644 include/net/mdio.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 642c448..07f7c66 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -432,6 +432,7 @@ M:	Joe Hershberger <joe.hershberger@ni.com>
>  S:	Maintained
>  T:	git git://git.denx.de/u-boot-net.git
>  F:	drivers/net/
> +F:	drivers/net/mdio/
>  F:	net/
>  
>  NIOS
> diff --git a/doc/device-tree-bindings/net/mdio-bus.txt b/doc/device-tree-bindings/net/mdio-bus.txt
> new file mode 100644
> index 0000000..68d8b25
> --- /dev/null
> +++ b/doc/device-tree-bindings/net/mdio-bus.txt
> @@ -0,0 +1,54 @@
> +MDIO (Management Data Input/Output) busses
> +
> +MDIO busses can be described with a node for the MDIO master device
> +and a set of child nodes for each phy on the bus.
> +
> +The MDIO node requires the following properties:
> +- #address-cells  - number of cells required to define phy address on
> +                    the MDIO bus.
> +- #size-cells     - should be zero.
> +- compatible      - name of MDIO bus controller following generic names
> +                    recommended practice.
> +- reg	          - address and length of the MDIO register.
> +
> +Optional property:
> +- mdio-name       - MDIO bus name
> +
> +The child nodes of the MDIO driver are the individual PHY devices
> +connected to this MDIO bus. They must have a "reg" property given the
> +PHY address on the MDIO bus.
> +- reg             - (required) phy address in MDIO bus.
> +
> +Example for cp110 MDIO node at the SoC level:
> +	cp0_mdio: mdio@12a200 {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		compatible = "marvell,orion-mdio";
> +		reg = <0x12a200 0x10>;
> +		mdio-name = "cp0-mdio";
> +	};
> +
> +	cp0_xmdio: mdio@12a600 {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		compatible = "marvell,xmdio";
> +		reg = <0x12a600 0x200>;
> +		mdio-name = "cp0-xmdio";
> +	};
> +
> +And at the board level, example for armada-8040-mcbin board:
> +	&cp0_mdio {
> +		ge_phy: ethernet-phy@0 {
> +			reg = <0>;
> +		};
> +	};
> +
> +	&cp0_xmdio {
> +		phy0: ethernet-phy@0 {
> +			reg = <0>;
> +		};
> +
> +		phy8: ethernet-phy@8 {
> +			reg = <8>;
> +		};
> +	};

this binding should be in separate patch and it is not align with what
it is in the kernel. mdio-name is not there. You should send a patch to
kernel.

Thanks,
Michal
Joe Hershberger July 9, 2018, 9:05 p.m. UTC | #3
On Thu, Jul 5, 2018 at 2:34 AM,  <make@marvell.com> wrote:
> From: Ken Ma <make@marvell.com>
>
> Add a uclass which provides access to MDIO busses and includes
> operations required by MDIO.
> The implementation is based on the existing mii/phy/mdio data
> structures and APIs.
> This patch also adds device tree binding for MDIO bus.
>
> Signed-off-by: Ken Ma <make@marvell.com>
> Reviewed-by: sjg@chromium.org, joe.hershberger@ni.com
> ---
>
> Changes in v4:
> - Minor updates for comments and Maintainer.
>
> Changes in v3:
> - Move mdio uclass implementation to driver/net folder;
> - Replace flat-tree functions with livetree functions and update codes
>   and comments to be consistent with driver-model codes style;
> - Put struct mii_dev to uclass platdata to avoid the mdio alloc and
>   let driver model framework to alloc the memroy automatically,
>   meanwhile the mii bus link initialization is added.
>
> Changes in v2:
> - Fix error printing:
> - Change some debug to pr_err;
> - mii bus has no parent member and it is not a udevice, so dev_err
>   is changed to pr_err for mii bus error printings.
>
>  MAINTAINERS                               |   1 +
>  doc/device-tree-bindings/net/mdio-bus.txt |  54 ++++++++++++++
>  drivers/Kconfig                           |   2 +
>  drivers/net/Makefile                      |   1 +
>  drivers/net/mdio/Kconfig                  |  18 +++++
>  drivers/net/mdio/Makefile                 |   6 ++
>  drivers/net/mdio/mdio-uclass.c            | 112 ++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h                    |   1 +
>  include/net/mdio.h                        |  62 +++++++++++++++++
>  9 files changed, 257 insertions(+)
>  create mode 100644 doc/device-tree-bindings/net/mdio-bus.txt
>  create mode 100644 drivers/net/mdio/Kconfig
>  create mode 100644 drivers/net/mdio/Makefile
>  create mode 100644 drivers/net/mdio/mdio-uclass.c
>  create mode 100644 include/net/mdio.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 642c448..07f7c66 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -432,6 +432,7 @@ M:  Joe Hershberger <joe.hershberger@ni.com>
>  S:     Maintained
>  T:     git git://git.denx.de/u-boot-net.git
>  F:     drivers/net/
> +F:     drivers/net/mdio/
>  F:     net/
>
>  NIOS
> diff --git a/doc/device-tree-bindings/net/mdio-bus.txt b/doc/device-tree-bindings/net/mdio-bus.txt
> new file mode 100644
> index 0000000..68d8b25
> --- /dev/null
> +++ b/doc/device-tree-bindings/net/mdio-bus.txt
> @@ -0,0 +1,54 @@
> +MDIO (Management Data Input/Output) busses
> +
> +MDIO busses can be described with a node for the MDIO master device
> +and a set of child nodes for each phy on the bus.
> +
> +The MDIO node requires the following properties:
> +- #address-cells  - number of cells required to define phy address on
> +                    the MDIO bus.
> +- #size-cells     - should be zero.
> +- compatible      - name of MDIO bus controller following generic names
> +                    recommended practice.
> +- reg            - address and length of the MDIO register.
> +
> +Optional property:
> +- mdio-name       - MDIO bus name
> +
> +The child nodes of the MDIO driver are the individual PHY devices
> +connected to this MDIO bus. They must have a "reg" property given the
> +PHY address on the MDIO bus.
> +- reg             - (required) phy address in MDIO bus.
> +
> +Example for cp110 MDIO node at the SoC level:
> +       cp0_mdio: mdio@12a200 {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               compatible = "marvell,orion-mdio";
> +               reg = <0x12a200 0x10>;
> +               mdio-name = "cp0-mdio";
> +       };
> +
> +       cp0_xmdio: mdio@12a600 {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               compatible = "marvell,xmdio";
> +               reg = <0x12a600 0x200>;
> +               mdio-name = "cp0-xmdio";
> +       };
> +
> +And at the board level, example for armada-8040-mcbin board:
> +       &cp0_mdio {
> +               ge_phy: ethernet-phy@0 {
> +                       reg = <0>;
> +               };
> +       };
> +
> +       &cp0_xmdio {
> +               phy0: ethernet-phy@0 {
> +                       reg = <0>;
> +               };
> +
> +               phy8: ethernet-phy@8 {
> +                       reg = <8>;
> +               };
> +       };
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 9e21b28..0e0982c 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -54,6 +54,8 @@ source "drivers/mtd/Kconfig"
>
>  source "drivers/net/Kconfig"
>
> +source "drivers/net/mdio/Kconfig"

Please put 'source "drivers/net/mdio/Kconfig"' in drivers/net/Kconfig.

>  source "drivers/nvme/Kconfig"
>
>  source "drivers/pci/Kconfig"
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 584bfdf..1cda03f 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -70,3 +70,4 @@ obj-$(CONFIG_VSC9953) += vsc9953.o
>  obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
>  obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
>  obj-$(CONFIG_FSL_PFE) += pfe_eth/
> +obj-$(CONFIG_MDIO) += mdio/
> diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
> new file mode 100644
> index 0000000..c065baa
> --- /dev/null
> +++ b/drivers/net/mdio/Kconfig
> @@ -0,0 +1,18 @@
> +#
> +# MDIO infrastructure and drivers
> +#
> +
> +menu "MDIO Support"
> +
> +config MDIO
> +       bool "Enable MDIO (Management Data Input/Output) drivers"

I think it would be smart to mention driver model for now, since many
other drivers have MDIO support enabled without this. We can later
remove that from the text.

> +       depends on DM
> +       help
> +         Enable driver model for MDIO access.
> +         Drivers provide methods to management data
> +         Input/Output.
> +         MDIO uclass provides interfaces to get mdio
> +         udevice or mii bus from its child phy node or
> +         an ethernet udevice which the phy belongs to.
> +
> +endmenu
> diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
> new file mode 100644
> index 0000000..45ae502
> --- /dev/null
> +++ b/drivers/net/mdio/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright (C) 2018 Marvell International Ltd.
> +# Author: Ken Ma<make@marvell.com>
> +
> +obj-$(CONFIG_MDIO) += mdio-uclass.o
> diff --git a/drivers/net/mdio/mdio-uclass.c b/drivers/net/mdio/mdio-uclass.c
> new file mode 100644
> index 0000000..ad4bc8f
> --- /dev/null
> +++ b/drivers/net/mdio/mdio-uclass.c
> @@ -0,0 +1,112 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018 Marvell International Ltd.
> + * Author: Ken Ma<make@marvell.com>
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>

You shouldn't need this.

> +#include <errno.h>
> +#include <dm.h>
> +#include <dm/uclass.h>
> +#include <dm/uclass-internal.h>
> +#include <miiphy.h>
> +#include <net/mdio.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int mdio_mii_bus_get(struct udevice *mdio_dev, struct mii_dev **busp)
> +{
> +       *busp = (struct mii_dev *)dev_get_uclass_platdata(mdio_dev);
> +
> +       return 0;
> +}
> +
> +int mdio_device_get_from_phy(ofnode phy_node, struct udevice **devp)
> +{
> +       ofnode mdio_node;
> +
> +       mdio_node = ofnode_get_parent(phy_node);
> +       return uclass_get_device_by_ofnode(UCLASS_MDIO, mdio_node, devp);
> +}
> +
> +int mdio_mii_bus_get_from_phy(ofnode phy_node, struct mii_dev **busp)
> +{
> +       struct udevice *mdio_dev;
> +       int ret;
> +
> +       ret = mdio_device_get_from_phy(phy_node, &mdio_dev);
> +       if (ret)
> +               return ret;
> +
> +       *busp = (struct mii_dev *)dev_get_uclass_platdata(mdio_dev);
> +
> +       return 0;
> +}
> +
> +int mdio_device_get_from_eth(struct udevice *eth, struct udevice **devp)
> +{
> +       struct ofnode_phandle_args phy_args;
> +       int ret;
> +
> +       ret = dev_read_phandle_with_args(eth, "phy", NULL, 0, 0, &phy_args);
> +       if (!ret)
> +               return mdio_device_get_from_phy(phy_args.node, devp);
> +
> +       /*
> +        * If there is no phy reference under the ethernet fdt node,
> +        * it is not an error since the ethernet device may do not use
> +        * mode; so in this case, the output mdio device pointer is set
> +        * as NULL.
> +        */
> +       *devp = NULL;
> +       return 0;
> +}
> +
> +int mdio_mii_bus_get_from_eth(struct udevice *eth, struct mii_dev **busp)
> +{
> +       struct udevice *mdio_dev;
> +       int ret;
> +
> +       ret = mdio_device_get_from_eth(eth, &mdio_dev);
> +       if (ret)
> +               return ret;
> +
> +       if (mdio_dev)
> +               *busp = (struct mii_dev *)dev_get_uclass_platdata(mdio_dev);
> +       else
> +               *busp = NULL;
> +
> +       return 0;
> +}
> +
> +static int mdio_uclass_pre_probe(struct udevice *dev)
> +{
> +       struct mii_dev *bus = (struct mii_dev *)dev_get_uclass_platdata(dev);
> +       const char *name;
> +
> +       /* initialize mii_dev struct fields,  implement mdio_alloc() setup */
> +       INIT_LIST_HEAD(&bus->link);
> +
> +       name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
> +                          "mdio-name", NULL);

Please use dev_read_string() here.

> +       if (name)
> +               strncpy(bus->name, name, MDIO_NAME_LEN);
> +
> +       return 0;
> +}
> +
> +static int mdio_uclass_post_probe(struct udevice *dev)
> +{
> +       struct mii_dev *bus = (struct mii_dev *)dev_get_uclass_platdata(dev);
> +
> +       return mdio_register(bus);
> +}
> +
> +UCLASS_DRIVER(mdio) = {
> +       .id             = UCLASS_MDIO,
> +       .name           = "mdio",
> +       .pre_probe      = mdio_uclass_pre_probe,
> +       .post_probe     = mdio_uclass_post_probe,
> +       .per_device_platdata_auto_alloc_size = sizeof(struct mii_dev),
> +};

<snip>
Bin Meng July 25, 2018, 12:34 p.m. UTC | #4
Hello,

On Tue, Jul 10, 2018 at 5:05 AM, Joe Hershberger <joe.hershberger@ni.com> wrote:
> On Thu, Jul 5, 2018 at 2:34 AM,  <make@marvell.com> wrote:
>> From: Ken Ma <make@marvell.com>
>>
>> Add a uclass which provides access to MDIO busses and includes
>> operations required by MDIO.
>> The implementation is based on the existing mii/phy/mdio data
>> structures and APIs.
>> This patch also adds device tree binding for MDIO bus.
>>
>> Signed-off-by: Ken Ma <make@marvell.com>
>> Reviewed-by: sjg@chromium.org, joe.hershberger@ni.com
>> ---
>>
>> Changes in v4:
>> - Minor updates for comments and Maintainer.
>>
>> Changes in v3:
>> - Move mdio uclass implementation to driver/net folder;
>> - Replace flat-tree functions with livetree functions and update codes
>>   and comments to be consistent with driver-model codes style;
>> - Put struct mii_dev to uclass platdata to avoid the mdio alloc and
>>   let driver model framework to alloc the memroy automatically,
>>   meanwhile the mii bus link initialization is added.
>>
>> Changes in v2:
>> - Fix error printing:
>> - Change some debug to pr_err;
>> - mii bus has no parent member and it is not a udevice, so dev_err
>>   is changed to pr_err for mii bus error printings.
>>
>>  MAINTAINERS                               |   1 +
>>  doc/device-tree-bindings/net/mdio-bus.txt |  54 ++++++++++++++
>>  drivers/Kconfig                           |   2 +
>>  drivers/net/Makefile                      |   1 +
>>  drivers/net/mdio/Kconfig                  |  18 +++++
>>  drivers/net/mdio/Makefile                 |   6 ++
>>  drivers/net/mdio/mdio-uclass.c            | 112 ++++++++++++++++++++++++++++++
>>  include/dm/uclass-id.h                    |   1 +
>>  include/net/mdio.h                        |  62 +++++++++++++++++
>>  9 files changed, 257 insertions(+)
>>  create mode 100644 doc/device-tree-bindings/net/mdio-bus.txt
>>  create mode 100644 drivers/net/mdio/Kconfig
>>  create mode 100644 drivers/net/mdio/Makefile
>>  create mode 100644 drivers/net/mdio/mdio-uclass.c
>>  create mode 100644 include/net/mdio.h
>>

It looks this only supports mdio device via device tree. How about PCI NICs?

Regards,
Bin
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 642c448..07f7c66 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -432,6 +432,7 @@  M:	Joe Hershberger <joe.hershberger@ni.com>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-net.git
 F:	drivers/net/
+F:	drivers/net/mdio/
 F:	net/
 
 NIOS
diff --git a/doc/device-tree-bindings/net/mdio-bus.txt b/doc/device-tree-bindings/net/mdio-bus.txt
new file mode 100644
index 0000000..68d8b25
--- /dev/null
+++ b/doc/device-tree-bindings/net/mdio-bus.txt
@@ -0,0 +1,54 @@ 
+MDIO (Management Data Input/Output) busses
+
+MDIO busses can be described with a node for the MDIO master device
+and a set of child nodes for each phy on the bus.
+
+The MDIO node requires the following properties:
+- #address-cells  - number of cells required to define phy address on
+                    the MDIO bus.
+- #size-cells     - should be zero.
+- compatible      - name of MDIO bus controller following generic names
+                    recommended practice.
+- reg	          - address and length of the MDIO register.
+
+Optional property:
+- mdio-name       - MDIO bus name
+
+The child nodes of the MDIO driver are the individual PHY devices
+connected to this MDIO bus. They must have a "reg" property given the
+PHY address on the MDIO bus.
+- reg             - (required) phy address in MDIO bus.
+
+Example for cp110 MDIO node at the SoC level:
+	cp0_mdio: mdio@12a200 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "marvell,orion-mdio";
+		reg = <0x12a200 0x10>;
+		mdio-name = "cp0-mdio";
+	};
+
+	cp0_xmdio: mdio@12a600 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "marvell,xmdio";
+		reg = <0x12a600 0x200>;
+		mdio-name = "cp0-xmdio";
+	};
+
+And at the board level, example for armada-8040-mcbin board:
+	&cp0_mdio {
+		ge_phy: ethernet-phy@0 {
+			reg = <0>;
+		};
+	};
+
+	&cp0_xmdio {
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+		};
+
+		phy8: ethernet-phy@8 {
+			reg = <8>;
+		};
+	};
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9e21b28..0e0982c 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -54,6 +54,8 @@  source "drivers/mtd/Kconfig"
 
 source "drivers/net/Kconfig"
 
+source "drivers/net/mdio/Kconfig"
+
 source "drivers/nvme/Kconfig"
 
 source "drivers/pci/Kconfig"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 584bfdf..1cda03f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -70,3 +70,4 @@  obj-$(CONFIG_VSC9953) += vsc9953.o
 obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
 obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
 obj-$(CONFIG_FSL_PFE) += pfe_eth/
+obj-$(CONFIG_MDIO) += mdio/
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
new file mode 100644
index 0000000..c065baa
--- /dev/null
+++ b/drivers/net/mdio/Kconfig
@@ -0,0 +1,18 @@ 
+#
+# MDIO infrastructure and drivers
+#
+
+menu "MDIO Support"
+
+config MDIO
+	bool "Enable MDIO (Management Data Input/Output) drivers"
+	depends on DM
+	help
+	  Enable driver model for MDIO access.
+	  Drivers provide methods to management data
+	  Input/Output.
+	  MDIO uclass provides interfaces to get mdio
+	  udevice or mii bus from its child phy node or
+	  an ethernet udevice which the phy belongs to.
+
+endmenu
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
new file mode 100644
index 0000000..45ae502
--- /dev/null
+++ b/drivers/net/mdio/Makefile
@@ -0,0 +1,6 @@ 
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018 Marvell International Ltd.
+# Author: Ken Ma<make@marvell.com>
+
+obj-$(CONFIG_MDIO) += mdio-uclass.o
diff --git a/drivers/net/mdio/mdio-uclass.c b/drivers/net/mdio/mdio-uclass.c
new file mode 100644
index 0000000..ad4bc8f
--- /dev/null
+++ b/drivers/net/mdio/mdio-uclass.c
@@ -0,0 +1,112 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ * Author: Ken Ma<make@marvell.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/uclass.h>
+#include <dm/uclass-internal.h>
+#include <miiphy.h>
+#include <net/mdio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int mdio_mii_bus_get(struct udevice *mdio_dev, struct mii_dev **busp)
+{
+	*busp = (struct mii_dev *)dev_get_uclass_platdata(mdio_dev);
+
+	return 0;
+}
+
+int mdio_device_get_from_phy(ofnode phy_node, struct udevice **devp)
+{
+	ofnode mdio_node;
+
+	mdio_node = ofnode_get_parent(phy_node);
+	return uclass_get_device_by_ofnode(UCLASS_MDIO, mdio_node, devp);
+}
+
+int mdio_mii_bus_get_from_phy(ofnode phy_node, struct mii_dev **busp)
+{
+	struct udevice *mdio_dev;
+	int ret;
+
+	ret = mdio_device_get_from_phy(phy_node, &mdio_dev);
+	if (ret)
+		return ret;
+
+	*busp = (struct mii_dev *)dev_get_uclass_platdata(mdio_dev);
+
+	return 0;
+}
+
+int mdio_device_get_from_eth(struct udevice *eth, struct udevice **devp)
+{
+	struct ofnode_phandle_args phy_args;
+	int ret;
+
+	ret = dev_read_phandle_with_args(eth, "phy", NULL, 0, 0, &phy_args);
+	if (!ret)
+		return mdio_device_get_from_phy(phy_args.node, devp);
+
+	/*
+	 * If there is no phy reference under the ethernet fdt node,
+	 * it is not an error since the ethernet device may do not use
+	 * mode; so in this case, the output mdio device pointer is set
+	 * as NULL.
+	 */
+	*devp = NULL;
+	return 0;
+}
+
+int mdio_mii_bus_get_from_eth(struct udevice *eth, struct mii_dev **busp)
+{
+	struct udevice *mdio_dev;
+	int ret;
+
+	ret = mdio_device_get_from_eth(eth, &mdio_dev);
+	if (ret)
+		return ret;
+
+	if (mdio_dev)
+		*busp = (struct mii_dev *)dev_get_uclass_platdata(mdio_dev);
+	else
+		*busp = NULL;
+
+	return 0;
+}
+
+static int mdio_uclass_pre_probe(struct udevice *dev)
+{
+	struct mii_dev *bus = (struct mii_dev *)dev_get_uclass_platdata(dev);
+	const char *name;
+
+	/* initialize mii_dev struct fields,  implement mdio_alloc() setup */
+	INIT_LIST_HEAD(&bus->link);
+
+	name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
+			   "mdio-name", NULL);
+	if (name)
+		strncpy(bus->name, name, MDIO_NAME_LEN);
+
+	return 0;
+}
+
+static int mdio_uclass_post_probe(struct udevice *dev)
+{
+	struct mii_dev *bus = (struct mii_dev *)dev_get_uclass_platdata(dev);
+
+	return mdio_register(bus);
+}
+
+UCLASS_DRIVER(mdio) = {
+	.id		= UCLASS_MDIO,
+	.name		= "mdio",
+	.pre_probe	= mdio_uclass_pre_probe,
+	.post_probe	= mdio_uclass_post_probe,
+	.per_device_platdata_auto_alloc_size = sizeof(struct mii_dev),
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index d7f9df3..1a85362 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -49,6 +49,7 @@  enum uclass_id {
 	UCLASS_LPC,		/* x86 'low pin count' interface */
 	UCLASS_MAILBOX,		/* Mailbox controller */
 	UCLASS_MASS_STORAGE,	/* Mass storage device */
+	UCLASS_MDIO,		/* Management Data Input/Output (MDIO) device */
 	UCLASS_MISC,		/* Miscellaneous device */
 	UCLASS_MMC,		/* SD / MMC card or chip */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
diff --git a/include/net/mdio.h b/include/net/mdio.h
new file mode 100644
index 0000000..6adb13f
--- /dev/null
+++ b/include/net/mdio.h
@@ -0,0 +1,62 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ * Author: Ken Ma<make@marvell.com>
+ */
+
+#ifndef _MDIO_H_
+#define _MDIO_H_
+
+#include <dm.h>
+#include <phy.h>
+
+/**
+ * mdio_mii_bus_get() - Get mii bus from mdio udevice
+ *
+ * @mdio_dev:	mdio udevice
+ * @busp:	returns mii bus
+ * @returns 0 on success, error code otherwise.
+ */
+int mdio_mii_bus_get(struct udevice *mdio_dev, struct mii_dev **busp);
+
+/**
+ * mdio_device_get_from_phy() - Get the mdio udevice which the phy belongs to
+ *
+ * @phy_node:	phy node offset
+ * @devp:	returns mdio udevice
+ * @returns 0 on success, error code otherwise.
+ */
+int mdio_device_get_from_phy(ofnode phy_node, struct udevice **devp);
+
+/**
+ * mdio_mii_bus_get_from_phy() - Get the mii bus which the phy belongs to
+ *
+ * @phy_node:	phy node offset
+ * @busp:	returns mii bus
+ * @returns 0 on success, error code otherwise.
+ */
+int mdio_mii_bus_get_from_phy(ofnode phy_node, struct mii_dev **busp);
+
+/**
+ * mdio_device_get_from_eth() - When there is a phy reference of "phy = <&...>"
+ *                      under an ethernet udevice fdt node, this function can
+ *                      get the mdio udevice which the phy belongs to
+ *
+ * @dev:	the ethernet udevice which contains the phy reference
+ * @devp:	returns mdio udevice
+ * @returns 0 on success, error code otherwise.
+ */
+int mdio_device_get_from_eth(struct udevice *eth, struct udevice **devp);
+
+/**
+ * mdio_mii_bus_get_from_eth() - When there is a phy reference of
+ *                      "phy = <&...>" under an ethernet udevice fdt node, this
+ *                      function can get the mii bus which the phy belongs to
+ *
+ * @eth:	the ethernet udevice which contains the phy reference
+ * @busp:	returns mii bus
+ * @returns 0 on success, error code otherwise.
+ */
+int mdio_mii_bus_get_from_eth(struct udevice *eth, struct mii_dev **busp);
+
+#endif /* _MDIO_H_ */