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

Merge branch 'phy_device_type'

Johan Hovold says:

====================
net: phy: add device-type abstraction

This series adds device and device-type abstractions to the micrel
driver, and enables support for RMII-reference clock selection for
KSZ8081 and KSZ8091 devices.

While adding support for more features for the Micrel PHYs mentioned
above, it became apparent that the configuration space is much too large
and that adding type-specific callbacks will simply not scale. Instead I
added a driver_data field to struct phy_device, which can be used to
store static device type data that can be parsed and acted on in
generic driver callbacks. This allows a lot of duplicated code to be
removed, and should make it much easier to add new features or deal with
device-type quirks in the future.

The series has been tested on a dual KSZ8081 setup. Further testing on
other Micrel PHYs would be much appreciated.

The recent commit a95a18afe4c8 ("phy/micrel: KSZ8031RNL RMII clock
reconfiguration bug") currently prevents KSZ8031 PHYs from using the
generic config-init. Bruno, who is the author of that patch, has agreed
to test this series and some follow-up diagnostic patches to determine
how best to incorporate these devices as well. I intend to send a
follow-up patch that removes the custom 8031 config-init and documents
this quirk, but the current series can be applied meanwhile.

These patches are against net-next which contains some already merged
prerequisite patches to the driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2e95b2a8 ee0dc2fb
...@@ -6,21 +6,32 @@ Optional properties: ...@@ -6,21 +6,32 @@ Optional properties:
- micrel,led-mode : LED mode value to set for PHYs with configurable LEDs. - micrel,led-mode : LED mode value to set for PHYs with configurable LEDs.
Configure the LED mode with single value. The list of PHYs and Configure the LED mode with single value. The list of PHYs and the
the bits that are currently supported: bits that are currently supported:
KSZ8001: register 0x1e, bits 15..14 KSZ8001: register 0x1e, bits 15..14
KSZ8041: register 0x1e, bits 15..14 KSZ8041: register 0x1e, bits 15..14
KSZ8021: register 0x1f, bits 5..4 KSZ8021: register 0x1f, bits 5..4
KSZ8031: register 0x1f, bits 5..4 KSZ8031: register 0x1f, bits 5..4
KSZ8051: register 0x1f, bits 5..4 KSZ8051: register 0x1f, bits 5..4
KSZ8081: register 0x1f, bits 5..4 KSZ8081: register 0x1f, bits 5..4
KSZ8091: register 0x1f, bits 5..4 KSZ8091: register 0x1f, bits 5..4
See the respective PHY datasheet for the mode values. See the respective PHY datasheet for the mode values.
- micrel,rmii-reference-clock-select-25-mhz: RMII Reference Clock Select
bit selects 25 MHz mode
Setting the RMII Reference Clock Select bit enables 25 MHz rather
than 50 MHz clock mode.
Note that this option in only needed for certain PHY revisions with a
non-standard, inverted function of this configuration bit.
Specifically, a clock reference ("rmii-ref" below) is always needed to
actually select a mode.
- clocks, clock-names: contains clocks according to the common clock bindings. - clocks, clock-names: contains clocks according to the common clock bindings.
supported clocks: supported clocks:
- KSZ8021, KSZ8031: "rmii-ref": The RMII refence input clock. Used - KSZ8021, KSZ8031, KSZ8081, KSZ8091: "rmii-ref": The RMII reference
to determine the XI input clock. input clock. Used to determine the XI input clock.
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Author: David J. Choi * Author: David J. Choi
* *
* Copyright (c) 2010-2013 Micrel, Inc. * Copyright (c) 2010-2013 Micrel, Inc.
* Copyright (c) 2014 Johan Hovold <johan@kernel.org>
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
...@@ -55,9 +56,7 @@ ...@@ -55,9 +56,7 @@
#define MII_KSZPHY_CTRL MII_KSZPHY_CTRL_2 #define MII_KSZPHY_CTRL MII_KSZPHY_CTRL_2
/* bitmap of PHY register to set interrupt mode */ /* bitmap of PHY register to set interrupt mode */
#define KSZPHY_CTRL_INT_ACTIVE_HIGH BIT(9) #define KSZPHY_CTRL_INT_ACTIVE_HIGH BIT(9)
#define KSZ9021_CTRL_INT_ACTIVE_HIGH BIT(14) #define KSZPHY_RMII_REF_CLK_SEL BIT(7)
#define KS8737_CTRL_INT_ACTIVE_HIGH BIT(14)
#define KSZ8051_RMII_50MHZ_CLK BIT(7)
/* Write/read to/from extended registers */ /* Write/read to/from extended registers */
#define MII_KSZPHY_EXTREG 0x0b #define MII_KSZPHY_EXTREG 0x0b
...@@ -73,20 +72,46 @@ ...@@ -73,20 +72,46 @@
#define PS_TO_REG 200 #define PS_TO_REG 200
static int ksz_config_flags(struct phy_device *phydev) struct kszphy_type {
{ u32 led_mode_reg;
int regval; u16 interrupt_level_mask;
bool has_broadcast_disable;
bool has_rmii_ref_clk_sel;
};
if (phydev->dev_flags & (MICREL_PHY_50MHZ_CLK | MICREL_PHY_25MHZ_CLK)) { struct kszphy_priv {
regval = phy_read(phydev, MII_KSZPHY_CTRL); const struct kszphy_type *type;
if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) int led_mode;
regval |= KSZ8051_RMII_50MHZ_CLK; bool rmii_ref_clk_sel;
else bool rmii_ref_clk_sel_val;
regval &= ~KSZ8051_RMII_50MHZ_CLK; };
return phy_write(phydev, MII_KSZPHY_CTRL, regval);
} static const struct kszphy_type ksz8021_type = {
return 0; .led_mode_reg = MII_KSZPHY_CTRL_2,
} .has_rmii_ref_clk_sel = true,
};
static const struct kszphy_type ksz8041_type = {
.led_mode_reg = MII_KSZPHY_CTRL_1,
};
static const struct kszphy_type ksz8051_type = {
.led_mode_reg = MII_KSZPHY_CTRL_2,
};
static const struct kszphy_type ksz8081_type = {
.led_mode_reg = MII_KSZPHY_CTRL_2,
.has_broadcast_disable = true,
.has_rmii_ref_clk_sel = true,
};
static const struct kszphy_type ks8737_type = {
.interrupt_level_mask = BIT(14),
};
static const struct kszphy_type ksz9021_type = {
.interrupt_level_mask = BIT(14),
};
static int kszphy_extended_write(struct phy_device *phydev, static int kszphy_extended_write(struct phy_device *phydev,
u32 regnum, u16 val) u32 regnum, u16 val)
...@@ -112,74 +137,52 @@ static int kszphy_ack_interrupt(struct phy_device *phydev) ...@@ -112,74 +137,52 @@ static int kszphy_ack_interrupt(struct phy_device *phydev)
return (rc < 0) ? rc : 0; return (rc < 0) ? rc : 0;
} }
static int kszphy_set_interrupt(struct phy_device *phydev) static int kszphy_config_intr(struct phy_device *phydev)
{ {
const struct kszphy_type *type = phydev->drv->driver_data;
int temp; int temp;
temp = (PHY_INTERRUPT_ENABLED == phydev->interrupts) ? u16 mask;
KSZPHY_INTCS_ALL : 0;
return phy_write(phydev, MII_KSZPHY_INTCS, temp);
}
static int kszphy_config_intr(struct phy_device *phydev) if (type && type->interrupt_level_mask)
{ mask = type->interrupt_level_mask;
int temp, rc; else
mask = KSZPHY_CTRL_INT_ACTIVE_HIGH;
/* set the interrupt pin active low */ /* set the interrupt pin active low */
temp = phy_read(phydev, MII_KSZPHY_CTRL); temp = phy_read(phydev, MII_KSZPHY_CTRL);
if (temp < 0) if (temp < 0)
return temp; return temp;
temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH; temp &= ~mask;
phy_write(phydev, MII_KSZPHY_CTRL, temp); phy_write(phydev, MII_KSZPHY_CTRL, temp);
rc = kszphy_set_interrupt(phydev);
return rc < 0 ? rc : 0;
}
static int ksz9021_config_intr(struct phy_device *phydev) /* enable / disable interrupts */
{ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
int temp, rc; temp = KSZPHY_INTCS_ALL;
else
temp = 0;
/* set the interrupt pin active low */ return phy_write(phydev, MII_KSZPHY_INTCS, temp);
temp = phy_read(phydev, MII_KSZPHY_CTRL);
if (temp < 0)
return temp;
temp &= ~KSZ9021_CTRL_INT_ACTIVE_HIGH;
phy_write(phydev, MII_KSZPHY_CTRL, temp);
rc = kszphy_set_interrupt(phydev);
return rc < 0 ? rc : 0;
} }
static int ks8737_config_intr(struct phy_device *phydev) static int kszphy_rmii_clk_sel(struct phy_device *phydev, bool val)
{ {
int temp, rc; int ctrl;
/* set the interrupt pin active low */ ctrl = phy_read(phydev, MII_KSZPHY_CTRL);
temp = phy_read(phydev, MII_KSZPHY_CTRL); if (ctrl < 0)
if (temp < 0) return ctrl;
return temp;
temp &= ~KS8737_CTRL_INT_ACTIVE_HIGH; if (val)
phy_write(phydev, MII_KSZPHY_CTRL, temp); ctrl |= KSZPHY_RMII_REF_CLK_SEL;
rc = kszphy_set_interrupt(phydev); else
return rc < 0 ? rc : 0; ctrl &= ~KSZPHY_RMII_REF_CLK_SEL;
return phy_write(phydev, MII_KSZPHY_CTRL, ctrl);
} }
static int kszphy_setup_led(struct phy_device *phydev, u32 reg) static int kszphy_setup_led(struct phy_device *phydev, u32 reg, int val)
{ {
struct device *dev = &phydev->dev;
struct device_node *of_node = dev->of_node;
int rc, temp, shift; int rc, temp, shift;
u32 val;
if (!of_node && dev->parent->of_node)
of_node = dev->parent->of_node;
if (of_property_read_u32(of_node, "micrel,led-mode", &val))
return 0;
if (val > 3) {
dev_err(&phydev->dev, "invalid led mode: 0x%02x\n", val);
return -EINVAL;
}
switch (reg) { switch (reg) {
case MII_KSZPHY_CTRL_1: case MII_KSZPHY_CTRL_1:
...@@ -229,45 +232,43 @@ static int kszphy_broadcast_disable(struct phy_device *phydev) ...@@ -229,45 +232,43 @@ static int kszphy_broadcast_disable(struct phy_device *phydev)
static int kszphy_config_init(struct phy_device *phydev) static int kszphy_config_init(struct phy_device *phydev)
{ {
return 0; struct kszphy_priv *priv = phydev->priv;
} const struct kszphy_type *type;
int ret;
static int kszphy_config_init_led8041(struct phy_device *phydev) if (!priv)
{ return 0;
return kszphy_setup_led(phydev, MII_KSZPHY_CTRL_1);
}
static int ksz8021_config_init(struct phy_device *phydev) type = priv->type;
{
int rc;
kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2); if (type->has_broadcast_disable)
kszphy_broadcast_disable(phydev);
rc = ksz_config_flags(phydev); if (priv->rmii_ref_clk_sel) {
if (rc < 0) ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val);
return rc; if (ret) {
dev_err(&phydev->dev, "failed to set rmii reference clock\n");
return ret;
}
}
rc = kszphy_broadcast_disable(phydev); if (priv->led_mode >= 0)
kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode);
return rc < 0 ? rc : 0; return 0;
} }
static int ks8051_config_init(struct phy_device *phydev) static int ksz8021_config_init(struct phy_device *phydev)
{ {
int rc; int rc;
kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2); rc = kszphy_config_init(phydev);
if (rc)
rc = ksz_config_flags(phydev); return rc;
return rc < 0 ? rc : 0;
}
static int ksz8081_config_init(struct phy_device *phydev) rc = kszphy_broadcast_disable(phydev);
{
kszphy_broadcast_disable(phydev);
kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2);
return 0; return rc < 0 ? rc : 0;
} }
static int ksz9021_load_values_from_of(struct phy_device *phydev, static int ksz9021_load_values_from_of(struct phy_device *phydev,
...@@ -499,24 +500,62 @@ ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum, ...@@ -499,24 +500,62 @@ ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
{ {
} }
static int ksz8021_probe(struct phy_device *phydev) static int kszphy_probe(struct phy_device *phydev)
{ {
const struct kszphy_type *type = phydev->drv->driver_data;
struct device_node *np = phydev->dev.of_node;
struct kszphy_priv *priv;
struct clk *clk; struct clk *clk;
int ret;
priv = devm_kzalloc(&phydev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
phydev->priv = priv;
priv->type = type;
if (type->led_mode_reg) {
ret = of_property_read_u32(np, "micrel,led-mode",
&priv->led_mode);
if (ret)
priv->led_mode = -1;
if (priv->led_mode > 3) {
dev_err(&phydev->dev, "invalid led mode: 0x%02x\n",
priv->led_mode);
priv->led_mode = -1;
}
} else {
priv->led_mode = -1;
}
clk = devm_clk_get(&phydev->dev, "rmii-ref"); clk = devm_clk_get(&phydev->dev, "rmii-ref");
if (!IS_ERR(clk)) { if (!IS_ERR(clk)) {
unsigned long rate = clk_get_rate(clk); unsigned long rate = clk_get_rate(clk);
bool rmii_ref_clk_sel_25_mhz;
priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
rmii_ref_clk_sel_25_mhz = of_property_read_bool(np,
"micrel,rmii-reference-clock-select-25-mhz");
if (rate > 24500000 && rate < 25500000) { if (rate > 24500000 && rate < 25500000) {
phydev->dev_flags |= MICREL_PHY_25MHZ_CLK; priv->rmii_ref_clk_sel_val = rmii_ref_clk_sel_25_mhz;
} else if (rate > 49500000 && rate < 50500000) { } else if (rate > 49500000 && rate < 50500000) {
phydev->dev_flags |= MICREL_PHY_50MHZ_CLK; priv->rmii_ref_clk_sel_val = !rmii_ref_clk_sel_25_mhz;
} else { } else {
dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate); dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate);
return -EINVAL; return -EINVAL;
} }
} }
/* Support legacy board-file configuration */
if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
priv->rmii_ref_clk_sel = true;
priv->rmii_ref_clk_sel_val = true;
}
return 0; return 0;
} }
...@@ -527,11 +566,12 @@ static struct phy_driver ksphy_driver[] = { ...@@ -527,11 +566,12 @@ static struct phy_driver ksphy_driver[] = {
.name = "Micrel KS8737", .name = "Micrel KS8737",
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ks8737_type,
.config_init = kszphy_config_init, .config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt, .ack_interrupt = kszphy_ack_interrupt,
.config_intr = ks8737_config_intr, .config_intr = kszphy_config_intr,
.suspend = genphy_suspend, .suspend = genphy_suspend,
.resume = genphy_resume, .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,}, .driver = { .owner = THIS_MODULE,},
...@@ -542,7 +582,8 @@ static struct phy_driver ksphy_driver[] = { ...@@ -542,7 +582,8 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause), SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.probe = ksz8021_probe, .driver_data = &ksz8021_type,
.probe = kszphy_probe,
.config_init = ksz8021_config_init, .config_init = ksz8021_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
...@@ -558,7 +599,8 @@ static struct phy_driver ksphy_driver[] = { ...@@ -558,7 +599,8 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause), SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.probe = ksz8021_probe, .driver_data = &ksz8021_type,
.probe = kszphy_probe,
.config_init = ksz8021_config_init, .config_init = ksz8021_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
...@@ -574,7 +616,9 @@ static struct phy_driver ksphy_driver[] = { ...@@ -574,7 +616,9 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
| SUPPORTED_Asym_Pause), | SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init_led8041, .driver_data = &ksz8041_type,
.probe = kszphy_probe,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt, .ack_interrupt = kszphy_ack_interrupt,
...@@ -589,7 +633,9 @@ static struct phy_driver ksphy_driver[] = { ...@@ -589,7 +633,9 @@ static struct phy_driver ksphy_driver[] = {
.features = PHY_BASIC_FEATURES | .features = PHY_BASIC_FEATURES |
SUPPORTED_Pause | SUPPORTED_Asym_Pause, SUPPORTED_Pause | SUPPORTED_Asym_Pause,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init_led8041, .driver_data = &ksz8041_type,
.probe = kszphy_probe,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt, .ack_interrupt = kszphy_ack_interrupt,
...@@ -604,7 +650,9 @@ static struct phy_driver ksphy_driver[] = { ...@@ -604,7 +650,9 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
| SUPPORTED_Asym_Pause), | SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = ks8051_config_init, .driver_data = &ksz8051_type,
.probe = kszphy_probe,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt, .ack_interrupt = kszphy_ack_interrupt,
...@@ -618,7 +666,9 @@ static struct phy_driver ksphy_driver[] = { ...@@ -618,7 +666,9 @@ static struct phy_driver ksphy_driver[] = {
.phy_id_mask = 0x00ffffff, .phy_id_mask = 0x00ffffff,
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init_led8041, .driver_data = &ksz8041_type,
.probe = kszphy_probe,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt, .ack_interrupt = kszphy_ack_interrupt,
...@@ -632,7 +682,9 @@ static struct phy_driver ksphy_driver[] = { ...@@ -632,7 +682,9 @@ static struct phy_driver ksphy_driver[] = {
.phy_id_mask = 0x00fffff0, .phy_id_mask = 0x00fffff0,
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = ksz8081_config_init, .driver_data = &ksz8081_type,
.probe = kszphy_probe,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt, .ack_interrupt = kszphy_ack_interrupt,
...@@ -660,11 +712,12 @@ static struct phy_driver ksphy_driver[] = { ...@@ -660,11 +712,12 @@ static struct phy_driver ksphy_driver[] = {
.name = "Micrel KSZ9021 Gigabit PHY", .name = "Micrel KSZ9021 Gigabit PHY",
.features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz9021_type,
.config_init = ksz9021_config_init, .config_init = ksz9021_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt, .ack_interrupt = kszphy_ack_interrupt,
.config_intr = ksz9021_config_intr, .config_intr = kszphy_config_intr,
.suspend = genphy_suspend, .suspend = genphy_suspend,
.resume = genphy_resume, .resume = genphy_resume,
.read_mmd_indirect = ksz9021_rd_mmd_phyreg, .read_mmd_indirect = ksz9021_rd_mmd_phyreg,
...@@ -676,11 +729,12 @@ static struct phy_driver ksphy_driver[] = { ...@@ -676,11 +729,12 @@ static struct phy_driver ksphy_driver[] = {
.name = "Micrel KSZ9031 Gigabit PHY", .name = "Micrel KSZ9031 Gigabit PHY",
.features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.driver_data = &ksz9021_type,
.config_init = ksz9031_config_init, .config_init = ksz9031_config_init,
.config_aneg = genphy_config_aneg, .config_aneg = genphy_config_aneg,
.read_status = genphy_read_status, .read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt, .ack_interrupt = kszphy_ack_interrupt,
.config_intr = ksz9021_config_intr, .config_intr = kszphy_config_intr,
.suspend = genphy_suspend, .suspend = genphy_suspend,
.resume = genphy_resume, .resume = genphy_resume,
.driver = { .owner = THIS_MODULE, }, .driver = { .owner = THIS_MODULE, },
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
/* struct phy_device dev_flags definitions */ /* struct phy_device dev_flags definitions */
#define MICREL_PHY_50MHZ_CLK 0x00000001 #define MICREL_PHY_50MHZ_CLK 0x00000001
#define MICREL_PHY_25MHZ_CLK 0x00000002
#define MICREL_KSZ9021_EXTREG_CTRL 0xB #define MICREL_KSZ9021_EXTREG_CTRL 0xB
#define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC #define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC
......
...@@ -433,6 +433,7 @@ struct phy_device { ...@@ -433,6 +433,7 @@ struct phy_device {
* by this PHY * by this PHY
* flags: A bitfield defining certain other features this PHY * flags: A bitfield defining certain other features this PHY
* supports (like interrupts) * supports (like interrupts)
* driver_data: static driver data
* *
* The drivers must implement config_aneg and read_status. All * The drivers must implement config_aneg and read_status. All
* other functions are optional. Note that none of these * other functions are optional. Note that none of these
...@@ -448,6 +449,7 @@ struct phy_driver { ...@@ -448,6 +449,7 @@ struct phy_driver {
unsigned int phy_id_mask; unsigned int phy_id_mask;
u32 features; u32 features;
u32 flags; u32 flags;
const void *driver_data;
/* /*
* Called to issue a PHY software reset * Called to issue a PHY software reset
......
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