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