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