Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae803902 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-phy-Support-managed-Cortina-phys'



Bogdan Purcareata says:

====================
net: phy: Support managed Cortina phys

So far, the Cortina family phys (CS4340 in this particular case) are only
supported in fixed link mode (via fixed_phy_register). The generic 10G
phy driver does not work well with the phylib state machine, when the phy
is registered via of_phy_connect. This prohibits the user from describing the
phy nodes in the device tree.

In order to support this scenario, and to properly describe the board
device tree, add a minimal Cortina driver that reads the status from the
right register. With the generic 10G C45 driver, the kernel will print
messages like:
[    0.226521] mdio_bus 8b96000: Error while reading PHY16 reg at 1.6
[    0.232780] mdio_bus 8b96000: Error while reading PHY16 reg at 1.5

v3 -> v4:
- Add trademark info.
- Minor documentation entry consistency nit.

v2 -> v3:
- Add documentation entry.

v1 -> v2:
- Change approach for getting the phy_id from hacking get_phy_c45_ids to
  describing the device in the device tree via ethernet-phy-id.

More patch version changes per individual patches.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents eb67e07a 303d9771
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
Cortina Phy Driver Device Tree Bindings
---------------------------------------

CORTINA is a registered trademark of Cortina Systems, Inc.

The driver supports the Cortina Electronic Dispersion Compensation (EDC)
devices, equipped with clock and data recovery (CDR) circuits. These
devices make use of registers that are not compatible with Clause 45 or
Clause 22, therefore they need to be described using the
"ethernet-phy-id" compatible.

Since the driver only implements  polling mode support, interrupts info
can be skipped.

Example (CS4340 phy):
	mdio {
		cs4340_phy@10 {
			compatible = "ethernet-phy-id13e5.1002";
			reg = <0x10>;
		};
	};
+5 −0
Original line number Diff line number Diff line
@@ -234,6 +234,11 @@ config CICADA_PHY
	---help---
	  Currently supports the cis8204

config CORTINA_PHY
	tristate "Cortina EDC CDR 10G Ethernet PHY"
	---help---
	  Currently supports the CS4340 phy.

config DAVICOM_PHY
	tristate "Davicom PHYs"
	---help---
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o
obj-$(CONFIG_BCM_NET_PHYLIB)	+= bcm-phy-lib.o
obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
obj-$(CONFIG_CICADA_PHY)	+= cicada.o
obj-$(CONFIG_CORTINA_PHY)	+= cortina.o
obj-$(CONFIG_DAVICOM_PHY)	+= davicom.o
obj-$(CONFIG_DP83640_PHY)	+= dp83640.o
obj-$(CONFIG_DP83848_PHY)	+= dp83848.o
+118 −0
Original line number Diff line number Diff line
/*
 *    Copyright 2017 NXP
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    CORTINA is a registered trademark of Cortina Systems, Inc.
 *
 */
#include <linux/module.h>
#include <linux/phy.h>

#define PHY_ID_CS4340	0x13e51002

#define VILLA_GLOBAL_CHIP_ID_LSB			0x0
#define VILLA_GLOBAL_CHIP_ID_MSB			0x1

#define VILLA_GLOBAL_GPIO_1_INTS			0x017

static int cortina_read_reg(struct phy_device *phydev, u16 regnum)
{
	return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
			    MII_ADDR_C45 | regnum);
}

static int cortina_config_aneg(struct phy_device *phydev)
{
	phydev->supported = SUPPORTED_10000baseT_Full;
	phydev->advertising = SUPPORTED_10000baseT_Full;

	return 0;
}

static int cortina_read_status(struct phy_device *phydev)
{
	int gpio_int_status, ret = 0;

	gpio_int_status = cortina_read_reg(phydev, VILLA_GLOBAL_GPIO_1_INTS);
	if (gpio_int_status < 0) {
		ret = gpio_int_status;
		goto err;
	}

	if (gpio_int_status & 0x8) {
		/* up when edc_convergedS set */
		phydev->speed = SPEED_10000;
		phydev->duplex = DUPLEX_FULL;
		phydev->link = 1;
	} else {
		phydev->link = 0;
	}

err:
	return ret;
}

static int cortina_soft_reset(struct phy_device *phydev)
{
	return 0;
}

static int cortina_probe(struct phy_device *phydev)
{
	u32 phy_id = 0;
	int id_lsb = 0, id_msb = 0;

	/* Read device id from phy registers. */
	id_lsb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_LSB);
	if (id_lsb < 0)
		return -ENXIO;

	phy_id = id_lsb << 16;

	id_msb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_MSB);
	if (id_msb < 0)
		return -ENXIO;

	phy_id |= id_msb;

	/* Make sure the device tree binding matched the driver with the
	 * right device.
	 */
	if (phy_id != phydev->drv->phy_id) {
		phydev_err(phydev, "Error matching phy with %s driver\n",
			   phydev->drv->name);
		return -ENODEV;
	}

	return 0;
}

static struct phy_driver cortina_driver[] = {
{
	.phy_id		= PHY_ID_CS4340,
	.phy_id_mask	= 0xffffffff,
	.name		= "Cortina CS4340",
	.config_aneg	= cortina_config_aneg,
	.read_status	= cortina_read_status,
	.soft_reset	= cortina_soft_reset,
	.probe		= cortina_probe,
},
};

module_phy_driver(cortina_driver);

static struct mdio_device_id __maybe_unused cortina_tbl[] = {
	{ PHY_ID_CS4340, 0xffffffff},
	{},
};

MODULE_DEVICE_TABLE(mdio, cortina_tbl);