1 /* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */
4 #include "suni1x10gexp_regs.h"
7 static int my3126_reset(struct cphy
*cphy
, int wait
)
10 * This can be done through registers. It is not required since
11 * a full chip reset is used.
16 static int my3126_interrupt_enable(struct cphy
*cphy
)
18 schedule_delayed_work(&cphy
->phy_update
, HZ
/30);
19 t1_tpi_read(cphy
->adapter
, A_ELMER0_GPO
, &cphy
->elmer_gpo
);
23 static int my3126_interrupt_disable(struct cphy
*cphy
)
25 cancel_rearming_delayed_work(&cphy
->phy_update
);
29 static int my3126_interrupt_clear(struct cphy
*cphy
)
34 #define OFFSET(REG_ADDR) (REG_ADDR << 2)
36 static int my3126_interrupt_handler(struct cphy
*cphy
)
43 adapter
= cphy
->adapter
;
45 if (cphy
->count
== 50) {
46 mdio_read(cphy
, 0x1, 0x1, &val
);
48 status
= cphy
->bmsr
^ val16
;
50 if (status
& BMSR_LSTATUS
)
51 t1_link_changed(adapter
, 0);
54 /* We have only enabled link change interrupts so it
60 t1_tpi_write(adapter
, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL
),
61 SUNI1x10GEXP_BITMSK_MSTAT_SNAP
);
63 OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW
), &act_count
);
65 OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW
), &val
);
68 /* Populate elmer_gpo with the register value */
69 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
70 cphy
->elmer_gpo
= val
;
72 if ( (val
& (1 << 8)) || (val
& (1 << 19)) ||
73 (cphy
->act_count
== act_count
) || cphy
->act_on
) {
76 else if (t1_is_T1B(adapter
))
82 else if (t1_is_T1B(adapter
))
87 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
89 cphy
->elmer_gpo
= val
;
90 cphy
->act_count
= act_count
;
93 return cphy_cause_link_change
;
96 static void my3216_poll(struct work_struct
*work
)
98 struct cphy
*cphy
= container_of(work
, struct cphy
, phy_update
.work
);
100 my3126_interrupt_handler(cphy
);
103 static int my3126_set_loopback(struct cphy
*cphy
, int on
)
108 /* To check the activity LED */
109 static int my3126_get_link_status(struct cphy
*cphy
,
110 int *link_ok
, int *speed
, int *duplex
, int *fc
)
116 adapter
= cphy
->adapter
;
117 mdio_read(cphy
, 0x1, 0x1, &val
);
120 /* Populate elmer_gpo with the register value */
121 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
122 cphy
->elmer_gpo
= val
;
124 *link_ok
= (val16
& BMSR_LSTATUS
);
127 /* Turn on the LED. */
130 else if (t1_is_T1B(adapter
))
133 /* Turn off the LED. */
136 else if (t1_is_T1B(adapter
))
140 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
141 cphy
->elmer_gpo
= val
;
142 *speed
= SPEED_10000
;
143 *duplex
= DUPLEX_FULL
;
145 /* need to add flow control */
147 *fc
= PAUSE_RX
| PAUSE_TX
;
152 static void my3126_destroy(struct cphy
*cphy
)
157 static struct cphy_ops my3126_ops
= {
158 .destroy
= my3126_destroy
,
159 .reset
= my3126_reset
,
160 .interrupt_enable
= my3126_interrupt_enable
,
161 .interrupt_disable
= my3126_interrupt_disable
,
162 .interrupt_clear
= my3126_interrupt_clear
,
163 .interrupt_handler
= my3126_interrupt_handler
,
164 .get_link_status
= my3126_get_link_status
,
165 .set_loopback
= my3126_set_loopback
,
168 static struct cphy
*my3126_phy_create(adapter_t
*adapter
,
169 int phy_addr
, const struct mdio_ops
*mdio_ops
)
171 struct cphy
*cphy
= kzalloc(sizeof (*cphy
), GFP_KERNEL
);
176 cphy_init(cphy
, adapter
, phy_addr
, &my3126_ops
, mdio_ops
);
177 INIT_DELAYED_WORK(&cphy
->phy_update
, my3216_poll
);
184 static int my3126_phy_reset(adapter_t
* adapter
)
188 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
190 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
193 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
| 4);
196 /* Now lets enable the Laser. Delay 100us */
197 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
199 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
204 const struct gphy t1_my3126_ops
= {
205 .create
= my3126_phy_create
,
206 .reset
= my3126_phy_reset