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

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
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>;
};
};
......@@ -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---
......
......@@ -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
......
/*
* 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);
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