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