xref: /openbmc/qemu/hw/net/fsl_etsec/miim.c (revision 63dc36944383f70f1c7a20f6104966d8560300fa)
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"
266684bef1SAkihiko 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 
miim_read_cycle(eTSEC * etsec)32eb1e7c3eSFabien Chouteau static void miim_read_cycle(eTSEC *etsec)
33eb1e7c3eSFabien Chouteau {
34eb1e7c3eSFabien Chouteau     uint8_t  phy;
35eb1e7c3eSFabien Chouteau     uint8_t  addr;
36eb1e7c3eSFabien Chouteau     uint16_t value;
37eb1e7c3eSFabien Chouteau 
38eb1e7c3eSFabien Chouteau     phy  = (etsec->regs[MIIMADD].value >> 8) & 0x1F;
39eb1e7c3eSFabien Chouteau     (void)phy; /* Unreferenced */
40eb1e7c3eSFabien Chouteau     addr = etsec->regs[MIIMADD].value & 0x1F;
41eb1e7c3eSFabien Chouteau 
42eb1e7c3eSFabien Chouteau     switch (addr) {
43*65a12bb5SBernhard Beschow     case MII_BMCR:
44eb1e7c3eSFabien Chouteau         value = etsec->phy_control;
45eb1e7c3eSFabien Chouteau         break;
46*65a12bb5SBernhard Beschow     case MII_BMSR:
47eb1e7c3eSFabien Chouteau         value = etsec->phy_status;
48eb1e7c3eSFabien Chouteau         break;
49*65a12bb5SBernhard Beschow     case MII_STAT1000:
50*65a12bb5SBernhard Beschow         value = MII_STAT1000_LOK | MII_STAT1000_ROK;
51eb1e7c3eSFabien Chouteau         break;
52eb1e7c3eSFabien Chouteau     default:
53eb1e7c3eSFabien Chouteau         value = 0x0;
54eb1e7c3eSFabien Chouteau         break;
55eb1e7c3eSFabien Chouteau     };
56eb1e7c3eSFabien Chouteau 
57eb1e7c3eSFabien Chouteau #ifdef DEBUG_MIIM
58eb1e7c3eSFabien Chouteau     qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value);
59eb1e7c3eSFabien Chouteau #endif
60eb1e7c3eSFabien Chouteau 
61eb1e7c3eSFabien Chouteau     etsec->regs[MIIMSTAT].value = value;
62eb1e7c3eSFabien Chouteau }
63eb1e7c3eSFabien Chouteau 
miim_write_cycle(eTSEC * etsec)64eb1e7c3eSFabien Chouteau static void miim_write_cycle(eTSEC *etsec)
65eb1e7c3eSFabien Chouteau {
66eb1e7c3eSFabien Chouteau     uint8_t  phy;
67eb1e7c3eSFabien Chouteau     uint8_t  addr;
68eb1e7c3eSFabien Chouteau     uint16_t value;
69eb1e7c3eSFabien Chouteau 
70eb1e7c3eSFabien Chouteau     phy   = (etsec->regs[MIIMADD].value >> 8) & 0x1F;
71eb1e7c3eSFabien Chouteau     (void)phy; /* Unreferenced */
72eb1e7c3eSFabien Chouteau     addr  = etsec->regs[MIIMADD].value & 0x1F;
73eb1e7c3eSFabien Chouteau     value = etsec->regs[MIIMCON].value & 0xffff;
74eb1e7c3eSFabien Chouteau 
75eb1e7c3eSFabien Chouteau #ifdef DEBUG_MIIM
76eb1e7c3eSFabien Chouteau     qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value);
77eb1e7c3eSFabien Chouteau #endif
78eb1e7c3eSFabien Chouteau 
79eb1e7c3eSFabien Chouteau     switch (addr) {
80*65a12bb5SBernhard Beschow     case MII_BMCR:
81*65a12bb5SBernhard Beschow         etsec->phy_control = value & ~(MII_BMCR_RESET | MII_BMCR_FD);
82eb1e7c3eSFabien Chouteau         break;
83eb1e7c3eSFabien Chouteau     default:
84eb1e7c3eSFabien Chouteau         break;
85eb1e7c3eSFabien Chouteau     };
86eb1e7c3eSFabien Chouteau }
87eb1e7c3eSFabien Chouteau 
etsec_write_miim(eTSEC * etsec,eTSEC_Register * reg,uint32_t reg_index,uint32_t value)88eb1e7c3eSFabien Chouteau void etsec_write_miim(eTSEC          *etsec,
89eb1e7c3eSFabien Chouteau                       eTSEC_Register *reg,
90eb1e7c3eSFabien Chouteau                       uint32_t        reg_index,
91eb1e7c3eSFabien Chouteau                       uint32_t        value)
92eb1e7c3eSFabien Chouteau {
93eb1e7c3eSFabien Chouteau 
94eb1e7c3eSFabien Chouteau     switch (reg_index) {
95eb1e7c3eSFabien Chouteau 
96eb1e7c3eSFabien Chouteau     case MIIMCOM:
97eb1e7c3eSFabien Chouteau         /* Read and scan cycle */
98eb1e7c3eSFabien Chouteau 
99eb1e7c3eSFabien Chouteau         if ((!(reg->value & MIIMCOM_READ)) && (value & MIIMCOM_READ)) {
100eb1e7c3eSFabien Chouteau             /* Read */
101eb1e7c3eSFabien Chouteau             miim_read_cycle(etsec);
102eb1e7c3eSFabien Chouteau         }
103eb1e7c3eSFabien Chouteau         reg->value = value;
104eb1e7c3eSFabien Chouteau         break;
105eb1e7c3eSFabien Chouteau 
106eb1e7c3eSFabien Chouteau     case MIIMCON:
107eb1e7c3eSFabien Chouteau         reg->value = value & 0xffff;
108eb1e7c3eSFabien Chouteau         miim_write_cycle(etsec);
109eb1e7c3eSFabien Chouteau         break;
110eb1e7c3eSFabien Chouteau 
111eb1e7c3eSFabien Chouteau     default:
112eb1e7c3eSFabien Chouteau         /* Default handling */
113eb1e7c3eSFabien Chouteau         switch (reg->access) {
114eb1e7c3eSFabien Chouteau 
115eb1e7c3eSFabien Chouteau         case ACC_RW:
116eb1e7c3eSFabien Chouteau         case ACC_WO:
117eb1e7c3eSFabien Chouteau             reg->value = value;
118eb1e7c3eSFabien Chouteau             break;
119eb1e7c3eSFabien Chouteau 
120eb1e7c3eSFabien Chouteau         case ACC_W1C:
121eb1e7c3eSFabien Chouteau             reg->value &= ~value;
122eb1e7c3eSFabien Chouteau             break;
123eb1e7c3eSFabien Chouteau 
124eb1e7c3eSFabien Chouteau         case ACC_RO:
125eb1e7c3eSFabien Chouteau         default:
126eb1e7c3eSFabien Chouteau             /* Read Only or Unknown register */
127eb1e7c3eSFabien Chouteau             break;
128eb1e7c3eSFabien Chouteau         }
129eb1e7c3eSFabien Chouteau     }
130eb1e7c3eSFabien Chouteau 
131eb1e7c3eSFabien Chouteau }
132eb1e7c3eSFabien Chouteau 
etsec_miim_link_status(eTSEC * etsec,NetClientState * nc)133eb1e7c3eSFabien Chouteau void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc)
134eb1e7c3eSFabien Chouteau {
135eb1e7c3eSFabien Chouteau     /* Set link status */
136eb1e7c3eSFabien Chouteau     if (nc->link_down) {
1376684bef1SAkihiko Odaki         etsec->phy_status &= ~MII_BMSR_LINK_ST;
138eb1e7c3eSFabien Chouteau     } else {
1396684bef1SAkihiko Odaki         etsec->phy_status |= MII_BMSR_LINK_ST;
140eb1e7c3eSFabien Chouteau     }
141eb1e7c3eSFabien Chouteau }
142