Adds support for ksz9031 PAD skew configuration over devicetree. Signed-off-by: Hubert Chaumette <hchaumette@xxxxxxxxxxxxxxxxxxx> --- drivers/net/phy/micrel.c | 167 +++++++++++++---------------------------------- 1 file changed, 44 insertions(+), 123 deletions(-) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index df56b26..c936b72 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -271,156 +271,77 @@ static int ksz9031_extended_read(struct phy_device *phydev, return phy_read(phydev, MII_KSZ9031RN_MMD_REGDATA_REG); } -/* Two 5-bit fields register */ -static int ksz9031_load_clk_skew_values(struct phy_device *phydev, - struct device_node *of_node, - char *field1, char *field2) +static int ksz9031_of_load_skew_values(struct phy_device *phydev, + struct device_node *of_node, + u16 reg, size_t field_sz, + char *field[], u8 numfields) { - int val1 = -1; - int val2 = -2; - int newval; + int val[4] = {-1, -2, -3, -4}; int matches = 0; + u16 mask; + u16 maxval; + u16 newval; + int i; - if (!of_property_read_u32(of_node, field1, &val1)) - matches++; - - if (!of_property_read_u32(of_node, field2, &val2)) - matches++; + for (i = 0; i < numfields; i++) + if (!of_property_read_u32(of_node, field[i], val + i)) + matches++; if (!matches) return 0; - if (matches < 2) - newval = ksz9031_extended_read(phydev, OP_DATA, 2, - MII_KSZ9031RN_CLK_PAD_SKEW); - else - newval = 0; - - if (val1 != -1) - newval = (newval & 0xffe0) | - ((val1 / KSZ9031_PS_TO_REG) & 0x1f); - - if (val2 != -2) - newval = (newval & 0xfc1f) | - (((val2 / KSZ9031_PS_TO_REG) & 0x1f) << 5); - - return ksz9031_extended_write(phydev, OP_DATA, 2, - MII_KSZ9031RN_CLK_PAD_SKEW, newval); -} - -/* Four 4-bit fields register */ -static int ksz9031_load_data_skew_values(struct phy_device *phydev, - struct device_node *of_node, u16 reg, - char *field1, char *field2, - char *field3, char *field4) -{ - int val1 = -1; - int val2 = -2; - int val3 = -3; - int val4 = -4; - int newval; - int matches = 0; - - if (!of_property_read_u32(of_node, field1, &val1)) - matches++; - - if (!of_property_read_u32(of_node, field2, &val2)) - matches++; - - if (!of_property_read_u32(of_node, field3, &val3)) - matches++; - - if (!of_property_read_u32(of_node, field4, &val4)) - matches++; - - if (!matches) - return 0; - - if (matches < 4) + if (matches < numfields) newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg); else newval = 0; - if (val1 != -1) - newval = (newval & 0xfff0) | - (((val1 / KSZ9031_PS_TO_REG) & 0xf) << 0); - - if (val2 != -2) - newval = (newval & 0xff0f) | - (((val2 / KSZ9031_PS_TO_REG) & 0xf) << 4); - - if (val3 != -3) - newval = (newval & 0xf0ff) | - (((val3 / KSZ9031_PS_TO_REG) & 0xf) << 8); - - if (val4 != -4) - newval = (newval & 0x0fff) | - (((val4 / KSZ9031_PS_TO_REG) & 0xf) << 12); + maxval = (field_sz == 4) ? 0xf : 0x1f; + for (i = 0; i < numfields; i++) + if (val[i] != -(i + 1)) { + mask = 0xffff; + mask ^= maxval << (field_sz * i); + newval = (newval & mask) | + (((val[i] / KSZ9031_PS_TO_REG) & maxval) + << (field_sz * i)); + } return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval); } -/* Two 4-bit fields register */ -static int ksz9031_load_ctrl_skew_values(struct phy_device *phydev, - struct device_node *of_node, - char *field1, char *field2) -{ - int val1 = -1; - int val2 = -2; - int newval; - int matches = 0; - - if (!of_property_read_u32(of_node, field1, &val1)) - matches++; - - if (!of_property_read_u32(of_node, field2, &val2)) - matches++; - - if (!matches) - return 0; - - if (matches < 2) - newval = ksz9031_extended_read(phydev, OP_DATA, 2, - MII_KSZ9031RN_CONTROL_PAD_SKEW); - else - newval = 0; - - if (val1 != -1) - newval = (newval & 0xfff0) | - (((val1 / KSZ9031_PS_TO_REG) & 0xf) << 0); - - if (val2 != -2) - newval = (newval & 0xff0f) | - (((val2 / KSZ9031_PS_TO_REG) & 0xf) << 4); - - return ksz9031_extended_write(phydev, OP_DATA, 2, - MII_KSZ9031RN_CONTROL_PAD_SKEW, newval); -} - static int ksz9031_config_init(struct phy_device *phydev) { struct device *dev = &phydev->dev; struct device_node *of_node = dev->of_node; + char *clk_skews[2] = {"rxc-skew-ps", "txc-skew-ps"}; + char *rx_data_skews[4] = { + "rxd0-skew-ps", "rxd1-skew-ps", + "rxd2-skew-ps", "rxd3-skew-ps" + }; + char *tx_data_skews[4] = { + "txd0-skew-ps", "txd1-skew-ps", + "txd2-skew-ps", "txd3-skew-ps" + }; + char *control_skews[2] = {"txen-skew-ps", "rxdv-skew-ps"}; if (!of_node && dev->parent->of_node) of_node = dev->parent->of_node; if (of_node) { - ksz9031_load_clk_skew_values(phydev, of_node, - "rxc-skew-ps", "txc-skew-ps"); + ksz9031_of_load_skew_values(phydev, of_node, + MII_KSZ9031RN_CLK_PAD_SKEW, 5, + clk_skews, 2); - ksz9031_load_data_skew_values(phydev, of_node, - MII_KSZ9031RN_RX_DATA_PAD_SKEW, - "rxd0-skew-ps", "rxd1-skew-ps", - "rxd2-skew-ps", "rxd3-skew-ps"); + ksz9031_of_load_skew_values(phydev, of_node, + MII_KSZ9031RN_CONTROL_PAD_SKEW, 4, + control_skews, 2); - ksz9031_load_data_skew_values(phydev, of_node, - MII_KSZ9031RN_TX_DATA_PAD_SKEW, - "txd0-skew-ps", "txd1-skew-ps", - "txd2-skew-ps", "txd3-skew-ps"); + ksz9031_of_load_skew_values(phydev, of_node, + MII_KSZ9031RN_RX_DATA_PAD_SKEW, 4, + rx_data_skews, 4); - ksz9031_load_ctrl_skew_values(phydev, of_node, - "txen-skew-ps", "rxdv-skew-ps"); + ksz9031_of_load_skew_values(phydev, of_node, + MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4, + tx_data_skews, 4); } return 0; } -- 1.9.2 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html