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

Merge branch 'Microchip-Technology-KSZ9131'

Yuiko Oshino says:

====================
Add support for Microchip Technology KSZ9131 10/100/1000 Ethernet PHY

This is the initial driver for Microchip KSZ9131 10/100/1000 Ethernet PHY

v3:
- KSZ9131 uses picosecond units for values of devicetree properties.
- rewrite micrel.c and micrel-ksz90x1.txt to use the picosecond values.
v2:
- Creating a series from two related patches.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c9fbd71f 806700ba
Micrel KSZ9021/KSZ9031 Gigabit Ethernet PHY Micrel KSZ9021/KSZ9031/KSZ9131 Gigabit Ethernet PHY
Some boards require special tuning values, particularly when it comes Some boards require special tuning values, particularly when it comes
to clock delays. You can specify clock delay values in the PHY OF to clock delays. You can specify clock delay values in the PHY OF
...@@ -64,6 +64,32 @@ KSZ9031: ...@@ -64,6 +64,32 @@ KSZ9031:
Attention: The link partner must be configurable as slave otherwise Attention: The link partner must be configurable as slave otherwise
no link will be established. no link will be established.
KSZ9131:
All skew control options are specified in picoseconds. The increment
step is 100ps. Unlike KSZ9031, the values represent picoseccond delays.
A negative value can be assigned as rxc-skew-psec = <(-100)>;.
Optional properties:
Range of the value -700 to 2400, default value 0:
- rxc-skew-psec : Skew control of RX clock pad
- txc-skew-psec : Skew control of TX clock pad
Range of the value -700 to 800, default value 0:
- rxdv-skew-psec : Skew control of RX CTL pad
- txen-skew-psec : Skew control of TX CTL pad
- rxd0-skew-psec : Skew control of RX data 0 pad
- rxd1-skew-psec : Skew control of RX data 1 pad
- rxd2-skew-psec : Skew control of RX data 2 pad
- rxd3-skew-psec : Skew control of RX data 3 pad
- txd0-skew-psec : Skew control of TX data 0 pad
- txd1-skew-psec : Skew control of TX data 1 pad
- txd2-skew-psec : Skew control of TX data 2 pad
- txd3-skew-psec : Skew control of TX data 3 pad
Examples: Examples:
mdio { mdio {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* option) any later version. * option) any later version.
* *
* Support : Micrel Phys: * Support : Micrel Phys:
* Giga phys: ksz9021, ksz9031 * Giga phys: ksz9021, ksz9031, ksz9131
* 100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041 * 100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041
* ksz8021, ksz8031, ksz8051, * ksz8021, ksz8031, ksz8051,
* ksz8081, ksz8091, * ksz8081, ksz8091,
...@@ -609,6 +609,116 @@ static int ksz9031_config_init(struct phy_device *phydev) ...@@ -609,6 +609,116 @@ static int ksz9031_config_init(struct phy_device *phydev)
return result; return result;
} }
#define KSZ9131_SKEW_5BIT_MAX 2400
#define KSZ9131_SKEW_4BIT_MAX 800
#define KSZ9131_OFFSET 700
#define KSZ9131_STEP 100
static int ksz9131_of_load_skew_values(struct phy_device *phydev,
struct device_node *of_node,
u16 reg, size_t field_sz,
char *field[], u8 numfields)
{
int val[4] = {-(1 + KSZ9131_OFFSET), -(2 + KSZ9131_OFFSET),
-(3 + KSZ9131_OFFSET), -(4 + KSZ9131_OFFSET)};
int skewval, skewmax = 0;
int matches = 0;
u16 maxval;
u16 newval;
u16 mask;
int i;
/* psec properties in dts should mean x pico seconds */
if (field_sz == 5)
skewmax = KSZ9131_SKEW_5BIT_MAX;
else
skewmax = KSZ9131_SKEW_4BIT_MAX;
for (i = 0; i < numfields; i++)
if (!of_property_read_s32(of_node, field[i], &skewval)) {
if (skewval < -KSZ9131_OFFSET)
skewval = -KSZ9131_OFFSET;
else if (skewval > skewmax)
skewval = skewmax;
val[i] = skewval + KSZ9131_OFFSET;
matches++;
}
if (!matches)
return 0;
if (matches < numfields)
newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg);
else
newval = 0;
maxval = (field_sz == 4) ? 0xf : 0x1f;
for (i = 0; i < numfields; i++)
if (val[i] != -(i + 1 + KSZ9131_OFFSET)) {
mask = 0xffff;
mask ^= maxval << (field_sz * i);
newval = (newval & mask) |
(((val[i] / KSZ9131_STEP) & maxval)
<< (field_sz * i));
}
return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval);
}
static int ksz9131_config_init(struct phy_device *phydev)
{
const struct device *dev = &phydev->mdio.dev;
struct device_node *of_node = dev->of_node;
char *clk_skews[2] = {"rxc-skew-psec", "txc-skew-psec"};
char *rx_data_skews[4] = {
"rxd0-skew-psec", "rxd1-skew-psec",
"rxd2-skew-psec", "rxd3-skew-psec"
};
char *tx_data_skews[4] = {
"txd0-skew-psec", "txd1-skew-psec",
"txd2-skew-psec", "txd3-skew-psec"
};
char *control_skews[2] = {"txen-skew-psec", "rxdv-skew-psec"};
const struct device *dev_walker;
int ret;
dev_walker = &phydev->mdio.dev;
do {
of_node = dev_walker->of_node;
dev_walker = dev_walker->parent;
} while (!of_node && dev_walker);
if (!of_node)
return 0;
ret = ksz9131_of_load_skew_values(phydev, of_node,
MII_KSZ9031RN_CLK_PAD_SKEW, 5,
clk_skews, 2);
if (ret < 0)
return ret;
ret = ksz9131_of_load_skew_values(phydev, of_node,
MII_KSZ9031RN_CONTROL_PAD_SKEW, 4,
control_skews, 2);
if (ret < 0)
return ret;
ret = ksz9131_of_load_skew_values(phydev, of_node,
MII_KSZ9031RN_RX_DATA_PAD_SKEW, 4,
rx_data_skews, 4);
if (ret < 0)
return ret;
ret = ksz9131_of_load_skew_values(phydev, of_node,
MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4,
tx_data_skews, 4);
if (ret < 0)
return ret;
return 0;
}
#define KSZ8873MLL_GLOBAL_CONTROL_4 0x06 #define KSZ8873MLL_GLOBAL_CONTROL_4 0x06
#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX BIT(6) #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX BIT(6)
#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED BIT(4) #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED BIT(4)
...@@ -974,6 +1084,23 @@ static struct phy_driver ksphy_driver[] = { ...@@ -974,6 +1084,23 @@ static struct phy_driver ksphy_driver[] = {
.get_stats = kszphy_get_stats, .get_stats = kszphy_get_stats,
.suspend = genphy_suspend, .suspend = genphy_suspend,
.resume = kszphy_resume, .resume = kszphy_resume,
}, {
.phy_id = PHY_ID_KSZ9131,
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Microchip KSZ9131 Gigabit PHY",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.driver_data = &ksz9021_type,
.probe = kszphy_probe,
.config_init = ksz9131_config_init,
.read_status = ksz9031_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
.suspend = genphy_suspend,
.resume = kszphy_resume,
}, { }, {
.phy_id = PHY_ID_KSZ8873MLL, .phy_id = PHY_ID_KSZ8873MLL,
.phy_id_mask = MICREL_PHY_ID_MASK, .phy_id_mask = MICREL_PHY_ID_MASK,
...@@ -1022,6 +1149,7 @@ MODULE_LICENSE("GPL"); ...@@ -1022,6 +1149,7 @@ MODULE_LICENSE("GPL");
static struct mdio_device_id __maybe_unused micrel_tbl[] = { static struct mdio_device_id __maybe_unused micrel_tbl[] = {
{ PHY_ID_KSZ9021, 0x000ffffe }, { PHY_ID_KSZ9021, 0x000ffffe },
{ PHY_ID_KSZ9031, MICREL_PHY_ID_MASK }, { PHY_ID_KSZ9031, MICREL_PHY_ID_MASK },
{ PHY_ID_KSZ9131, MICREL_PHY_ID_MASK },
{ PHY_ID_KSZ8001, 0x00fffffc }, { PHY_ID_KSZ8001, 0x00fffffc },
{ PHY_ID_KS8737, MICREL_PHY_ID_MASK }, { PHY_ID_KS8737, MICREL_PHY_ID_MASK },
{ PHY_ID_KSZ8021, 0x00ffffff }, { PHY_ID_KSZ8021, 0x00ffffff },
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#define PHY_ID_KSZ8081 0x00221560 #define PHY_ID_KSZ8081 0x00221560
#define PHY_ID_KSZ8061 0x00221570 #define PHY_ID_KSZ8061 0x00221570
#define PHY_ID_KSZ9031 0x00221620 #define PHY_ID_KSZ9031 0x00221620
#define PHY_ID_KSZ9131 0x00221640
#define PHY_ID_KSZ886X 0x00221430 #define PHY_ID_KSZ886X 0x00221430
#define PHY_ID_KSZ8863 0x00221435 #define PHY_ID_KSZ8863 0x00221435
......
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