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