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/module.h>
17 #include <linux/types.h>
18 #include <linux/kernel.h>
19 #include <linux/sched.h>
20 #include <linux/string.h>
21 #include <linux/ptrace.h>
22 #include <linux/errno.h>
23 #include <linux/ioport.h>
24 #include <linux/slab.h>
25 #include <linux/interrupt.h>
26 #include <linux/pci.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/netdevice.h>
30 #include <linux/etherdevice.h>
31 #include <linux/skbuff.h>
32 #include <linux/spinlock.h>
33 #include <linux/mii.h>
34 #include <linux/ethtool.h>
35 #include <linux/bitops.h>
37 #include <asm/pgtable.h>
39 #include <asm/uaccess.h>
44 static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
46 immap_t *im = (immap_t *)fs_enet_immap;
47 void *dir, *dat, *ppar;
53 dir = &im->im_ioport.iop_padir;
54 dat = &im->im_ioport.iop_padat;
55 ppar = &im->im_ioport.iop_papar;
59 dir = &im->im_cpm.cp_pbdir;
60 dat = &im->im_cpm.cp_pbdat;
61 ppar = &im->im_cpm.cp_pbpar;
65 dir = &im->im_ioport.iop_pcdir;
66 dat = &im->im_ioport.iop_pcdat;
67 ppar = &im->im_ioport.iop_pcpar;
71 dir = &im->im_ioport.iop_pddir;
72 dat = &im->im_ioport.iop_pddat;
73 ppar = &im->im_ioport.iop_pdpar;
77 dir = &im->im_cpm.cp_pedir;
78 dat = &im->im_cpm.cp_pedat;
79 ppar = &im->im_cpm.cp_pepar;
83 printk(KERN_ERR DRV_MODULE_NAME
84 "Illegal port value %d!\n", port);
89 dir = (char *)dir + adv;
90 dat = (char *)dat + adv;
91 ppar = (char *)ppar + adv;
93 msk = 1 << (7 - (bit & 7));
94 if ((in_8(ppar) & msk) != 0) {
95 printk(KERN_ERR DRV_MODULE_NAME
96 "pin %d on port %d is not general purpose!\n", bit, port);
109 static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
111 iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
112 void *dir, *dat, *ppar;
118 dir = &io->iop_pdira;
119 dat = &io->iop_pdata;
120 ppar = &io->iop_ppara;
124 dir = &io->iop_pdirb;
125 dat = &io->iop_pdatb;
126 ppar = &io->iop_pparb;
130 dir = &io->iop_pdirc;
131 dat = &io->iop_pdatc;
132 ppar = &io->iop_pparc;
136 dir = &io->iop_pdird;
137 dat = &io->iop_pdatd;
138 ppar = &io->iop_ppard;
142 printk(KERN_ERR DRV_MODULE_NAME
143 "Illegal port value %d!\n", port);
148 dir = (char *)dir + adv;
149 dat = (char *)dat + adv;
150 ppar = (char *)ppar + adv;
152 msk = 1 << (7 - (bit & 7));
153 if ((in_8(ppar) & msk) != 0) {
154 printk(KERN_ERR DRV_MODULE_NAME
155 "pin %d on port %d is not general purpose!\n", bit, port);
167 static inline void bb_set(u8 *p, u8 m)
169 out_8(p, in_8(p) | m);
172 static inline void bb_clr(u8 *p, u8 m)
174 out_8(p, in_8(p) & ~m);
177 static inline int bb_read(u8 *p, u8 m)
179 return (in_8(p) & m) != 0;
182 static inline void mdio_active(struct fs_enet_mii_bus *bus)
184 bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
187 static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
189 bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
192 static inline int mdio_read(struct fs_enet_mii_bus *bus)
194 return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
197 static inline void mdio(struct fs_enet_mii_bus *bus, int what)
200 bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
202 bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
205 static inline void mdc(struct fs_enet_mii_bus *bus, int what)
208 bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
210 bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
213 static inline void mii_delay(struct fs_enet_mii_bus *bus)
215 udelay(bus->bus_info->i.bitbang.delay);
218 /* Utility to send the preamble, address, and register (common to read and write). */
219 static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
224 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
225 * The IEEE spec says this is a PHY optional requirement. The AMD
226 * 79C874 requires one after power up and one after a MII communications
227 * error. This means that we are doing more preambles than we need,
228 * but it is safer and will be much more robust.
233 for (j = 0; j < 32; j++) {
240 /* send the start bit (01) and the read opcode (10) or write (10) */
262 /* send the PHY address */
263 for (j = 0; j < 5; j++) {
265 mdio(bus, (addr & 0x10) != 0);
272 /* send the register address */
273 for (j = 0; j < 5; j++) {
275 mdio(bus, (reg & 0x10) != 0);
283 static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
287 u8 addr = phy_id & 0xff;
288 u8 reg = location & 0xff;
290 bitbang_pre(bus, 1, addr, reg);
292 /* tri-state our MDIO I/O pin so we can read */
299 /* check the turnaround bit: the PHY should be driving it to zero */
300 if (mdio_read(bus) != 0) {
301 /* PHY didn't drive TA low */
302 for (j = 0; j < 32; j++) {
315 /* read 16 bits of register data, MSB first */
317 for (j = 0; j < 16; j++) {
321 rdreg |= mdio_read(bus);
338 static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
341 u8 addr = phy_id & 0xff;
342 u8 reg = location & 0xff;
343 u16 value = val & 0xffff;
345 bitbang_pre(bus, 0, addr, reg);
347 /* send the turnaround (10) */
359 /* write 16 bits of register data, MSB first */
360 for (j = 0; j < 16; j++) {
362 mdio(bus, (value & 0x8000) != 0);
370 * Tri-state the MDIO line.
379 int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
381 const struct fs_mii_bus_info *bi = bus->bus_info;
384 r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
385 &bus->bitbang.mdio_dat,
386 &bus->bitbang.mdio_msk,
387 bi->i.bitbang.mdio_port,
388 bi->i.bitbang.mdio_bit);
392 r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
393 &bus->bitbang.mdc_dat,
394 &bus->bitbang.mdc_msk,
395 bi->i.bitbang.mdc_port,
396 bi->i.bitbang.mdc_bit);
400 bus->mii_read = mii_read;
401 bus->mii_write = mii_write;