1/* 2 * @TAG(OTHER_GPL) 3 */ 4 5/* 6 * Micrel PHY drivers 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 * 23 * Copyright 2010-2011 Freescale Semiconductor, Inc. 24 * author Andy Fleming 25 * 26 */ 27#include "config.h" 28#include "common.h" 29#include "micrel.h" 30#include "phy.h" 31 32#define CONFIG_PHY_MICREL_KSZ9021 33 34static struct phy_driver KSZ804_driver = { 35 .name = "Micrel KSZ804", 36 .uid = 0x221510, 37 .mask = 0xfffff0, 38 .features = PHY_BASIC_FEATURES, 39 .config = &genphy_config, 40 .startup = &genphy_startup, 41 .shutdown = &genphy_shutdown, 42}; 43 44/* ksz9021 PHY Registers */ 45#define MII_KSZ9021_EXTENDED_CTRL 0x0b 46#define MII_KSZ9021_EXTENDED_DATAW 0x0c 47#define MII_KSZ9021_EXTENDED_DATAR 0x0d 48#define MII_KSZ9021_PHY_CTL 0x1f 49#define MIIM_KSZ9021_PHYCTL_1000 (BIT(6)) 50#define MIIM_KSZ9021_PHYCTL_100 (BIT(5)) 51#define MIIM_KSZ9021_PHYCTL_10 (BIT(4)) 52#define MIIM_KSZ9021_PHYCTL_DUPLEX (BIT(3)) 53 54#define CTRL1000_PREFER_MASTER (BIT(10)) 55#define CTRL1000_CONFIG_MASTER (BIT(11)) 56#define CTRL1000_MANUAL_CONFIG (BIT(12)) 57 58int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, uint16_t val) 59{ 60 /* extended registers */ 61 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000); 62 return phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAW, val); 63} 64 65int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum) 66{ 67 /* extended registers */ 68 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum); 69 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR); 70} 71 72/* Micrel ksz9021 */ 73int ksz9021_config(struct phy_device *phydev) 74{ 75 unsigned ctrl1000 = 0; 76 const unsigned master = CTRL1000_PREFER_MASTER | 77 CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG; 78 unsigned features = phydev->drv->features; 79 80 /* force master mode for 1000BaseT due to chip errata */ 81 if (features & SUPPORTED_1000baseT_Half) 82 ctrl1000 |= ADVERTISE_1000HALF | master; 83 if (features & SUPPORTED_1000baseT_Full) 84 ctrl1000 |= ADVERTISE_1000FULL | master; 85 phydev->advertising = phydev->supported = features; 86 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000); 87 genphy_config_aneg(phydev); 88 genphy_restart_aneg(phydev); 89 return 0; 90} 91 92void print_phyregs(struct phy_device *phydev){ 93 int i; 94 printf("\n\nPHY config\n"); 95 printf("\n\nIEEE\n"); 96 for(i = 0; i < 16; i++){ 97 uint16_t val = phy_read(phydev, MDIO_DEVAD_NONE, i); 98 printf("%3d | 0x%04x\n", i, val); 99 } 100 101 printf("vendor\n"); 102 for(i = 16; i < 32; i++){ 103 uint16_t val = phy_read(phydev, MDIO_DEVAD_NONE, i); 104 printf("%3d | 0x%04x\n", i, val); 105 } 106 107 printf("extended\n"); 108 for(i = 257; i < 264; i++){ 109 uint16_t val = ksz9021_phy_extended_read(phydev, i); 110 printf("%3d | 0x%04x\n", i, val); 111 } 112 printf("\n\n"); 113} 114 115int ksz9021_startup(struct phy_device *phydev) 116{ 117 unsigned phy_ctl; 118 genphy_update_link(phydev); 119 phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_PHY_CTL); 120 121 if (phy_ctl & MIIM_KSZ9021_PHYCTL_DUPLEX){ 122 phydev->duplex = DUPLEX_FULL; 123 }else{ 124 phydev->duplex = DUPLEX_HALF; 125 } 126 if (phy_ctl & MIIM_KSZ9021_PHYCTL_1000){ 127 phydev->speed = SPEED_1000; 128 }else if (phy_ctl & MIIM_KSZ9021_PHYCTL_100){ 129 phydev->speed = SPEED_100; 130 }else if (phy_ctl & MIIM_KSZ9021_PHYCTL_10){ 131 phydev->speed = SPEED_10; 132 } 133 return 0; 134} 135 136static struct phy_driver ksz9021_driver = { 137 .name = "Micrel ksz9021", 138 .uid = 0x221610, 139 .mask = 0xfffff0, 140 .features = PHY_GBIT_FEATURES, 141 .config = &ksz9021_config, 142 .startup = &ksz9021_startup, 143 .shutdown = &genphy_shutdown, 144}; 145 146int phy_micrel_init(void) 147{ 148 phy_register(&KSZ804_driver); 149 phy_register(&ksz9021_driver); 150 return 0; 151} 152