diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c')
-rwxr-xr-x | drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c new file mode 100755 index 0000000..ccda11e --- /dev/null +++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c @@ -0,0 +1,213 @@ +/* + * Copyright 2008-2013 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "fsl_fman_memac_mii_acc.h" + +static void write_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs, + uint8_t phy_addr, uint8_t reg, uint16_t data) +{ + uint32_t tmp_reg; + + tmp_reg = ioread32be(&mii_regs->mdio_cfg); + /* Leave only MDIO_CLK_DIV bits set on */ + tmp_reg &= MDIO_CFG_CLK_DIV_MASK; + /* Set maximum MDIO_HOLD value to allow phy to see + change of data signal */ + tmp_reg |= MDIO_CFG_HOLD_MASK; + /* Add 10G interface mode */ + tmp_reg |= MDIO_CFG_ENC45; + iowrite32be(tmp_reg, &mii_regs->mdio_cfg); + + /* Wait for command completion */ + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Specify phy and register to be accessed */ + iowrite32be(phy_addr, &mii_regs->mdio_ctrl); + iowrite32be(reg, &mii_regs->mdio_addr); + wmb(); + + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Write data */ + iowrite32be(data, &mii_regs->mdio_data); + wmb(); + + /* Wait for write transaction end */ + while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) + udelay(1); +} + +static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs, + uint8_t phy_addr, uint8_t reg, uint16_t *data) +{ + uint32_t tmp_reg; + + tmp_reg = ioread32be(&mii_regs->mdio_cfg); + /* Leave only MDIO_CLK_DIV bits set on */ + tmp_reg &= MDIO_CFG_CLK_DIV_MASK; + /* Set maximum MDIO_HOLD value to allow phy to see + change of data signal */ + tmp_reg |= MDIO_CFG_HOLD_MASK; + /* Add 10G interface mode */ + tmp_reg |= MDIO_CFG_ENC45; + iowrite32be(tmp_reg, &mii_regs->mdio_cfg); + + /* Wait for command completion */ + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Specify phy and register to be accessed */ + iowrite32be(phy_addr, &mii_regs->mdio_ctrl); + iowrite32be(reg, &mii_regs->mdio_addr); + wmb(); + + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Read cycle */ + tmp_reg = phy_addr; + tmp_reg |= MDIO_CTL_READ; + iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); + wmb(); + + /* Wait for data to be available */ + while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) + udelay(1); + + *data = (uint16_t)ioread32be(&mii_regs->mdio_data); + + /* Check if there was an error */ + return ioread32be(&mii_regs->mdio_cfg); +} + +static void write_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs, + uint8_t phy_addr, uint8_t reg, uint16_t data) +{ + uint32_t tmp_reg; + + /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ + tmp_reg = ioread32be(&mii_regs->mdio_cfg); + tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); + iowrite32be(tmp_reg, &mii_regs->mdio_cfg); + + /* Wait for command completion */ + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Write transaction */ + tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT); + tmp_reg |= reg; + iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); + + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + iowrite32be(data, &mii_regs->mdio_data); + + wmb(); + + /* Wait for write transaction to end */ + while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) + udelay(1); +} + +static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs, + uint8_t phy_addr, uint8_t reg, uint16_t *data) +{ + uint32_t tmp_reg; + + /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ + tmp_reg = ioread32be(&mii_regs->mdio_cfg); + tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); + iowrite32be(tmp_reg, &mii_regs->mdio_cfg); + + /* Wait for command completion */ + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Read transaction */ + tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT); + tmp_reg |= reg; + tmp_reg |= MDIO_CTL_READ; + iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); + + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Wait for data to be available */ + while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) + udelay(1); + + *data = (uint16_t)ioread32be(&mii_regs->mdio_data); + + /* Check error */ + return ioread32be(&mii_regs->mdio_cfg); +} + +/*****************************************************************************/ +int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map *mii_regs, + uint8_t phy_addr, uint8_t reg, uint16_t data, + enum enet_speed enet_speed) +{ + /* Figure out interface type - 10G vs 1G. + In 10G interface both phy_addr and devAddr present. */ + if (enet_speed == E_ENET_SPEED_10000) + write_phy_reg_10g(mii_regs, phy_addr, reg, data); + else + write_phy_reg_1g(mii_regs, phy_addr, reg, data); + + return 0; +} + +/*****************************************************************************/ +int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map *mii_regs, + uint8_t phy_addr, uint8_t reg, uint16_t *data, + enum enet_speed enet_speed) +{ + uint32_t ans; + /* Figure out interface type - 10G vs 1G. + In 10G interface both phy_addr and devAddr present. */ + if (enet_speed == E_ENET_SPEED_10000) + ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data); + else + ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data); + + if (ans & MDIO_CFG_READ_ERR) + return -EINVAL; + return 0; +} + +/* ......................................................................... */ + |