revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / emac / emac_hw.c
blob76cab374f9e18544953ecb819a707585c476732f
1 #define DEBUG 1
2 #include <inttypes.h>
3 #include <aros/debug.h>
4 #include <asm/amcc440.h>
5 #include <asm/io.h>
6 #include "emac.h"
8 void EMACIRQHandler(struct EMACBase *EMACBase, struct EMACUnit *unit)
10 if (unit)
12 D(bug("[EMAC%d] IRQ Handler\n", unit->eu_UnitNum));
16 void EMAC_Startup(struct EMACUnit *unit)
18 uint32_t tmp;
20 D(bug("[EMAC%d] Startup\n", unit->eu_UnitNum));
22 tmp = inl((uint32_t*)(unit->eu_IOBase + EMAC_IAH));
24 unit->eu_DevAddr[0] = unit->eu_OrgAddr[0] = (tmp >> 8) & 0xff;
25 unit->eu_DevAddr[1] = unit->eu_OrgAddr[1] = (tmp >> 0) & 0xff;
27 tmp = inl((uint32_t*)(unit->eu_IOBase + EMAC_IAL));
29 unit->eu_DevAddr[2] = unit->eu_OrgAddr[2] = (tmp >> 24) & 0xff;
30 unit->eu_DevAddr[3] = unit->eu_OrgAddr[3] = (tmp >> 16) & 0xff;
31 unit->eu_DevAddr[4] = unit->eu_OrgAddr[4] = (tmp >> 8) & 0xff;
32 unit->eu_DevAddr[5] = unit->eu_OrgAddr[5] = (tmp >> 0) & 0xff;
33 D(bug("[EMAC%d] HW addr=%02x:%02x:%02x:%02x:%02x:%02x\n", unit->eu_UnitNum,
34 unit->eu_DevAddr[0],unit->eu_DevAddr[1],
35 unit->eu_DevAddr[2],unit->eu_DevAddr[3],
36 unit->eu_DevAddr[4],unit->eu_DevAddr[5]));
39 int EMAC_miiphy_read(struct EMACUnit *unit, uint8_t reg, uint16_t *value)
41 unsigned long sta_reg; /* STA scratch area */
42 unsigned long i;
44 /* see if it is ready for 1000 nsec */
45 i = 0;
47 /* see if it is ready for sec */
48 while ((inl (EMAC_STACR + unit->eu_IOBase) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
49 unit->udelay (unit, 7);
50 if (i > 5) {
51 D({
52 sta_reg = inl (EMAC_STACR + unit->eu_IOBase);
53 bug ("[EMAC%d] read : EMAC_STACR=0x%0x\n", unit->eu_UnitNum, sta_reg); /* test-only */
54 bug ("[EMAC%d] read err 1\n", unit->eu_UnitNum);
56 return -1;
58 i++;
60 sta_reg = reg; /* reg address */
62 sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ;
64 sta_reg = sta_reg | (unit->eu_PHYAddr << 5); /* Phy address */
65 sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
66 outl (sta_reg, EMAC_STACR + unit->eu_IOBase);
67 D(bug("[EMAC%d] a2: write: EMAC_STACR=0x%0x\n", unit->eu_UnitNum, sta_reg));
69 sta_reg = inl (EMAC_STACR + unit->eu_IOBase);
70 D(bug("[EMAC%d] a21: read: EMAC_STACR=0x%0x\n", unit->eu_UnitNum, sta_reg));
71 i = 0;
72 while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
73 unit->udelay (unit, 7);
74 if (i > 5) {
75 return -1;
77 i++;
78 sta_reg = inl (EMAC_STACR + unit->eu_IOBase);
79 D(bug("[EMAC%d] a22: read: EMAC_STACR=0x%0x\n", unit->eu_UnitNum, sta_reg));
81 if ((sta_reg & EMAC_STACR_PHYE) != 0) {
82 return -1;
85 // *value = *(uint16_t *) (&sta_reg);
86 *value = sta_reg >> 16;
87 return 0;
90 int EMAC_miiphy_write(struct EMACUnit *unit, uint8_t reg, uint16_t value)
92 unsigned long sta_reg; /* STA scratch area */
93 unsigned long i;
95 /* see if it is ready for 1000 nsec */
96 i = 0;
98 while ((inl (EMAC_STACR + unit->eu_IOBase) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
99 if (i > 5)
100 return -1;
101 unit->udelay (unit, 7);
102 i++;
104 sta_reg = 0;
105 sta_reg = reg; /* reg address */
107 sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ;
109 sta_reg = sta_reg | ((unsigned long) unit->eu_PHYAddr << 5);/* Phy address */
110 sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
111 sta_reg = ((uint32_t)(value)) << 16 | sta_reg;
112 // memcpy (&sta_reg, &value, 2); /* put in data */
114 outl (sta_reg, EMAC_STACR + unit->eu_IOBase);
116 /* wait for completion */
117 i = 0;
118 sta_reg = inl (EMAC_STACR + unit->eu_IOBase);
119 D(bug("[EMAC%d] a31: read : EMAC_STACR=0x%0x\n", unit->eu_UnitNum, sta_reg));
121 while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
122 unit->udelay (unit, 7);
123 if (i > 5)
124 return -1;
125 i++;
126 sta_reg = inl (EMAC_STACR + unit->eu_IOBase);
127 D(bug("[EMAC%d] a32: read : EMAC_STACR=0x%0x\n", unit->eu_UnitNum, sta_reg));
130 if ((sta_reg & EMAC_STACR_PHYE) != 0)
131 return -1;
132 return 0;
135 int EMAC_miiphy_reset(struct EMACUnit *unit)
137 uint16_t reg;
138 uint32_t loop_cnt;
140 if (EMAC_miiphy_read (unit, PHY_BMCR, &reg) != 0) {
141 D(bug("[EMAC%d] PHY status read failed\n", unit->eu_UnitNum));
142 return -1;
144 if (EMAC_miiphy_write (unit, PHY_BMCR, reg | 0x8000) != 0) {
145 D(bug("[EMAC%d] PHY reset failed\n", unit->eu_UnitNum));
146 return (-1);
149 unit->udelay(unit, 1000);
152 * Poll the control register for the reset bit to go to 0 (it is
153 * auto-clearing). This should happen within 0.5 seconds per the
154 * IEEE spec.
156 loop_cnt = 0;
157 reg = 0x8000;
158 while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) {
159 if (EMAC_miiphy_read (unit, PHY_BMCR, &reg) != 0) {
160 D(bug("[EMAC%d] PHY status read failed\n", unit->eu_UnitNum));
161 return (-1);
164 if ((reg & 0x8000) == 0) {
165 return (0);
166 } else {
167 D(bug("[EMAC%d] PHY reset timed out\n", unit->eu_UnitNum));
168 return (-1);
170 return (0);
173 int EMAC_miiphy_speed(struct EMACUnit *unit)
175 uint16_t bmcr, anlpar;
177 /* Check Basic Management Control Register first. */
178 if (EMAC_miiphy_read (unit, PHY_BMCR, &bmcr)) {
179 D(bug("[EMAC%d] PHY speed", unit->eu_UnitNum));
180 goto miiphy_read_failed;
182 /* Check if auto-negotiation is on. */
183 if (bmcr & PHY_BMCR_AUTON) {
184 /* Get auto-negotiation results. */
185 if (EMAC_miiphy_read (unit, PHY_ANLPAR, &anlpar)) {
186 D(bug("[EMAC%d] PHY AN speed", unit->eu_UnitNum));
187 goto miiphy_read_failed;
189 return (anlpar & PHY_ANLPAR_100) ? _100BASET : _10BASET;
191 /* Get speed from basic control settings. */
192 return (bmcr & PHY_BMCR_100MB) ? _100BASET : _10BASET;
194 miiphy_read_failed:
195 D(bug(" read failed, assuming 10BASE-T\n"));
196 return _10BASET;
199 int EMAC_miiphy_duplex(struct EMACUnit *unit)
201 uint16_t bmcr, anlpar;
203 /* Check Basic Management Control Register first. */
204 if (EMAC_miiphy_read(unit, PHY_BMCR, &bmcr)) {
205 D(bug("[EMAC%d] PHY duplex", unit->eu_UnitNum));
206 goto miiphy_read_failed;
208 /* Check if auto-negotiation is on. */
209 if (bmcr & PHY_BMCR_AUTON) {
210 /* Get auto-negotiation results. */
211 if (EMAC_miiphy_read(unit, PHY_ANLPAR, &anlpar)) {
212 D(bug("[EMAC%d] PHY AN duplex", unit->eu_UnitNum));
213 goto miiphy_read_failed;
215 return (anlpar & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) ?
216 FULL : HALF;
218 /* Get speed from basic control settings. */
219 return (bmcr & PHY_BMCR_DPLX) ? FULL : HALF;
221 miiphy_read_failed:
222 D(bug(" read failed, assuming half duplex\n"));
223 return HALF;
226 int EMAC_miiphy_link(struct EMACUnit *unit)
228 uint16_t reg;
230 EMAC_miiphy_read(unit, PHY_BMSR, &reg);
231 if (EMAC_miiphy_read(unit, PHY_BMSR, &reg))
233 D(bug("[EMAC%d] PHY_BMSR read failed\n", unit->eu_UnitNum));
234 return 0;
237 if (reg & PHY_BMSR_LS)
238 return 1;
239 else
240 return 0;
243 int EMAC_phy_setup_aneg (struct EMACUnit *unit)
245 unsigned short ctl, adv;
247 /* Setup standard advertise */
248 EMAC_miiphy_read (unit, PHY_ANAR, &adv);
249 adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 |
250 PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD |
251 PHY_ANLPAR_10);
252 EMAC_miiphy_write (unit, PHY_ANAR, adv);
254 EMAC_miiphy_read (unit, PHY_1000BTCR, &adv);
255 adv |= (0x0300);
256 EMAC_miiphy_write (unit, PHY_1000BTCR, adv);
258 /* Start/Restart aneg */
259 EMAC_miiphy_read (unit, PHY_BMCR, &ctl);
260 ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
261 EMAC_miiphy_write (unit, PHY_BMCR, ctl);
263 return 0;