2 * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
4 * Copyright (c) 2003 Intracom S.A.
5 * by Pantelis Antoniou <panto@intracom.gr>
7 * 2005 (c) MontaVista Software, Inc.
8 * Vitaly Bordug <vbordug@ru.mvista.com>
10 * This file is licensed under the terms of the GNU General Public License
11 * version 2. This program is licensed "as is" without any warranty of any
12 * kind, whether express or implied.
16 #include <linux/config.h>
17 #include <linux/module.h>
18 #include <linux/types.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/string.h>
22 #include <linux/ptrace.h>
23 #include <linux/errno.h>
24 #include <linux/ioport.h>
25 #include <linux/slab.h>
26 #include <linux/interrupt.h>
27 #include <linux/pci.h>
28 #include <linux/init.h>
29 #include <linux/delay.h>
30 #include <linux/netdevice.h>
31 #include <linux/etherdevice.h>
32 #include <linux/skbuff.h>
33 #include <linux/spinlock.h>
34 #include <linux/mii.h>
35 #include <linux/ethtool.h>
36 #include <linux/bitops.h>
38 #include <asm/pgtable.h>
40 #include <asm/uaccess.h>
45 static int bitbang_prep_bit(u8
**dirp
, u8
**datp
, u8
*mskp
, int port
, int bit
)
47 immap_t
*im
= (immap_t
*)fs_enet_immap
;
48 void *dir
, *dat
, *ppar
;
54 dir
= &im
->im_ioport
.iop_padir
;
55 dat
= &im
->im_ioport
.iop_padat
;
56 ppar
= &im
->im_ioport
.iop_papar
;
60 dir
= &im
->im_cpm
.cp_pbdir
;
61 dat
= &im
->im_cpm
.cp_pbdat
;
62 ppar
= &im
->im_cpm
.cp_pbpar
;
66 dir
= &im
->im_ioport
.iop_pcdir
;
67 dat
= &im
->im_ioport
.iop_pcdat
;
68 ppar
= &im
->im_ioport
.iop_pcpar
;
72 dir
= &im
->im_ioport
.iop_pddir
;
73 dat
= &im
->im_ioport
.iop_pddat
;
74 ppar
= &im
->im_ioport
.iop_pdpar
;
78 dir
= &im
->im_cpm
.cp_pedir
;
79 dat
= &im
->im_cpm
.cp_pedat
;
80 ppar
= &im
->im_cpm
.cp_pepar
;
84 printk(KERN_ERR DRV_MODULE_NAME
85 "Illegal port value %d!\n", port
);
90 dir
= (char *)dir
+ adv
;
91 dat
= (char *)dat
+ adv
;
92 ppar
= (char *)ppar
+ adv
;
94 msk
= 1 << (7 - (bit
& 7));
95 if ((in_8(ppar
) & msk
) != 0) {
96 printk(KERN_ERR DRV_MODULE_NAME
97 "pin %d on port %d is not general purpose!\n", bit
, port
);
110 static int bitbang_prep_bit(u8
**dirp
, u8
**datp
, u8
*mskp
, int port
, int bit
)
112 iop_cpm2_t
*io
= &((cpm2_map_t
*)fs_enet_immap
)->im_ioport
;
113 void *dir
, *dat
, *ppar
;
119 dir
= &io
->iop_pdira
;
120 dat
= &io
->iop_pdata
;
121 ppar
= &io
->iop_ppara
;
125 dir
= &io
->iop_pdirb
;
126 dat
= &io
->iop_pdatb
;
127 ppar
= &io
->iop_pparb
;
131 dir
= &io
->iop_pdirc
;
132 dat
= &io
->iop_pdatc
;
133 ppar
= &io
->iop_pparc
;
137 dir
= &io
->iop_pdird
;
138 dat
= &io
->iop_pdatd
;
139 ppar
= &io
->iop_ppard
;
143 printk(KERN_ERR DRV_MODULE_NAME
144 "Illegal port value %d!\n", port
);
149 dir
= (char *)dir
+ adv
;
150 dat
= (char *)dat
+ adv
;
151 ppar
= (char *)ppar
+ adv
;
153 msk
= 1 << (7 - (bit
& 7));
154 if ((in_8(ppar
) & msk
) != 0) {
155 printk(KERN_ERR DRV_MODULE_NAME
156 "pin %d on port %d is not general purpose!\n", bit
, port
);
168 static inline void bb_set(u8
*p
, u8 m
)
170 out_8(p
, in_8(p
) | m
);
173 static inline void bb_clr(u8
*p
, u8 m
)
175 out_8(p
, in_8(p
) & ~m
);
178 static inline int bb_read(u8
*p
, u8 m
)
180 return (in_8(p
) & m
) != 0;
183 static inline void mdio_active(struct fs_enet_mii_bus
*bus
)
185 bb_set(bus
->bitbang
.mdio_dir
, bus
->bitbang
.mdio_msk
);
188 static inline void mdio_tristate(struct fs_enet_mii_bus
*bus
)
190 bb_clr(bus
->bitbang
.mdio_dir
, bus
->bitbang
.mdio_msk
);
193 static inline int mdio_read(struct fs_enet_mii_bus
*bus
)
195 return bb_read(bus
->bitbang
.mdio_dat
, bus
->bitbang
.mdio_msk
);
198 static inline void mdio(struct fs_enet_mii_bus
*bus
, int what
)
201 bb_set(bus
->bitbang
.mdio_dat
, bus
->bitbang
.mdio_msk
);
203 bb_clr(bus
->bitbang
.mdio_dat
, bus
->bitbang
.mdio_msk
);
206 static inline void mdc(struct fs_enet_mii_bus
*bus
, int what
)
209 bb_set(bus
->bitbang
.mdc_dat
, bus
->bitbang
.mdc_msk
);
211 bb_clr(bus
->bitbang
.mdc_dat
, bus
->bitbang
.mdc_msk
);
214 static inline void mii_delay(struct fs_enet_mii_bus
*bus
)
216 udelay(bus
->bus_info
->i
.bitbang
.delay
);
219 /* Utility to send the preamble, address, and register (common to read and write). */
220 static void bitbang_pre(struct fs_enet_mii_bus
*bus
, int read
, u8 addr
, u8 reg
)
225 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
226 * The IEEE spec says this is a PHY optional requirement. The AMD
227 * 79C874 requires one after power up and one after a MII communications
228 * error. This means that we are doing more preambles than we need,
229 * but it is safer and will be much more robust.
234 for (j
= 0; j
< 32; j
++) {
241 /* send the start bit (01) and the read opcode (10) or write (10) */
263 /* send the PHY address */
264 for (j
= 0; j
< 5; j
++) {
266 mdio(bus
, (addr
& 0x10) != 0);
273 /* send the register address */
274 for (j
= 0; j
< 5; j
++) {
276 mdio(bus
, (reg
& 0x10) != 0);
284 static int mii_read(struct fs_enet_mii_bus
*bus
, int phy_id
, int location
)
288 u8 addr
= phy_id
& 0xff;
289 u8 reg
= location
& 0xff;
291 bitbang_pre(bus
, 1, addr
, reg
);
293 /* tri-state our MDIO I/O pin so we can read */
300 /* check the turnaround bit: the PHY should be driving it to zero */
301 if (mdio_read(bus
) != 0) {
302 /* PHY didn't drive TA low */
303 for (j
= 0; j
< 32; j
++) {
316 /* read 16 bits of register data, MSB first */
318 for (j
= 0; j
< 16; j
++) {
322 rdreg
|= mdio_read(bus
);
339 static void mii_write(struct fs_enet_mii_bus
*bus
, int phy_id
, int location
, int val
)
342 u8 addr
= phy_id
& 0xff;
343 u8 reg
= location
& 0xff;
344 u16 value
= val
& 0xffff;
346 bitbang_pre(bus
, 0, addr
, reg
);
348 /* send the turnaround (10) */
360 /* write 16 bits of register data, MSB first */
361 for (j
= 0; j
< 16; j
++) {
363 mdio(bus
, (value
& 0x8000) != 0);
371 * Tri-state the MDIO line.
380 int fs_mii_bitbang_init(struct fs_enet_mii_bus
*bus
)
382 const struct fs_mii_bus_info
*bi
= bus
->bus_info
;
385 r
= bitbang_prep_bit(&bus
->bitbang
.mdio_dir
,
386 &bus
->bitbang
.mdio_dat
,
387 &bus
->bitbang
.mdio_msk
,
388 bi
->i
.bitbang
.mdio_port
,
389 bi
->i
.bitbang
.mdio_bit
);
393 r
= bitbang_prep_bit(&bus
->bitbang
.mdc_dir
,
394 &bus
->bitbang
.mdc_dat
,
395 &bus
->bitbang
.mdc_msk
,
396 bi
->i
.bitbang
.mdc_port
,
397 bi
->i
.bitbang
.mdc_bit
);
401 bus
->mii_read
= mii_read
;
402 bus
->mii_write
= mii_write
;