ipq40xx: net: phy: ar40xx: remove PHY handling
Since we now have proper PHY driver for the QCA807x PHY-s, lets remove PHY handling from AR40xx. This removes PHY driver, PHY GPIO driver and PHY init code. AR40xx still needs to handle PSGMII calibration as that requires R/W from the switch, so I am unable to move it into PHY driver. This also converted the AR40xx driver to use OF_MDIO to find the MDIO bus as it now cant be set through the PHY driver. So lets depend on OF_MDIO in KConfig. Signed-off-by: Robert Marko <robert.marko@sartura.hr>
This commit is contained in:
parent
b5c93edd74
commit
26b1f72381
|
@ -25,6 +25,7 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/mdio.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
|
@ -1245,42 +1246,6 @@ ar40xx_init_globals(struct ar40xx_priv *priv)
|
|||
ar40xx_write(priv, AR40XX_REG_PORT_FLOWCTRL_THRESH(0), t);
|
||||
}
|
||||
|
||||
static void
|
||||
ar40xx_malibu_init(struct ar40xx_priv *priv)
|
||||
{
|
||||
int i;
|
||||
struct mii_bus *bus;
|
||||
u16 val;
|
||||
|
||||
bus = priv->mii_bus;
|
||||
|
||||
/* war to enable AZ transmitting ability */
|
||||
ar40xx_phy_mmd_write(priv, AR40XX_PSGMII_ID, 1,
|
||||
AR40XX_MALIBU_PSGMII_MODE_CTRL,
|
||||
AR40XX_MALIBU_PHY_PSGMII_MODE_CTRL_ADJUST_VAL);
|
||||
for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) {
|
||||
/* change malibu control_dac */
|
||||
val = ar40xx_phy_mmd_read(priv, i, 7,
|
||||
AR40XX_MALIBU_PHY_MMD7_DAC_CTRL);
|
||||
val &= ~AR40XX_MALIBU_DAC_CTRL_MASK;
|
||||
val |= AR40XX_MALIBU_DAC_CTRL_VALUE;
|
||||
ar40xx_phy_mmd_write(priv, i, 7,
|
||||
AR40XX_MALIBU_PHY_MMD7_DAC_CTRL, val);
|
||||
if (i == AR40XX_MALIBU_PHY_LAST_ADDR) {
|
||||
/* to avoid goes into hibernation */
|
||||
val = ar40xx_phy_mmd_read(priv, i, 3,
|
||||
AR40XX_MALIBU_PHY_RLP_CTRL);
|
||||
val &= (~(1<<1));
|
||||
ar40xx_phy_mmd_write(priv, i, 3,
|
||||
AR40XX_MALIBU_PHY_RLP_CTRL, val);
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust psgmii serdes tx amp */
|
||||
mdiobus_write(bus, AR40XX_PSGMII_ID, AR40XX_PSGMII_TX_DRIVER_1_CTRL,
|
||||
AR40XX_MALIBU_PHY_PSGMII_REDUCE_SERDES_TX_AMP);
|
||||
}
|
||||
|
||||
static int
|
||||
ar40xx_hw_init(struct ar40xx_priv *priv)
|
||||
{
|
||||
|
@ -1288,9 +1253,7 @@ ar40xx_hw_init(struct ar40xx_priv *priv)
|
|||
|
||||
ar40xx_ess_reset(priv);
|
||||
|
||||
if (priv->mii_bus)
|
||||
ar40xx_malibu_init(priv);
|
||||
else
|
||||
if (!priv->mii_bus)
|
||||
return -1;
|
||||
|
||||
ar40xx_psgmii_self_test(priv);
|
||||
|
@ -1763,183 +1726,13 @@ static const struct switch_dev_ops ar40xx_sw_ops = {
|
|||
.get_port_link = ar40xx_sw_get_port_link,
|
||||
};
|
||||
|
||||
/* Start of phy driver support */
|
||||
|
||||
static const u32 ar40xx_phy_ids[] = {
|
||||
0x004dd0b1,
|
||||
0x004dd0b2, /* AR40xx */
|
||||
};
|
||||
|
||||
static bool
|
||||
ar40xx_phy_match(u32 phy_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ar40xx_phy_ids); i++)
|
||||
if (phy_id == ar40xx_phy_ids[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_ar40xx_phy(struct mii_bus *bus)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 phy_id;
|
||||
|
||||
phy_id = mdiobus_read(bus, i, MII_PHYSID1) << 16;
|
||||
phy_id |= mdiobus_read(bus, i, MII_PHYSID2);
|
||||
if (!ar40xx_phy_match(phy_id))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
ar40xx_phy_probe(struct phy_device *phydev)
|
||||
{
|
||||
if (!is_ar40xx_phy(phydev->mdio.bus))
|
||||
return -ENODEV;
|
||||
|
||||
ar40xx_priv->mii_bus = phydev->mdio.bus;
|
||||
phydev->priv = ar40xx_priv;
|
||||
if (phydev->mdio.addr == 0)
|
||||
ar40xx_priv->phy = phydev;
|
||||
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, phydev->supported);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, phydev->advertising);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ar40xx_phy_remove(struct phy_device *phydev)
|
||||
{
|
||||
ar40xx_priv->mii_bus = NULL;
|
||||
phydev->priv = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ar40xx_phy_config_init(struct phy_device *phydev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ar40xx_phy_read_status(struct phy_device *phydev)
|
||||
{
|
||||
if (phydev->mdio.addr != 0)
|
||||
return genphy_read_status(phydev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ar40xx_phy_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
if (phydev->mdio.addr == 0)
|
||||
return 0;
|
||||
|
||||
return genphy_config_aneg(phydev);
|
||||
}
|
||||
|
||||
static struct phy_driver ar40xx_phy_driver = {
|
||||
.phy_id = 0x004d0000,
|
||||
.name = "QCA Malibu",
|
||||
.phy_id_mask = 0xffff0000,
|
||||
.features = PHY_GBIT_FEATURES,
|
||||
.probe = ar40xx_phy_probe,
|
||||
.remove = ar40xx_phy_remove,
|
||||
.config_init = ar40xx_phy_config_init,
|
||||
.config_aneg = ar40xx_phy_config_aneg,
|
||||
.read_status = ar40xx_phy_read_status,
|
||||
};
|
||||
|
||||
static uint16_t ar40xx_gpio_get_phy(unsigned int offset)
|
||||
{
|
||||
return offset / 4;
|
||||
}
|
||||
|
||||
static uint16_t ar40xx_gpio_get_reg(unsigned int offset)
|
||||
{
|
||||
return 0x8074 + offset % 4;
|
||||
}
|
||||
|
||||
static void ar40xx_gpio_set(struct gpio_chip *gc, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct ar40xx_priv *priv = gpiochip_get_data(gc);
|
||||
|
||||
ar40xx_phy_mmd_write(priv, ar40xx_gpio_get_phy(offset), 0x7,
|
||||
ar40xx_gpio_get_reg(offset),
|
||||
value ? 0xA000 : 0x8000);
|
||||
}
|
||||
|
||||
static int ar40xx_gpio_get(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct ar40xx_priv *priv = gpiochip_get_data(gc);
|
||||
|
||||
return ar40xx_phy_mmd_read(priv, ar40xx_gpio_get_phy(offset), 0x7,
|
||||
ar40xx_gpio_get_reg(offset)) == 0xA000;
|
||||
}
|
||||
|
||||
static int ar40xx_gpio_get_dir(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
return 0; /* only out direction */
|
||||
}
|
||||
|
||||
static int ar40xx_gpio_dir_out(struct gpio_chip *gc, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
/*
|
||||
* the direction out value is used to set the initial value.
|
||||
* support of this function is required by leds-gpio.c
|
||||
*/
|
||||
ar40xx_gpio_set(gc, offset, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ar40xx_register_gpio(struct device *pdev,
|
||||
struct ar40xx_priv *priv,
|
||||
struct device_node *switch_node)
|
||||
{
|
||||
struct gpio_chip *gc;
|
||||
int err;
|
||||
|
||||
gc = devm_kzalloc(pdev, sizeof(*gc), GFP_KERNEL);
|
||||
if (!gc)
|
||||
return;
|
||||
|
||||
gc->label = "ar40xx_gpio",
|
||||
gc->base = -1,
|
||||
gc->ngpio = 5 /* mmd 0 - 4 */ * 4 /* 0x8074 - 0x8077 */,
|
||||
gc->parent = pdev;
|
||||
gc->owner = THIS_MODULE;
|
||||
|
||||
gc->get_direction = ar40xx_gpio_get_dir;
|
||||
gc->direction_output = ar40xx_gpio_dir_out;
|
||||
gc->get = ar40xx_gpio_get;
|
||||
gc->set = ar40xx_gpio_set;
|
||||
gc->can_sleep = true;
|
||||
gc->label = priv->dev.name;
|
||||
gc->of_node = switch_node;
|
||||
|
||||
err = devm_gpiochip_add_data(pdev, gc, priv);
|
||||
if (err != 0)
|
||||
dev_err(pdev, "Failed to register gpio %d.\n", err);
|
||||
}
|
||||
|
||||
/* End of phy driver support */
|
||||
|
||||
/* Platform driver probe function */
|
||||
|
||||
static int ar40xx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *switch_node;
|
||||
struct device_node *psgmii_node;
|
||||
struct device_node *mdio_node;
|
||||
const __be32 *mac_mode;
|
||||
struct clk *ess_clk;
|
||||
struct switch_dev *swdev;
|
||||
|
@ -2010,12 +1803,6 @@ static int ar40xx_probe(struct platform_device *pdev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
ret = phy_driver_register(&ar40xx_phy_driver, THIS_MODULE);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to register ar40xx phy driver!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mutex_init(&priv->reg_mutex);
|
||||
mutex_init(&priv->mib_lock);
|
||||
INIT_DELAYED_WORK(&priv->mib_work, ar40xx_mib_work_func);
|
||||
|
@ -2023,6 +1810,15 @@ static int ar40xx_probe(struct platform_device *pdev)
|
|||
/* register switch */
|
||||
swdev = &priv->dev;
|
||||
|
||||
mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq4019-mdio");
|
||||
if (!mdio_node) {
|
||||
dev_err(&pdev->dev, "Probe failed - Cannot find mdio node by phandle!\n");
|
||||
ret = -ENODEV;
|
||||
goto err_missing_phy;
|
||||
}
|
||||
|
||||
priv->mii_bus = of_mdio_find_bus(mdio_node);
|
||||
|
||||
if (priv->mii_bus == NULL) {
|
||||
dev_err(&pdev->dev, "Probe failed - Missing PHYs!\n");
|
||||
ret = -ENODEV;
|
||||
|
@ -2037,8 +1833,10 @@ static int ar40xx_probe(struct platform_device *pdev)
|
|||
swdev->ports = AR40XX_NUM_PORTS;
|
||||
swdev->ops = &ar40xx_sw_ops;
|
||||
ret = register_switch(swdev, NULL);
|
||||
if (ret)
|
||||
goto err_unregister_phy;
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Switch registration failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
num_mibs = ARRAY_SIZE(ar40xx_mibs);
|
||||
len = priv->dev.ports * num_mibs *
|
||||
|
@ -2051,15 +1849,10 @@ static int ar40xx_probe(struct platform_device *pdev)
|
|||
|
||||
ar40xx_start(priv);
|
||||
|
||||
if (of_property_read_bool(switch_node, "gpio-controller"))
|
||||
ar40xx_register_gpio(&pdev->dev, ar40xx_priv, switch_node);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_switch:
|
||||
unregister_switch(&priv->dev);
|
||||
err_unregister_phy:
|
||||
phy_driver_unregister(&ar40xx_phy_driver);
|
||||
err_missing_phy:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return ret;
|
||||
|
@ -2074,8 +1867,6 @@ static int ar40xx_remove(struct platform_device *pdev)
|
|||
|
||||
unregister_switch(&priv->dev);
|
||||
|
||||
phy_driver_unregister(&ar40xx_phy_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -584,6 +584,13 @@ config MDIO_IPQ40XX
|
||||
This driver supports the MDIO interface found in Qualcomm
|
||||
Atheros ipq40xx Soc chip.
|
||||
@@ -584,6 +584,13 @@ config XILINX_GMII2RGMII
|
||||
the Reduced Gigabit Media Independent Interface(RGMII) between
|
||||
Ethernet physical media devices and the Gigabit Ethernet controller.
|
||||
|
||||
+config AR40XX_PHY
|
||||
+ tristate "Driver for Qualcomm Atheros IPQ40XX switches"
|
||||
+ depends on HAS_IOMEM && OF
|
||||
+ depends on HAS_IOMEM && OF && OF_MDIO
|
||||
+ select SWCONFIG
|
||||
+ help
|
||||
+ This is the driver for Qualcomm Atheros IPQ40XX ESS switches.
|
||||
|
|
Loading…
Reference in New Issue