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