1 /* 2 * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. 3 * 4 * Copyright (c) 2003 Intracom S.A. 5 * by Pantelis Antoniou <panto@intracom.gr> 6 * 7 * 2005 (c) MontaVista Software, Inc. 8 * Vitaly Bordug <vbordug@ru.mvista.com> 9 * 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. 13 */ 14 15 #include <linux/module.h> 16 #include <linux/types.h> 17 #include <linux/kernel.h> 18 #include <linux/string.h> 19 #include <linux/ptrace.h> 20 #include <linux/errno.h> 21 #include <linux/ioport.h> 22 #include <linux/slab.h> 23 #include <linux/interrupt.h> 24 #include <linux/delay.h> 25 #include <linux/netdevice.h> 26 #include <linux/etherdevice.h> 27 #include <linux/skbuff.h> 28 #include <linux/spinlock.h> 29 #include <linux/mii.h> 30 #include <linux/ethtool.h> 31 #include <linux/bitops.h> 32 #include <linux/platform_device.h> 33 #include <linux/property.h> 34 #include <linux/of.h> 35 #include <linux/of_address.h> 36 #include <linux/of_mdio.h> 37 #include <linux/pgtable.h> 38 39 #include <asm/irq.h> 40 #include <linux/uaccess.h> 41 #include <asm/mpc5xxx.h> 42 43 #include "fs_enet.h" 44 #include "fec.h" 45 46 /* Make MII read/write commands for the FEC. 47 */ 48 #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) 49 #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff)) 50 #define mk_mii_end 0 51 52 #define FEC_MII_LOOPS 10000 53 54 static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) 55 { 56 struct fec_info* fec = bus->priv; 57 struct fec __iomem *fecp = fec->fecp; 58 int i, ret = -1; 59 60 BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); 61 62 /* Add PHY address to register command. */ 63 out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location)); 64 65 for (i = 0; i < FEC_MII_LOOPS; i++) 66 if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) 67 break; 68 69 if (i < FEC_MII_LOOPS) { 70 out_be32(&fecp->fec_ievent, FEC_ENET_MII); 71 ret = in_be32(&fecp->fec_mii_data) & 0xffff; 72 } 73 74 return ret; 75 } 76 77 static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) 78 { 79 struct fec_info* fec = bus->priv; 80 struct fec __iomem *fecp = fec->fecp; 81 int i; 82 83 /* this must never happen */ 84 BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); 85 86 /* Add PHY address to register command. */ 87 out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val)); 88 89 for (i = 0; i < FEC_MII_LOOPS; i++) 90 if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) 91 break; 92 93 if (i < FEC_MII_LOOPS) 94 out_be32(&fecp->fec_ievent, FEC_ENET_MII); 95 96 return 0; 97 98 } 99 100 static int fs_enet_mdio_probe(struct platform_device *ofdev) 101 { 102 struct resource res; 103 struct mii_bus *new_bus; 104 struct fec_info *fec; 105 int (*get_bus_freq)(struct device *); 106 int ret = -ENOMEM, clock, speed; 107 108 get_bus_freq = device_get_match_data(&ofdev->dev); 109 110 new_bus = mdiobus_alloc(); 111 if (!new_bus) 112 goto out; 113 114 fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL); 115 if (!fec) 116 goto out_mii; 117 118 new_bus->priv = fec; 119 new_bus->name = "FEC MII Bus"; 120 new_bus->read = &fs_enet_fec_mii_read; 121 new_bus->write = &fs_enet_fec_mii_write; 122 123 ret = of_address_to_resource(ofdev->dev.of_node, 0, &res); 124 if (ret) 125 goto out_res; 126 127 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%pap", &res.start); 128 129 fec->fecp = ioremap(res.start, resource_size(&res)); 130 if (!fec->fecp) { 131 ret = -ENOMEM; 132 goto out_fec; 133 } 134 135 if (get_bus_freq) { 136 clock = get_bus_freq(&ofdev->dev); 137 if (!clock) { 138 /* Use maximum divider if clock is unknown */ 139 dev_warn(&ofdev->dev, "could not determine IPS clock\n"); 140 clock = 0x3F * 5000000; 141 } 142 } else 143 clock = ppc_proc_freq; 144 145 /* 146 * Scale for a MII clock <= 2.5 MHz 147 * Note that only 6 bits (25:30) are available for MII speed. 148 */ 149 speed = (clock + 4999999) / 5000000; 150 if (speed > 0x3F) { 151 speed = 0x3F; 152 dev_err(&ofdev->dev, 153 "MII clock (%d Hz) exceeds max (2.5 MHz)\n", 154 clock / speed); 155 } 156 157 fec->mii_speed = speed << 1; 158 159 setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); 160 setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | 161 FEC_ECNTRL_ETHER_EN); 162 out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII); 163 clrsetbits_be32(&fec->fecp->fec_mii_speed, 0x7E, fec->mii_speed); 164 165 new_bus->phy_mask = ~0; 166 167 new_bus->parent = &ofdev->dev; 168 platform_set_drvdata(ofdev, new_bus); 169 170 ret = of_mdiobus_register(new_bus, ofdev->dev.of_node); 171 if (ret) 172 goto out_unmap_regs; 173 174 return 0; 175 176 out_unmap_regs: 177 iounmap(fec->fecp); 178 out_res: 179 out_fec: 180 kfree(fec); 181 out_mii: 182 mdiobus_free(new_bus); 183 out: 184 return ret; 185 } 186 187 static void fs_enet_mdio_remove(struct platform_device *ofdev) 188 { 189 struct mii_bus *bus = platform_get_drvdata(ofdev); 190 struct fec_info *fec = bus->priv; 191 192 mdiobus_unregister(bus); 193 iounmap(fec->fecp); 194 kfree(fec); 195 mdiobus_free(bus); 196 } 197 198 static const struct of_device_id fs_enet_mdio_fec_match[] = { 199 { 200 .compatible = "fsl,pq1-fec-mdio", 201 }, 202 #if defined(CONFIG_PPC_MPC512x) 203 { 204 .compatible = "fsl,mpc5121-fec-mdio", 205 .data = mpc5xxx_get_bus_frequency, 206 }, 207 #endif 208 {}, 209 }; 210 MODULE_DEVICE_TABLE(of, fs_enet_mdio_fec_match); 211 212 static struct platform_driver fs_enet_fec_mdio_driver = { 213 .driver = { 214 .name = "fsl-fec-mdio", 215 .of_match_table = fs_enet_mdio_fec_match, 216 }, 217 .probe = fs_enet_mdio_probe, 218 .remove_new = fs_enet_mdio_remove, 219 }; 220 221 module_platform_driver(fs_enet_fec_mdio_driver); 222 MODULE_LICENSE("GPL"); 223