[POWERPC] 85xx: Add 8568 PHY workarounds to board code

The 8568 MDS needs some configuration changes to the PHY in order to
work properly. These are done in the firmware, normally, but Linux
shouldn't need to rely on the firmware running such things (someone
could disable the PHY support in the firmware to save space, for instance).

Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by Andy Fleming and committed by Kumar Gala 94833a42 ad12e34f

+119
+119
arch/powerpc/platforms/85xx/mpc85xx_mds.c
··· 32 32 #include <linux/fsl_devices.h> 33 33 #include <linux/of_platform.h> 34 34 #include <linux/of_device.h> 35 + #include <linux/phy.h> 35 36 36 37 #include <asm/system.h> 37 38 #include <asm/atomic.h> ··· 56 55 #else 57 56 #define DBG(fmt...) 58 57 #endif 58 + 59 + #define MV88E1111_SCR 0x10 60 + #define MV88E1111_SCR_125CLK 0x0010 61 + static int mpc8568_fixup_125_clock(struct phy_device *phydev) 62 + { 63 + int scr; 64 + int err; 65 + 66 + /* Workaround for the 125 CLK Toggle */ 67 + scr = phy_read(phydev, MV88E1111_SCR); 68 + 69 + if (scr < 0) 70 + return scr; 71 + 72 + err = phy_write(phydev, MV88E1111_SCR, scr & ~(MV88E1111_SCR_125CLK)); 73 + 74 + if (err) 75 + return err; 76 + 77 + err = phy_write(phydev, MII_BMCR, BMCR_RESET); 78 + 79 + if (err) 80 + return err; 81 + 82 + scr = phy_read(phydev, MV88E1111_SCR); 83 + 84 + if (scr < 0) 85 + return err; 86 + 87 + err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008); 88 + 89 + return err; 90 + } 91 + 92 + static int mpc8568_mds_phy_fixups(struct phy_device *phydev) 93 + { 94 + int temp; 95 + int err; 96 + 97 + /* Errata */ 98 + err = phy_write(phydev,29, 0x0006); 99 + 100 + if (err) 101 + return err; 102 + 103 + temp = phy_read(phydev, 30); 104 + 105 + if (temp < 0) 106 + return temp; 107 + 108 + temp = (temp & (~0x8000)) | 0x4000; 109 + err = phy_write(phydev,30, temp); 110 + 111 + if (err) 112 + return err; 113 + 114 + err = phy_write(phydev,29, 0x000a); 115 + 116 + if (err) 117 + return err; 118 + 119 + temp = phy_read(phydev, 30); 120 + 121 + if (temp < 0) 122 + return temp; 123 + 124 + temp = phy_read(phydev, 30); 125 + 126 + if (temp < 0) 127 + return temp; 128 + 129 + temp &= ~0x0020; 130 + 131 + err = phy_write(phydev,30,temp); 132 + 133 + if (err) 134 + return err; 135 + 136 + /* Disable automatic MDI/MDIX selection */ 137 + temp = phy_read(phydev, 16); 138 + 139 + if (temp < 0) 140 + return temp; 141 + 142 + temp &= ~0x0060; 143 + err = phy_write(phydev,16,temp); 144 + 145 + return err; 146 + } 59 147 60 148 /* ************************************************************************ 61 149 * ··· 227 137 } 228 138 #endif /* CONFIG_QUICC_ENGINE */ 229 139 } 140 + 141 + 142 + static int __init board_fixups(void) 143 + { 144 + char phy_id[BUS_ID_SIZE]; 145 + char *compstrs[2] = {"fsl,gianfar-mdio", "fsl,ucc-mdio"}; 146 + struct device_node *mdio; 147 + struct resource res; 148 + int i; 149 + 150 + for (i = 0; i < ARRAY_SIZE(compstrs); i++) { 151 + mdio = of_find_compatible_node(NULL, NULL, compstrs[i]); 152 + 153 + of_address_to_resource(mdio, 0, &res); 154 + snprintf(phy_id, BUS_ID_SIZE, "%x:%02x", res.start, 1); 155 + 156 + phy_register_fixup_for_id(phy_id, mpc8568_fixup_125_clock); 157 + phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups); 158 + 159 + /* Register a workaround for errata */ 160 + snprintf(phy_id, BUS_ID_SIZE, "%x:%02x", res.start, 7); 161 + phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups); 162 + 163 + of_node_put(mdio); 164 + } 165 + 166 + return 0; 167 + } 168 + machine_arch_initcall(mpc85xx_mds, board_fixups); 230 169 231 170 static struct of_device_id mpc85xx_ids[] = { 232 171 { .type = "soc", },