diff options
Diffstat (limited to 'hw/net/fsl_etsec/miim.c')
-rw-r--r-- | hw/net/fsl_etsec/miim.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/hw/net/fsl_etsec/miim.c b/hw/net/fsl_etsec/miim.c new file mode 100644 index 0000000000..1931b74e6c --- /dev/null +++ b/hw/net/fsl_etsec/miim.c @@ -0,0 +1,146 @@ +/* + * QEMU Freescale eTSEC Emulator + * + * Copyright (c) 2011-2013 AdaCore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "etsec.h" +#include "registers.h" + +/* #define DEBUG_MIIM */ + +#define MIIM_CONTROL 0 +#define MIIM_STATUS 1 +#define MIIM_PHY_ID_1 2 +#define MIIM_PHY_ID_2 3 +#define MIIM_T2_STATUS 10 +#define MIIM_EXT_STATUS 15 + +static void miim_read_cycle(eTSEC *etsec) +{ + uint8_t phy; + uint8_t addr; + uint16_t value; + + phy = (etsec->regs[MIIMADD].value >> 8) & 0x1F; + (void)phy; /* Unreferenced */ + addr = etsec->regs[MIIMADD].value & 0x1F; + + switch (addr) { + case MIIM_CONTROL: + value = etsec->phy_control; + break; + case MIIM_STATUS: + value = etsec->phy_status; + break; + case MIIM_T2_STATUS: + value = 0x1800; /* Local and remote receivers OK */ + break; + default: + value = 0x0; + break; + }; + +#ifdef DEBUG_MIIM + qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value); +#endif + + etsec->regs[MIIMSTAT].value = value; +} + +static void miim_write_cycle(eTSEC *etsec) +{ + uint8_t phy; + uint8_t addr; + uint16_t value; + + phy = (etsec->regs[MIIMADD].value >> 8) & 0x1F; + (void)phy; /* Unreferenced */ + addr = etsec->regs[MIIMADD].value & 0x1F; + value = etsec->regs[MIIMCON].value & 0xffff; + +#ifdef DEBUG_MIIM + qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value); +#endif + + switch (addr) { + case MIIM_CONTROL: + etsec->phy_control = value & ~(0x8100); + break; + default: + break; + }; +} + +void etsec_write_miim(eTSEC *etsec, + eTSEC_Register *reg, + uint32_t reg_index, + uint32_t value) +{ + + switch (reg_index) { + + case MIIMCOM: + /* Read and scan cycle */ + + if ((!(reg->value & MIIMCOM_READ)) && (value & MIIMCOM_READ)) { + /* Read */ + miim_read_cycle(etsec); + } + reg->value = value; + break; + + case MIIMCON: + reg->value = value & 0xffff; + miim_write_cycle(etsec); + break; + + default: + /* Default handling */ + switch (reg->access) { + + case ACC_RW: + case ACC_WO: + reg->value = value; + break; + + case ACC_W1C: + reg->value &= ~value; + break; + + case ACC_RO: + default: + /* Read Only or Unknown register */ + break; + } + } + +} + +void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc) +{ + /* Set link status */ + if (nc->link_down) { + etsec->phy_status &= ~MII_SR_LINK_STATUS; + } else { + etsec->phy_status |= MII_SR_LINK_STATUS; + } +} |