xref: /qemu/hw/net/fsl_etsec/miim.c (revision eb1e7c3e514665bb948357ef39845efd9af29de1)
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