1eb1e7c3eSFabien Chouteau /* 2eb1e7c3eSFabien Chouteau * QEMU Freescale eTSEC Emulator 3eb1e7c3eSFabien Chouteau * 4eb1e7c3eSFabien Chouteau * Copyright (c) 2011-2013 AdaCore 5eb1e7c3eSFabien Chouteau * 6eb1e7c3eSFabien Chouteau * Permission is hereby granted, free of charge, to any person obtaining a copy 7eb1e7c3eSFabien Chouteau * of this software and associated documentation files (the "Software"), to deal 8eb1e7c3eSFabien Chouteau * in the Software without restriction, including without limitation the rights 9eb1e7c3eSFabien Chouteau * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10eb1e7c3eSFabien Chouteau * copies of the Software, and to permit persons to whom the Software is 11eb1e7c3eSFabien Chouteau * furnished to do so, subject to the following conditions: 12eb1e7c3eSFabien Chouteau * 13eb1e7c3eSFabien Chouteau * The above copyright notice and this permission notice shall be included in 14eb1e7c3eSFabien Chouteau * all copies or substantial portions of the Software. 15eb1e7c3eSFabien Chouteau * 16eb1e7c3eSFabien Chouteau * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17eb1e7c3eSFabien Chouteau * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18eb1e7c3eSFabien Chouteau * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19eb1e7c3eSFabien Chouteau * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20eb1e7c3eSFabien Chouteau * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21eb1e7c3eSFabien Chouteau * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22eb1e7c3eSFabien Chouteau * THE SOFTWARE. 23eb1e7c3eSFabien Chouteau */ 24eb1e7c3eSFabien Chouteau 25e8d40465SPeter Maydell #include "qemu/osdep.h" 26*6684bef1SAkihiko Odaki #include "hw/net/mii.h" 27eb1e7c3eSFabien Chouteau #include "etsec.h" 28eb1e7c3eSFabien Chouteau #include "registers.h" 29eb1e7c3eSFabien Chouteau 30eb1e7c3eSFabien Chouteau /* #define DEBUG_MIIM */ 31eb1e7c3eSFabien Chouteau 32eb1e7c3eSFabien Chouteau #define MIIM_CONTROL 0 33eb1e7c3eSFabien Chouteau #define MIIM_STATUS 1 34eb1e7c3eSFabien Chouteau #define MIIM_PHY_ID_1 2 35eb1e7c3eSFabien Chouteau #define MIIM_PHY_ID_2 3 36eb1e7c3eSFabien Chouteau #define MIIM_T2_STATUS 10 37eb1e7c3eSFabien Chouteau #define MIIM_EXT_STATUS 15 38eb1e7c3eSFabien Chouteau 39eb1e7c3eSFabien Chouteau static void miim_read_cycle(eTSEC *etsec) 40eb1e7c3eSFabien Chouteau { 41eb1e7c3eSFabien Chouteau uint8_t phy; 42eb1e7c3eSFabien Chouteau uint8_t addr; 43eb1e7c3eSFabien Chouteau uint16_t value; 44eb1e7c3eSFabien Chouteau 45eb1e7c3eSFabien Chouteau phy = (etsec->regs[MIIMADD].value >> 8) & 0x1F; 46eb1e7c3eSFabien Chouteau (void)phy; /* Unreferenced */ 47eb1e7c3eSFabien Chouteau addr = etsec->regs[MIIMADD].value & 0x1F; 48eb1e7c3eSFabien Chouteau 49eb1e7c3eSFabien Chouteau switch (addr) { 50eb1e7c3eSFabien Chouteau case MIIM_CONTROL: 51eb1e7c3eSFabien Chouteau value = etsec->phy_control; 52eb1e7c3eSFabien Chouteau break; 53eb1e7c3eSFabien Chouteau case MIIM_STATUS: 54eb1e7c3eSFabien Chouteau value = etsec->phy_status; 55eb1e7c3eSFabien Chouteau break; 56eb1e7c3eSFabien Chouteau case MIIM_T2_STATUS: 57eb1e7c3eSFabien Chouteau value = 0x1800; /* Local and remote receivers OK */ 58eb1e7c3eSFabien Chouteau break; 59eb1e7c3eSFabien Chouteau default: 60eb1e7c3eSFabien Chouteau value = 0x0; 61eb1e7c3eSFabien Chouteau break; 62eb1e7c3eSFabien Chouteau }; 63eb1e7c3eSFabien Chouteau 64eb1e7c3eSFabien Chouteau #ifdef DEBUG_MIIM 65eb1e7c3eSFabien Chouteau qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value); 66eb1e7c3eSFabien Chouteau #endif 67eb1e7c3eSFabien Chouteau 68eb1e7c3eSFabien Chouteau etsec->regs[MIIMSTAT].value = value; 69eb1e7c3eSFabien Chouteau } 70eb1e7c3eSFabien Chouteau 71eb1e7c3eSFabien Chouteau static void miim_write_cycle(eTSEC *etsec) 72eb1e7c3eSFabien Chouteau { 73eb1e7c3eSFabien Chouteau uint8_t phy; 74eb1e7c3eSFabien Chouteau uint8_t addr; 75eb1e7c3eSFabien Chouteau uint16_t value; 76eb1e7c3eSFabien Chouteau 77eb1e7c3eSFabien Chouteau phy = (etsec->regs[MIIMADD].value >> 8) & 0x1F; 78eb1e7c3eSFabien Chouteau (void)phy; /* Unreferenced */ 79eb1e7c3eSFabien Chouteau addr = etsec->regs[MIIMADD].value & 0x1F; 80eb1e7c3eSFabien Chouteau value = etsec->regs[MIIMCON].value & 0xffff; 81eb1e7c3eSFabien Chouteau 82eb1e7c3eSFabien Chouteau #ifdef DEBUG_MIIM 83eb1e7c3eSFabien Chouteau qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value); 84eb1e7c3eSFabien Chouteau #endif 85eb1e7c3eSFabien Chouteau 86eb1e7c3eSFabien Chouteau switch (addr) { 87eb1e7c3eSFabien Chouteau case MIIM_CONTROL: 88eb1e7c3eSFabien Chouteau etsec->phy_control = value & ~(0x8100); 89eb1e7c3eSFabien Chouteau break; 90eb1e7c3eSFabien Chouteau default: 91eb1e7c3eSFabien Chouteau break; 92eb1e7c3eSFabien Chouteau }; 93eb1e7c3eSFabien Chouteau } 94eb1e7c3eSFabien Chouteau 95eb1e7c3eSFabien Chouteau void etsec_write_miim(eTSEC *etsec, 96eb1e7c3eSFabien Chouteau eTSEC_Register *reg, 97eb1e7c3eSFabien Chouteau uint32_t reg_index, 98eb1e7c3eSFabien Chouteau uint32_t value) 99eb1e7c3eSFabien Chouteau { 100eb1e7c3eSFabien Chouteau 101eb1e7c3eSFabien Chouteau switch (reg_index) { 102eb1e7c3eSFabien Chouteau 103eb1e7c3eSFabien Chouteau case MIIMCOM: 104eb1e7c3eSFabien Chouteau /* Read and scan cycle */ 105eb1e7c3eSFabien Chouteau 106eb1e7c3eSFabien Chouteau if ((!(reg->value & MIIMCOM_READ)) && (value & MIIMCOM_READ)) { 107eb1e7c3eSFabien Chouteau /* Read */ 108eb1e7c3eSFabien Chouteau miim_read_cycle(etsec); 109eb1e7c3eSFabien Chouteau } 110eb1e7c3eSFabien Chouteau reg->value = value; 111eb1e7c3eSFabien Chouteau break; 112eb1e7c3eSFabien Chouteau 113eb1e7c3eSFabien Chouteau case MIIMCON: 114eb1e7c3eSFabien Chouteau reg->value = value & 0xffff; 115eb1e7c3eSFabien Chouteau miim_write_cycle(etsec); 116eb1e7c3eSFabien Chouteau break; 117eb1e7c3eSFabien Chouteau 118eb1e7c3eSFabien Chouteau default: 119eb1e7c3eSFabien Chouteau /* Default handling */ 120eb1e7c3eSFabien Chouteau switch (reg->access) { 121eb1e7c3eSFabien Chouteau 122eb1e7c3eSFabien Chouteau case ACC_RW: 123eb1e7c3eSFabien Chouteau case ACC_WO: 124eb1e7c3eSFabien Chouteau reg->value = value; 125eb1e7c3eSFabien Chouteau break; 126eb1e7c3eSFabien Chouteau 127eb1e7c3eSFabien Chouteau case ACC_W1C: 128eb1e7c3eSFabien Chouteau reg->value &= ~value; 129eb1e7c3eSFabien Chouteau break; 130eb1e7c3eSFabien Chouteau 131eb1e7c3eSFabien Chouteau case ACC_RO: 132eb1e7c3eSFabien Chouteau default: 133eb1e7c3eSFabien Chouteau /* Read Only or Unknown register */ 134eb1e7c3eSFabien Chouteau break; 135eb1e7c3eSFabien Chouteau } 136eb1e7c3eSFabien Chouteau } 137eb1e7c3eSFabien Chouteau 138eb1e7c3eSFabien Chouteau } 139eb1e7c3eSFabien Chouteau 140eb1e7c3eSFabien Chouteau void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc) 141eb1e7c3eSFabien Chouteau { 142eb1e7c3eSFabien Chouteau /* Set link status */ 143eb1e7c3eSFabien Chouteau if (nc->link_down) { 144*6684bef1SAkihiko Odaki etsec->phy_status &= ~MII_BMSR_LINK_ST; 145eb1e7c3eSFabien Chouteau } else { 146*6684bef1SAkihiko Odaki etsec->phy_status |= MII_BMSR_LINK_ST; 147eb1e7c3eSFabien Chouteau } 148eb1e7c3eSFabien Chouteau } 149