1/* 2 * Copyright 2008-2013 Freescale Semiconductor Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * * Neither the name of Freescale Semiconductor nor the 12 * names of its contributors may be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * 16 * ALTERNATIVELY, this software may be distributed under the terms of the 17 * GNU General Public License ("GPL") as published by the Free Software 18 * Foundation, either version 2 of that License or (at your option) any 19 * later version. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34#include "fsl_fman_memac_mii_acc.h" 35 36static void write_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs, 37 uint8_t phy_addr, uint8_t reg, uint16_t data) 38{ 39 uint32_t tmp_reg; 40 41 tmp_reg = ioread32be(&mii_regs->mdio_cfg); 42 /* Leave only MDIO_CLK_DIV bits set on */ 43 tmp_reg &= MDIO_CFG_CLK_DIV_MASK; 44 /* Set maximum MDIO_HOLD value to allow phy to see 45 change of data signal */ 46 tmp_reg |= MDIO_CFG_HOLD_MASK; 47 /* Add 10G interface mode */ 48 tmp_reg |= MDIO_CFG_ENC45; 49 iowrite32be(tmp_reg, &mii_regs->mdio_cfg); 50 51 /* Wait for command completion */ 52 while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) 53 udelay(1); 54 55 /* Specify phy and register to be accessed */ 56 iowrite32be(phy_addr, &mii_regs->mdio_ctrl); 57 iowrite32be(reg, &mii_regs->mdio_addr); 58 wmb(); 59 60 while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) 61 udelay(1); 62 63 /* Write data */ 64 iowrite32be(data, &mii_regs->mdio_data); 65 wmb(); 66 67 /* Wait for write transaction end */ 68 while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) 69 udelay(1); 70} 71 72static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs, 73 uint8_t phy_addr, uint8_t reg, uint16_t *data) 74{ 75 uint32_t tmp_reg; 76 77 tmp_reg = ioread32be(&mii_regs->mdio_cfg); 78 /* Leave only MDIO_CLK_DIV bits set on */ 79 tmp_reg &= MDIO_CFG_CLK_DIV_MASK; 80 /* Set maximum MDIO_HOLD value to allow phy to see 81 change of data signal */ 82 tmp_reg |= MDIO_CFG_HOLD_MASK; 83 /* Add 10G interface mode */ 84 tmp_reg |= MDIO_CFG_ENC45; 85 iowrite32be(tmp_reg, &mii_regs->mdio_cfg); 86 87 /* Wait for command completion */ 88 while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) 89 udelay(1); 90 91 /* Specify phy and register to be accessed */ 92 iowrite32be(phy_addr, &mii_regs->mdio_ctrl); 93 iowrite32be(reg, &mii_regs->mdio_addr); 94 wmb(); 95 96 while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) 97 udelay(1); 98 99 /* Read cycle */ 100 tmp_reg = phy_addr; 101 tmp_reg |= MDIO_CTL_READ; 102 iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); 103 wmb(); 104 105 /* Wait for data to be available */ 106 while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) 107 udelay(1); 108 109 *data = (uint16_t)ioread32be(&mii_regs->mdio_data); 110 111 /* Check if there was an error */ 112 return ioread32be(&mii_regs->mdio_cfg); 113} 114 115static void write_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs, 116 uint8_t phy_addr, uint8_t reg, uint16_t data) 117{ 118 uint32_t tmp_reg; 119 120 /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ 121 tmp_reg = ioread32be(&mii_regs->mdio_cfg); 122 tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); 123 iowrite32be(tmp_reg, &mii_regs->mdio_cfg); 124 125 /* Wait for command completion */ 126 while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) 127 udelay(1); 128 129 /* Write transaction */ 130 tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT); 131 tmp_reg |= reg; 132 iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); 133 134 while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) 135 udelay(1); 136 137 iowrite32be(data, &mii_regs->mdio_data); 138 139 wmb(); 140 141 /* Wait for write transaction to end */ 142 while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) 143 udelay(1); 144} 145 146static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs, 147 uint8_t phy_addr, uint8_t reg, uint16_t *data) 148{ 149 uint32_t tmp_reg; 150 151 /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ 152 tmp_reg = ioread32be(&mii_regs->mdio_cfg); 153 tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); 154 iowrite32be(tmp_reg, &mii_regs->mdio_cfg); 155 156 /* Wait for command completion */ 157 while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) 158 udelay(1); 159 160 /* Read transaction */ 161 tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT); 162 tmp_reg |= reg; 163 tmp_reg |= MDIO_CTL_READ; 164 iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); 165 166 while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) 167 udelay(1); 168 169 /* Wait for data to be available */ 170 while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) 171 udelay(1); 172 173 *data = (uint16_t)ioread32be(&mii_regs->mdio_data); 174 175 /* Check error */ 176 return ioread32be(&mii_regs->mdio_cfg); 177} 178 179/*****************************************************************************/ 180int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map *mii_regs, 181 uint8_t phy_addr, uint8_t reg, uint16_t data, 182 enum enet_speed enet_speed) 183{ 184 /* Figure out interface type - 10G vs 1G. 185 In 10G interface both phy_addr and devAddr present. */ 186 if (enet_speed == E_ENET_SPEED_10000) 187 write_phy_reg_10g(mii_regs, phy_addr, reg, data); 188 else 189 write_phy_reg_1g(mii_regs, phy_addr, reg, data); 190 191 return 0; 192} 193 194/*****************************************************************************/ 195int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map *mii_regs, 196 uint8_t phy_addr, uint8_t reg, uint16_t *data, 197 enum enet_speed enet_speed) 198{ 199 uint32_t ans; 200 /* Figure out interface type - 10G vs 1G. 201 In 10G interface both phy_addr and devAddr present. */ 202 if (enet_speed == E_ENET_SPEED_10000) 203 ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data); 204 else 205 ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data); 206 207 if (ans & MDIO_CFG_READ_ERR) 208 return -EINVAL; 209 return 0; 210} 211 212/* ......................................................................... */ 213 214