Commit 6a864730 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-phy-marvell-usb-to-mdio-controller'

Tobias Waldekranz says:

====================
net: phy: marvell usb to mdio controller

Support for an MDIO controller present on development boards for
Marvell switches from the Link Street (88E6xxx) family.

v3->v4:
- Remove unnecessary dependency on OF_MDIO.

v2->v3:
- Rename driver smi2usb -> mvusb.
- Clean up unused USB references.

v1->v2:
- Reverse christmas tree ordering of local variables.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 16983507 04e37d92
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/marvell,mvusb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvell USB to MDIO Controller
maintainers:
- Tobias Waldekranz <tobias@waldekranz.com>
description: |+
This controller is mounted on development boards for Marvell's Link Street
family of Ethernet switches. It allows you to configure the switch's registers
using the standard MDIO interface.
Since the device is connected over USB, there is no strict requirement of
having a device tree representation of the device. But in order to use it with
the mv88e6xxx driver, you need a device tree node in which to place the switch
definition.
allOf:
- $ref: "mdio.yaml#"
properties:
compatible:
const: usb1286,1fa4
reg:
maxItems: 1
description: The USB port number on the host controller
required:
- compatible
- reg
- "#address-cells"
- "#size-cells"
examples:
- |
/* USB host controller */
&usb1 {
mvusb: mdio@1 {
compatible = "usb1286,1fa4";
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
};
};
/* MV88E6390X devboard */
&mvusb {
switch@0 {
compatible = "marvell,mv88e6190";
status = "ok";
reg = <0x0>;
ports {
/* Port definitions */
};
mdio {
/* PHY definitions */
};
};
};
......@@ -10106,6 +10106,13 @@ M: Nicolas Pitre <nico@fluxnic.net>
S: Odd Fixes
F: drivers/mmc/host/mvsdio.*
MARVELL USB MDIO CONTROLLER DRIVER
M: Tobias Waldekranz <tobias@waldekranz.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/phy/mdio-mvusb.c
F: Documentation/devicetree/bindings/net/marvell,mvusb.yaml
MARVELL XENON MMC/SD/SDIO HOST CONTROLLER DRIVER
M: Hu Ziji <huziji@marvell.com>
L: linux-mmc@vger.kernel.org
......
......@@ -179,6 +179,13 @@ config MDIO_MSCC_MIIM
This driver supports the MIIM (MDIO) interface found in the network
switches of the Microsemi SoCs
config MDIO_MVUSB
tristate "Marvell USB to MDIO Adapter"
depends on USB
help
A USB to MDIO converter present on development boards for
Marvell's Link Street family of Ethernet switches.
config MDIO_OCTEON
tristate "Octeon and some ThunderX SOCs MDIO buses"
depends on (64BIT && OF_MDIO) || COMPILE_TEST
......
......@@ -40,6 +40,7 @@ obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o
obj-$(CONFIG_MDIO_IPQ8064) += mdio-ipq8064.o
obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o
obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
......
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/usb.h>
#define USB_MARVELL_VID 0x1286
static const struct usb_device_id mvusb_mdio_table[] = {
{ USB_DEVICE(USB_MARVELL_VID, 0x1fa4) },
{}
};
MODULE_DEVICE_TABLE(usb, mvusb_mdio_table);
enum {
MVUSB_CMD_PREAMBLE0,
MVUSB_CMD_PREAMBLE1,
MVUSB_CMD_ADDR,
MVUSB_CMD_VAL,
};
struct mvusb_mdio {
struct usb_device *udev;
struct mii_bus *mdio;
__le16 buf[4];
};
static int mvusb_mdio_read(struct mii_bus *mdio, int dev, int reg)
{
struct mvusb_mdio *mvusb = mdio->priv;
int err, alen;
if (dev & MII_ADDR_C45)
return -EOPNOTSUPP;
mvusb->buf[MVUSB_CMD_ADDR] = cpu_to_le16(0xa400 | (dev << 5) | reg);
err = usb_bulk_msg(mvusb->udev, usb_sndbulkpipe(mvusb->udev, 2),
mvusb->buf, 6, &alen, 100);
if (err)
return err;
err = usb_bulk_msg(mvusb->udev, usb_rcvbulkpipe(mvusb->udev, 6),
&mvusb->buf[MVUSB_CMD_VAL], 2, &alen, 100);
if (err)
return err;
return le16_to_cpu(mvusb->buf[MVUSB_CMD_VAL]);
}
static int mvusb_mdio_write(struct mii_bus *mdio, int dev, int reg, u16 val)
{
struct mvusb_mdio *mvusb = mdio->priv;
int alen;
if (dev & MII_ADDR_C45)
return -EOPNOTSUPP;
mvusb->buf[MVUSB_CMD_ADDR] = cpu_to_le16(0x8000 | (dev << 5) | reg);
mvusb->buf[MVUSB_CMD_VAL] = cpu_to_le16(val);
return usb_bulk_msg(mvusb->udev, usb_sndbulkpipe(mvusb->udev, 2),
mvusb->buf, 8, &alen, 100);
}
static int mvusb_mdio_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct device *dev = &interface->dev;
struct mvusb_mdio *mvusb;
struct mii_bus *mdio;
mdio = devm_mdiobus_alloc_size(dev, sizeof(*mvusb));
if (!mdio)
return -ENOMEM;
mvusb = mdio->priv;
mvusb->mdio = mdio;
mvusb->udev = usb_get_dev(interface_to_usbdev(interface));
/* Reversed from USB PCAPs, no idea what these mean. */
mvusb->buf[MVUSB_CMD_PREAMBLE0] = cpu_to_le16(0xe800);
mvusb->buf[MVUSB_CMD_PREAMBLE1] = cpu_to_le16(0x0001);
snprintf(mdio->id, MII_BUS_ID_SIZE, "mvusb-%s", dev_name(dev));
mdio->name = mdio->id;
mdio->parent = dev;
mdio->read = mvusb_mdio_read;
mdio->write = mvusb_mdio_write;
usb_set_intfdata(interface, mvusb);
return of_mdiobus_register(mdio, dev->of_node);
}
static void mvusb_mdio_disconnect(struct usb_interface *interface)
{
struct mvusb_mdio *mvusb = usb_get_intfdata(interface);
struct usb_device *udev = mvusb->udev;
mdiobus_unregister(mvusb->mdio);
usb_set_intfdata(interface, NULL);
usb_put_dev(udev);
}
static struct usb_driver mvusb_mdio_driver = {
.name = "mvusb_mdio",
.id_table = mvusb_mdio_table,
.probe = mvusb_mdio_probe,
.disconnect = mvusb_mdio_disconnect,
};
module_usb_driver(mvusb_mdio_driver);
MODULE_AUTHOR("Tobias Waldekranz <tobias@waldekranz.com>");
MODULE_DESCRIPTION("Marvell USB MDIO Adapter");
MODULE_LICENSE("GPL");
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