source: rtems/c/src/lib/libbsp/arm/csb336/network/lan91c11x.c @ f3343c6e

4.104.114.84.9
Last change on this file since f3343c6e was f3343c6e, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 12, 2007 at 3:15:32 PM

2007-09-12 Joel Sherrill <joel.sherrill@…>

PR 1257/bsps

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