1 /* 2 * Micrel PHY drivers 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 * 6 * Copyright 2010-2011 Freescale Semiconductor, Inc. 7 * author Andy Fleming 8 * (C) 2012 NetModule AG, David Andrey, added KSZ9031 9 */ 10 #include <config.h> 11 #include <common.h> 12 #include <dm.h> 13 #include <errno.h> 14 #include <fdtdec.h> 15 #include <micrel.h> 16 #include <phy.h> 17 18 static struct phy_driver KSZ804_driver = { 19 .name = "Micrel KSZ804", 20 .uid = 0x221510, 21 .mask = 0xfffff0, 22 .features = PHY_BASIC_FEATURES, 23 .config = &genphy_config, 24 .startup = &genphy_startup, 25 .shutdown = &genphy_shutdown, 26 }; 27 28 #define MII_KSZPHY_OMSO 0x16 29 #define KSZPHY_OMSO_B_CAST_OFF (1 << 9) 30 31 static int ksz_genconfig_bcastoff(struct phy_device *phydev) 32 { 33 int ret; 34 35 ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZPHY_OMSO); 36 if (ret < 0) 37 return ret; 38 39 ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZPHY_OMSO, 40 ret | KSZPHY_OMSO_B_CAST_OFF); 41 if (ret < 0) 42 return ret; 43 44 return genphy_config(phydev); 45 } 46 47 static struct phy_driver KSZ8031_driver = { 48 .name = "Micrel KSZ8021/KSZ8031", 49 .uid = 0x221550, 50 .mask = 0xfffff0, 51 .features = PHY_BASIC_FEATURES, 52 .config = &ksz_genconfig_bcastoff, 53 .startup = &genphy_startup, 54 .shutdown = &genphy_shutdown, 55 }; 56 57 /** 58 * KSZ8051 59 */ 60 #define MII_KSZ8051_PHY_OMSO 0x16 61 #define MII_KSZ8051_PHY_OMSO_NAND_TREE_ON (1 << 5) 62 63 static int ksz8051_config(struct phy_device *phydev) 64 { 65 unsigned val; 66 67 /* Disable NAND-tree */ 68 val = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ8051_PHY_OMSO); 69 val &= ~MII_KSZ8051_PHY_OMSO_NAND_TREE_ON; 70 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ8051_PHY_OMSO, val); 71 72 return genphy_config(phydev); 73 } 74 75 static struct phy_driver KSZ8051_driver = { 76 .name = "Micrel KSZ8051", 77 .uid = 0x221550, 78 .mask = 0xfffff0, 79 .features = PHY_BASIC_FEATURES, 80 .config = &ksz8051_config, 81 .startup = &genphy_startup, 82 .shutdown = &genphy_shutdown, 83 }; 84 85 static struct phy_driver KSZ8081_driver = { 86 .name = "Micrel KSZ8081", 87 .uid = 0x221560, 88 .mask = 0xfffff0, 89 .features = PHY_BASIC_FEATURES, 90 .config = &ksz_genconfig_bcastoff, 91 .startup = &genphy_startup, 92 .shutdown = &genphy_shutdown, 93 }; 94 95 /** 96 * KSZ8895 97 */ 98 99 static unsigned short smireg_to_phy(unsigned short reg) 100 { 101 return ((reg & 0xc0) >> 3) + 0x06 + ((reg & 0x20) >> 5); 102 } 103 104 static unsigned short smireg_to_reg(unsigned short reg) 105 { 106 return reg & 0x1F; 107 } 108 109 static void ksz8895_write_smireg(struct phy_device *phydev, int smireg, int val) 110 { 111 phydev->bus->write(phydev->bus, smireg_to_phy(smireg), MDIO_DEVAD_NONE, 112 smireg_to_reg(smireg), val); 113 } 114 115 #if 0 116 static int ksz8895_read_smireg(struct phy_device *phydev, int smireg) 117 { 118 return phydev->bus->read(phydev->bus, smireg_to_phy(smireg), 119 MDIO_DEVAD_NONE, smireg_to_reg(smireg)); 120 } 121 #endif 122 123 int ksz8895_config(struct phy_device *phydev) 124 { 125 /* we are connected directly to the switch without 126 * dedicated PHY. SCONF1 == 001 */ 127 phydev->link = 1; 128 phydev->duplex = DUPLEX_FULL; 129 phydev->speed = SPEED_100; 130 131 /* Force the switch to start */ 132 ksz8895_write_smireg(phydev, 1, 1); 133 134 return 0; 135 } 136 137 static int ksz8895_startup(struct phy_device *phydev) 138 { 139 return 0; 140 } 141 142 static struct phy_driver ksz8895_driver = { 143 .name = "Micrel KSZ8895/KSZ8864", 144 .uid = 0x221450, 145 .mask = 0xffffe1, 146 .features = PHY_BASIC_FEATURES, 147 .config = &ksz8895_config, 148 .startup = &ksz8895_startup, 149 .shutdown = &genphy_shutdown, 150 }; 151 152 /* Micrel used the exact same part number for the KSZ9021. */ 153 static struct phy_driver KS8721_driver = { 154 .name = "Micrel KS8721BL", 155 .uid = 0x221610, 156 .mask = 0xfffff0, 157 .features = PHY_BASIC_FEATURES, 158 .config = &genphy_config, 159 .startup = &genphy_startup, 160 .shutdown = &genphy_shutdown, 161 }; 162 163 int ksz886x_config(struct phy_device *phydev) 164 { 165 /* we are connected directly to the switch without 166 * dedicated PHY. */ 167 phydev->link = 1; 168 phydev->duplex = DUPLEX_FULL; 169 phydev->speed = SPEED_100; 170 return 0; 171 } 172 173 static int ksz886x_startup(struct phy_device *phydev) 174 { 175 return 0; 176 } 177 178 static struct phy_driver ksz886x_driver = { 179 .name = "Micrel KSZ886x Switch", 180 .uid = 0x00221430, 181 .mask = 0xfffff0, 182 .features = PHY_BASIC_FEATURES, 183 .config = &ksz886x_config, 184 .startup = &ksz886x_startup, 185 .shutdown = &genphy_shutdown, 186 }; 187 188 int phy_micrel_ksz8xxx_init(void) 189 { 190 phy_register(&KSZ804_driver); 191 phy_register(&KSZ8031_driver); 192 phy_register(&KSZ8051_driver); 193 phy_register(&KSZ8081_driver); 194 phy_register(&KS8721_driver); 195 phy_register(&ksz8895_driver); 196 phy_register(&ksz886x_driver); 197 return 0; 198 } 199