OpenCores
URL https://opencores.org/ocsvn/xenie/xenie/trunk

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [mb_fw/] [xenie_eth_test_womtd/] [src/] [mdio.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 DFC
/******************************************************************************
2
**
3
**
4
** (C) Copyright 2017 DFC Design, s.r.o., Brno, Czech Republic
5
** Author: Marek Kvas (m.kvas@dspfpga.com)
6
**
7
****************************************************************************
8
**
9
** This file is part of Xenia Ethernet Example project.
10
**
11
** Xenia Ethernet Example project is free software: you can
12
** redistribute it and/or modify it under the terms of
13
** the GNU Lesser General Public License as published by the Free
14
** Software Foundation, either version 3 of the License, or
15
** (at your option) any later version.
16
**
17
** Xenia Ethernet Example project is distributed in the hope that
18
** it will be useful, but WITHOUT ANY WARRANTY; without even
19
** the implied warranty of MERCHANTABILITY or FITNESS FOR A
20
** PARTICULAR PURPOSE.  See the GNU Lesser General Public License
21
** for more details.
22
**
23
** You should have received a copy of the GNU Lesser General Public
24
** License along with Xenia Ethernet Example project.  If not,
25
** see <http://www.gnu.org/licenses/>.
26
****************************************************************************
27
*/
28
 
29
#include <stdint.h>
30
#include "mdio.h"
31
 
32
#define DEF_TIMEOUT  1000000
33
 
34
#define MDIO_START_DIRECT        1
35
#define MDIO_START_INDIRECT      0
36
#define MDIO_DIRECT_WRITE        1
37
#define MDIO_DIRECT_READ         2
38
#define MDIO_INDIRECT_ADDRESS    0
39
#define MDIO_INDIRECT_WRITE      1
40
#define MDIO_INDIRECT_READ       3
41
 
42
 
43
 
44
#define DPRINTF(...)
45
 
46
static int mdio_wait_busy(volatile struct mdio_struct *dev, int timeout)
47
{
48
   int i = 0;
49
 
50
   while(dev->ctrl & MDIO_BUSY)
51
   {
52
      if(i >= timeout)
53
         return -1;
54
 
55
      i++;
56
   }
57
 
58
   return 0;
59
}
60
 
61
static int mdio_wait_cmd_queue(volatile struct mdio_struct *dev, int timeout)
62
{
63
#ifndef USE_CMD_FIFO
64
        mdio_wait_busy(dev, timeout);
65
#else
66
   int i = 0;
67
 
68
   while(dev->ctrl & MDIO_CMD_FIFO_FULL)
69
   {
70
      if(i >= timeout)
71
         return -1;
72
 
73
      i++;
74
   }
75
 
76
   return 0;
77
#endif
78
}
79
 
80
 
81
 
82
 
83
int mdio_set_options(volatile struct mdio_struct *dev, unsigned int div, int preamble_suppression)
84
{
85
   if (mdio_wait_busy(dev, DEF_TIMEOUT) < 0)
86
      return -1;
87
 
88
   dev->divr = (div & 0xff) | ((preamble_suppression)? MDIO_PREAMBLE_SUPPRESSION:0);
89
   return 0;
90
}
91
 
92
/*
93
 * Send data to mdio bus it waits until data can be written to the MDIO core.
94
 * If blocking is set, it waits for completion either.
95
 */
96
int mdio_send(volatile struct mdio_struct *dev, unsigned int start_seq,
97
              unsigned int operation, unsigned int phy_addr,
98
              unsigned int reg_addr, unsigned int data, int blocking)
99
{
100
#ifdef USE_ONE_WRITE_COMMANDING
101
   unsigned int tmp;
102
#endif
103
 
104
   if (mdio_wait_cmd_queue(dev, DEF_TIMEOUT) < 0)
105
      return -1;
106
#ifndef USE_ONE_WRITE_COMMANDING
107
   dev->dout = data & 0xffff;
108
   dev->opst = ((start_seq & 0x3) << MDIO_START_SEQ_SHIFT) |
109
                ((operation & 0x3) << MDIO_OPEARTION_SHIFT);
110
   dev->addr = ((reg_addr & 0x1f) << MDIO_PHYREG_SHIFT) |
111
                ((phy_addr & 0x1f) << MDIO_PHYADDR_SHIFT);
112
 
113
   /* start process */
114
   dev->ctrl = MDIO_RUN;
115
#else
116
   tmp = MDIO_OC_RUN |
117
                 ((start_seq << MDIO_OC_START_SEQ_SHIFT)        & MDIO_OC_START_SEQ_MASK) |
118
                 ((operation << MDIO_OC_OPERATION_SHIFT)        & MDIO_OC_OPERATION_MASK) |
119
                 ((phy_addr << MDIO_OC_PHYADDR_SHIFT)           & MDIO_OC_PHYADDR_MASK) |
120
                 ((reg_addr << MDIO_OC_PHYREG_SHIFT)            & MDIO_OC_PHYREG_MASK) |
121
                 ((data << MDIO_OC_DATA_SHIFT)                          & MDIO_OC_DATA_MASK);
122
   dev->occmd = tmp;
123
#endif
124
 
125
   /* wait for completion if required */
126
   if (blocking) {
127
           if (mdio_wait_busy(dev, DEF_TIMEOUT) < 0)
128
                  return -1;
129
   }
130
 
131
   return 0;
132
}
133
 
134
/*
135
 * Tries to read from MDIO device it always waits for completion.
136
 */
137
int mdio_read(volatile struct mdio_struct *dev, unsigned int start_seq,
138
              unsigned int operation, unsigned int phy_addr,
139
              unsigned int reg_addr, unsigned int *data)
140
{
141
#ifdef USE_ONE_WRITE_COMMANDING
142
   unsigned int tmp;
143
#endif
144
 
145
   if (mdio_wait_cmd_queue(dev, DEF_TIMEOUT) < 0)
146
      return -1;
147
#ifndef USE_ONE_WRITE_COMMANDING
148
   dev->opst = ((start_seq & 0x3) << MDIO_START_SEQ_SHIFT) |
149
                ((operation & 0x3) << MDIO_OPEARTION_SHIFT);
150
   dev->addr = ((reg_addr & 0x1f) << MDIO_PHYREG_SHIFT) |
151
                ((phy_addr & 0x1f) << MDIO_PHYADDR_SHIFT);
152
   /* start process */
153
   dev->ctrl = MDIO_RUN;
154
#else
155
   tmp = MDIO_OC_RUN |
156
                 ((start_seq << MDIO_OC_START_SEQ_SHIFT)                & MDIO_OC_START_SEQ_MASK) |
157
                 ((operation << MDIO_OC_OPERATION_SHIFT)                & MDIO_OC_OPERATION_MASK) |
158
                 ((phy_addr << MDIO_OC_PHYADDR_SHIFT)                   & MDIO_OC_PHYADDR_MASK) |
159
                 ((reg_addr << MDIO_OC_PHYREG_SHIFT)                    & MDIO_OC_PHYREG_MASK);
160
   dev->occmd = tmp;
161
#endif
162
 
163
 
164
   /* wait for completion */
165
   if (mdio_wait_busy(dev, DEF_TIMEOUT) < 0)
166
      return -1;
167
 
168
   *data = dev->din;
169
 
170
   return 0;
171
 
172
}
173
 
174
int mdio_write_indirect(volatile struct mdio_struct *dev, uint16_t phyaddr,
175
                uint16_t devaddr, uint16_t regaddr, uint16_t data)
176
{
177
   /* Set address */
178
   if (mdio_send(dev, MDIO_START_INDIRECT, MDIO_INDIRECT_ADDRESS,
179
            phyaddr, devaddr, regaddr, 0) < 0)
180
   {
181
      return -1;
182
   }
183
 
184
   /* Write data */
185
   if (mdio_send(dev, MDIO_START_INDIRECT, MDIO_INDIRECT_WRITE,
186
            phyaddr, devaddr, data, 1) < 0)
187
   {
188
      return -1;
189
   }
190
   return 0;
191
}
192
 
193
int mdio_write_indirect_nonblocking(volatile struct mdio_struct *dev, uint16_t phyaddr,
194
                uint16_t devaddr, uint16_t regaddr, uint16_t data)
195
{
196
   /* Set address */
197
   if (mdio_send(dev, MDIO_START_INDIRECT, MDIO_INDIRECT_ADDRESS,
198
            phyaddr, devaddr, regaddr, 0) < 0)
199
   {
200
      return -1;
201
   }
202
 
203
   /* Write data */
204
   if (mdio_send(dev, MDIO_START_INDIRECT, MDIO_INDIRECT_WRITE,
205
            phyaddr, devaddr, data, 0) < 0)
206
   {
207
      return -1;
208
   }
209
   return 0;
210
}
211
 
212
int mdio_write_indirect_burst(volatile struct mdio_struct *dev, uint16_t phyaddr,
213
                uint16_t devaddr, uint16_t regaddr, uint8_t *data, int size)
214
{
215
        unsigned char lowByte, highByte;
216
        int buffCount;
217
 
218
   /* Size must be even */
219
   if (size % 2)
220
           return -1;
221
   /* Set address */
222
   if (mdio_send(dev, MDIO_START_INDIRECT, MDIO_INDIRECT_ADDRESS,
223
            phyaddr, devaddr, regaddr, 0) < 0)
224
   {
225
      return -1;
226
   }
227
 
228
 
229
   /* Write all data */
230
   buffCount = 0;
231
   while (buffCount < size) {
232
           lowByte = data[buffCount++];
233
           highByte = data[buffCount++];
234
 
235
           if (mdio_send(dev, MDIO_START_INDIRECT, MDIO_INDIRECT_WRITE,
236
                    phyaddr, devaddr, (((unsigned short)highByte)<<8)|lowByte, ((buffCount == size)?1:0)) < 0)
237
           {
238
              return -1;
239
           }
240
   }
241
   return 0;
242
}
243
 
244
int mdio_read_indirect(volatile struct mdio_struct *dev, uint16_t phyaddr,
245
                uint16_t devaddr, uint16_t regaddr, uint16_t *data)
246
{
247
        unsigned int tmp;
248
        /* Set address */
249
        if (mdio_send(dev, MDIO_START_INDIRECT, MDIO_INDIRECT_ADDRESS,
250
                   phyaddr, devaddr, regaddr, 0) < 0)
251
        {
252
                DPRINTF("\r\n Timed out\r\n");
253
                return -1;
254
        }
255
 
256
        /* Read data */
257
        if (mdio_read(dev, MDIO_START_INDIRECT, MDIO_INDIRECT_READ,
258
                   phyaddr, devaddr, &tmp) < 0)
259
        {
260
                DPRINTF("\r\n Timed out\r\n");
261
                return -1;
262
        }
263
 
264
        *data = tmp & 0xffff;
265
        return 0;
266
 }
267
 
268
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.