1 // SPDX-License-Identifier: GPL-2.0
2 /* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */
5 #include "suni1x10gexp_regs.h"
8 static int my3126_reset(struct cphy
*cphy
, int wait
)
11 * This can be done through registers. It is not required since
12 * a full chip reset is used.
17 static int my3126_interrupt_enable(struct cphy
*cphy
)
19 schedule_delayed_work(&cphy
->phy_update
, HZ
/30);
20 t1_tpi_read(cphy
->adapter
, A_ELMER0_GPO
, &cphy
->elmer_gpo
);
24 static int my3126_interrupt_disable(struct cphy
*cphy
)
26 cancel_delayed_work_sync(&cphy
->phy_update
);
30 static int my3126_interrupt_clear(struct cphy
*cphy
)
35 #define OFFSET(REG_ADDR) (REG_ADDR << 2)
37 static int my3126_interrupt_handler(struct cphy
*cphy
)
44 adapter
= cphy
->adapter
;
46 if (cphy
->count
== 50) {
47 cphy_mdio_read(cphy
, MDIO_MMD_PMAPMD
, MDIO_STAT1
, &val
);
49 status
= cphy
->bmsr
^ val16
;
51 if (status
& MDIO_STAT1_LSTATUS
)
52 t1_link_changed(adapter
, 0);
55 /* We have only enabled link change interrupts so it
61 t1_tpi_write(adapter
, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL
),
62 SUNI1x10GEXP_BITMSK_MSTAT_SNAP
);
64 OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW
), &act_count
);
66 OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW
), &val
);
69 /* Populate elmer_gpo with the register value */
70 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
71 cphy
->elmer_gpo
= val
;
73 if ( (val
& (1 << 8)) || (val
& (1 << 19)) ||
74 (cphy
->act_count
== act_count
) || cphy
->act_on
) {
77 else if (t1_is_T1B(adapter
))
83 else if (t1_is_T1B(adapter
))
88 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
90 cphy
->elmer_gpo
= val
;
91 cphy
->act_count
= act_count
;
94 return cphy_cause_link_change
;
97 static void my3126_poll(struct work_struct
*work
)
99 struct cphy
*cphy
= container_of(work
, struct cphy
, phy_update
.work
);
101 my3126_interrupt_handler(cphy
);
104 static int my3126_set_loopback(struct cphy
*cphy
, int on
)
109 /* To check the activity LED */
110 static int my3126_get_link_status(struct cphy
*cphy
,
111 int *link_ok
, int *speed
, int *duplex
, int *fc
)
117 adapter
= cphy
->adapter
;
118 cphy_mdio_read(cphy
, MDIO_MMD_PMAPMD
, MDIO_STAT1
, &val
);
121 /* Populate elmer_gpo with the register value */
122 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
123 cphy
->elmer_gpo
= val
;
125 *link_ok
= (val16
& MDIO_STAT1_LSTATUS
);
128 /* Turn on the LED. */
131 else if (t1_is_T1B(adapter
))
134 /* Turn off the LED. */
137 else if (t1_is_T1B(adapter
))
141 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
142 cphy
->elmer_gpo
= val
;
143 *speed
= SPEED_10000
;
144 *duplex
= DUPLEX_FULL
;
146 /* need to add flow control */
148 *fc
= PAUSE_RX
| PAUSE_TX
;
153 static void my3126_destroy(struct cphy
*cphy
)
158 static const struct cphy_ops my3126_ops
= {
159 .destroy
= my3126_destroy
,
160 .reset
= my3126_reset
,
161 .interrupt_enable
= my3126_interrupt_enable
,
162 .interrupt_disable
= my3126_interrupt_disable
,
163 .interrupt_clear
= my3126_interrupt_clear
,
164 .interrupt_handler
= my3126_interrupt_handler
,
165 .get_link_status
= my3126_get_link_status
,
166 .set_loopback
= my3126_set_loopback
,
167 .mmds
= (MDIO_DEVS_PMAPMD
| MDIO_DEVS_PCS
|
171 static struct cphy
*my3126_phy_create(struct net_device
*dev
,
172 int phy_addr
, const struct mdio_ops
*mdio_ops
)
174 struct cphy
*cphy
= kzalloc(sizeof (*cphy
), GFP_KERNEL
);
179 cphy_init(cphy
, dev
, phy_addr
, &my3126_ops
, mdio_ops
);
180 INIT_DELAYED_WORK(&cphy
->phy_update
, my3126_poll
);
187 static int my3126_phy_reset(adapter_t
* adapter
)
191 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
193 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
196 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
| 4);
199 /* Now lets enable the Laser. Delay 100us */
200 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
202 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
207 const struct gphy t1_my3126_ops
= {
208 .create
= my3126_phy_create
,
209 .reset
= my3126_phy_reset