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