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#include <linux/bitops.h> 16 17U_BOOT_PHY_DRIVER(ksz804) = { 18 .name = "Micrel KSZ804", 19 .uid = 0x221510, 20 .mask = 0xfffff0, 21 .features = PHY_BASIC_FEATURES, 22 .config = &genphy_config, 23 .startup = &genphy_startup, 24 .shutdown = &genphy_shutdown, 25}; 26 27#define MII_KSZPHY_OMSO 0x16 28#define KSZPHY_OMSO_FACTORY_TEST BIT(15) 29#define KSZPHY_OMSO_B_CAST_OFF (1 << 9) 30 31static 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 47U_BOOT_PHY_DRIVER(ksz8031) = { 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 63static 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 75U_BOOT_PHY_DRIVER(ksz8051) = { 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 85static int ksz8061_config(struct phy_device *phydev) 86{ 87 return phy_write(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A); 88} 89 90U_BOOT_PHY_DRIVER(ksz8061) = { 91 .name = "Micrel KSZ8061", 92 .uid = 0x00221570, 93 .mask = 0xfffff0, 94 .features = PHY_BASIC_FEATURES, 95 .config = &ksz8061_config, 96 .startup = &genphy_startup, 97 .shutdown = &genphy_shutdown, 98}; 99 100static int ksz8081_config(struct phy_device *phydev) 101{ 102 int ret; 103 104 ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZPHY_OMSO); 105 if (ret < 0) 106 return ret; 107 108 ret &= ~KSZPHY_OMSO_FACTORY_TEST; 109 110 ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZPHY_OMSO, 111 ret | KSZPHY_OMSO_B_CAST_OFF); 112 if (ret < 0) 113 return ret; 114 115 return genphy_config(phydev); 116} 117 118U_BOOT_PHY_DRIVER(ksz8081) = { 119 .name = "Micrel KSZ8081", 120 .uid = 0x221560, 121 .mask = 0xfffff0, 122 .features = PHY_BASIC_FEATURES, 123 .config = &ksz8081_config, 124 .startup = &genphy_startup, 125 .shutdown = &genphy_shutdown, 126}; 127 128/** 129 * KSZ8895 130 */ 131 132static unsigned short smireg_to_phy(unsigned short reg) 133{ 134 return ((reg & 0xc0) >> 3) + 0x06 + ((reg & 0x20) >> 5); 135} 136 137static unsigned short smireg_to_reg(unsigned short reg) 138{ 139 return reg & 0x1F; 140} 141 142static void ksz8895_write_smireg(struct phy_device *phydev, int smireg, int val) 143{ 144 phydev->bus->write(phydev->bus, smireg_to_phy(smireg), MDIO_DEVAD_NONE, 145 smireg_to_reg(smireg), val); 146} 147 148#if 0 149static int ksz8895_read_smireg(struct phy_device *phydev, int smireg) 150{ 151 return phydev->bus->read(phydev->bus, smireg_to_phy(smireg), 152 MDIO_DEVAD_NONE, smireg_to_reg(smireg)); 153} 154#endif 155 156int ksz8895_config(struct phy_device *phydev) 157{ 158 /* we are connected directly to the switch without 159 * dedicated PHY. SCONF1 == 001 */ 160 phydev->link = 1; 161 phydev->duplex = DUPLEX_FULL; 162 phydev->speed = SPEED_100; 163 164 /* Force the switch to start */ 165 ksz8895_write_smireg(phydev, 1, 1); 166 167 return 0; 168} 169 170static int ksz8895_startup(struct phy_device *phydev) 171{ 172 return 0; 173} 174 175U_BOOT_PHY_DRIVER(ksz8895) = { 176 .name = "Micrel KSZ8895/KSZ8864", 177 .uid = 0x221450, 178 .mask = 0xffffe1, 179 .features = PHY_BASIC_FEATURES, 180 .config = &ksz8895_config, 181 .startup = &ksz8895_startup, 182 .shutdown = &genphy_shutdown, 183}; 184 185/* Micrel used the exact same model number for the KSZ9021, 186 * so the revision number is used to distinguish them. 187 */ 188U_BOOT_PHY_DRIVER(ks8721) = { 189 .name = "Micrel KS8721BL", 190 .uid = 0x221618, 191 .mask = 0xfffffc, 192 .features = PHY_BASIC_FEATURES, 193 .config = &genphy_config, 194 .startup = &genphy_startup, 195 .shutdown = &genphy_shutdown, 196}; 197 198int ksz886x_config(struct phy_device *phydev) 199{ 200 /* we are connected directly to the switch without 201 * dedicated PHY. */ 202 phydev->link = 1; 203 phydev->duplex = DUPLEX_FULL; 204 phydev->speed = SPEED_100; 205 return 0; 206} 207 208static int ksz886x_startup(struct phy_device *phydev) 209{ 210 return 0; 211} 212 213U_BOOT_PHY_DRIVER(ksz886x) = { 214 .name = "Micrel KSZ886x Switch", 215 .uid = 0x00221430, 216 .mask = 0xfffff0, 217 .features = PHY_BASIC_FEATURES, 218 .config = &ksz886x_config, 219 .startup = &ksz886x_startup, 220 .shutdown = &genphy_shutdown, 221}; 222