source: rtems/bsps/arm/csb336/net/lan91c11x.c @ a3fe23c

5
Last change on this file since a3fe23c was 031df391, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 23, 2018 at 7:53:31 AM

bsps: Move legacy network drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup arm_csb336
5 *
6 * @brief Helper functions for SMSC LAN91C11x
7 */
8
9/*
10 *  Helper functions for SMSC LAN91C11x
11 *
12 *  Copyright (c) 2004 by Cogent Computer Systems
13 *  Written by Jay Monkman <jtm@lopingdog.com>
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.org/license/LICENSE.
18 */
19
20#define __INSIDE_RTEMS_BSD_TCPIP_STACK__
21
22#include <rtems.h>
23#include "lan91c11x.h"
24
25uint16_t lan91c11x_read_reg(int reg)
26{
27    volatile uint16_t *ptr = (uint16_t *)LAN91C11X_BASE_ADDR;
28    uint16_t old_bank;
29    uint16_t val;
30    rtems_interrupt_level level;
31
32    rtems_interrupt_disable(level);
33
34    /* save the bank register */
35    old_bank = ptr[7] & 0x7;
36
37    /* set the bank register */
38    ptr[7] = (reg >> 4) & 0x7;
39
40    val = ptr[((reg & 0xf) >> 1)];
41
42    /* restore the bank register */
43    ptr[7] = old_bank;
44
45    rtems_interrupt_enable(level);
46    return val;
47}
48
49void lan91c11x_write_reg(int reg, uint16_t value)
50{
51    volatile uint16_t *ptr = (uint16_t *)LAN91C11X_BASE_ADDR;
52    uint16_t old_bank;
53    rtems_interrupt_level level;
54
55    rtems_interrupt_disable(level);
56
57    /* save the bank register */
58    old_bank = ptr[7] & 0x7;
59
60    /* set the bank register */
61    ptr[7] = (reg >> 4) & 0x7;
62
63    ptr[((reg & 0xf) >> 1)] = value;
64
65    /* restore the bank register */
66    ptr[7] = old_bank;
67
68    rtems_interrupt_enable(level);
69}
70
71uint16_t lan91c11x_read_reg_fast(int reg)
72{
73    volatile uint16_t *ptr = (uint16_t *)LAN91C11X_BASE_ADDR;
74    uint16_t val;
75
76    val = ptr[((reg & 0xf) >> 1)];
77
78    return val;
79}
80
81void lan91c11x_write_reg_fast(int reg, uint16_t value)
82{
83    volatile uint16_t *ptr = (uint16_t *)LAN91C11X_BASE_ADDR;
84
85    ptr[((reg & 0xf) >> 1)] = value;
86}
87
88
89uint16_t lan91c11x_read_phy_reg(int reg)
90{
91    int i;
92    uint16_t mask;
93    uint16_t bits[64];
94    int clk_idx = 0;
95    int input_idx = 0;
96    uint16_t phydata;
97
98    /* 32 consecutive ones on MDO to establish sync */
99    for (i = 0; i < 32; ++i) {
100        bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
101    }
102
103    /* Start code <01> */
104    bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
105    bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
106
107    /* Read command <10> */
108    bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
109    bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
110
111    /* Output the PHY address, msb first - Internal PHY is address 0 */
112    for (i = 0; i < 5; ++i) {
113        bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
114    }
115
116    /* Output the phy register number, msb first */
117    mask = 0x10;
118    for (i = 0; i < 5; ++i) {
119        if (reg & mask) {
120            bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
121        } else {
122            bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
123        }
124
125
126        /* Shift to next lowest bit */
127        mask >>= 1;
128    }
129
130    /* 1 bit time for turnaround */
131    bits[clk_idx++] = 0;
132
133    /* Input starts at this bit time */
134    input_idx = clk_idx;
135
136    /* Will input 16 bits */
137    for (i = 0; i < 16; ++i) {
138        bits[clk_idx++] = 0;
139    }
140
141    /* Final clock bit */
142    bits[clk_idx++] = 0;
143
144    /* Turn off all MII Interface bits */
145    lan91c11x_write_reg(LAN91C11X_MGMT,
146                        lan91c11x_read_reg(LAN91C11X_MGMT) & 0xfff0);
147
148    /* Clock all 64 cycles */
149    for (i = 0; i < sizeof bits; ++i) {
150        /* Clock Low - output data */
151        lan91c11x_write_reg(LAN91C11X_MGMT, bits[i]);
152        rtems_task_wake_after(1);
153
154        /* Clock Hi - input data */
155        lan91c11x_write_reg(LAN91C11X_MGMT, bits[i] | LAN91C11X_MGMT_MCLK);
156        rtems_task_wake_after(1);
157        bits[i] |= lan91c11x_read_reg(LAN91C11X_MGMT) & LAN91C11X_MGMT_MDI;
158    }
159
160    /* Return to idle state */
161    /* Set clock to low, data to low, and output tristated */
162    lan91c11x_write_reg(LAN91C11X_MGMT, lan91c11x_read_reg(LAN91C11X_MGMT) & 0xfff0);
163    rtems_task_wake_after(1);
164
165    /* Recover input data */
166    phydata = 0;
167    for (i = 0; i < 16; ++i) {
168        phydata <<= 1;
169
170        if (bits[input_idx++] & LAN91C11X_MGMT_MDI) {
171            phydata |= 0x0001;
172        }
173    }
174
175    return phydata;
176}
177
178
179
180void lan91c11x_write_phy_reg(int reg, uint16_t phydata)
181{
182    int i;
183    ushort mask;
184    ushort bits[64];
185    int clk_idx = 0;
186
187    /* 32 consecutive ones on MDO to establish sync */
188    for (i = 0; i < 32; ++i) {
189        bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
190    }
191
192    /* Start code <01> */
193    bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
194    bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
195
196    /* Write command <01> */
197    bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
198    bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
199
200    /* Output the PHY address, msb first - Internal PHY is address 0 */
201    for (i = 0; i < 5; ++i) {
202        bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
203    }
204
205    /* Output the phy register number, msb first */
206    mask = 0x10;
207    for (i = 0; i < 5; ++i) {
208        if (reg & mask) {
209            bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
210        } else {
211            bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
212        }
213
214        /* Shift to next lowest bit */
215        mask >>= 1;
216    }
217
218    /* 2 extra bit times for turnaround */
219    bits[clk_idx++] = 0;
220    bits[clk_idx++] = 0;
221
222    /* Write out 16 bits of data, msb first */
223    mask = 0x8000;
224    for (i = 0; i < 16; ++i) {
225        if (phydata & mask) {
226            bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO;
227        } else {
228            bits[clk_idx++] = LAN91C11X_MGMT_MDOE;
229        }
230
231        /* Shift to next lowest bit */
232        mask >>= 1;
233    }
234
235    /* Turn off all MII Interface bits */
236    lan91c11x_write_reg(LAN91C11X_MGMT,
237                        lan91c11x_read_reg(LAN91C11X_MGMT) & 0xfff0);
238
239    /* Clock all 64 cycles */
240    for (i = 0; i < sizeof bits; ++i) {
241        /* Clock Low - output data */
242        lan91c11x_write_reg(LAN91C11X_MGMT, bits[i]);
243        rtems_task_wake_after(1);
244
245        /* Clock Hi - input data */
246        lan91c11x_write_reg(LAN91C11X_MGMT, bits[i] | LAN91C11X_MGMT_MCLK);
247        rtems_task_wake_after(1);
248        bits[i] |= lan91c11x_read_reg(LAN91C11X_MGMT) & LAN91C11X_MGMT_MDI;
249    }
250
251    /* Return to idle state */
252    /* Set clock to low, data to low, and output tristated */
253    lan91c11x_write_reg(LAN91C11X_MGMT,
254                        lan91c11x_read_reg(LAN91C11X_MGMT) & 0xfff0);
255    rtems_task_wake_after(1);
256
257}
258
259
260
Note: See TracBrowser for help on using the repository browser.