123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * RealTek PHY drivers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * Copyright 2010-2011 Freescale Semiconductor, Inc.
- * author Andy Fleming
- *
- */
- #include <config.h>
- #include <common.h>
- #include <phy.h>
- #include <bitfield.h>
- #define REG_PHY_SPEC_STATUS 0x11
- #define REG_DEBUG_ADDR_OFFSET 0x1e
- #define REG_DEBUG_DATA 0x1f
- #define EXTREG_SLEEP_CONTROL 0x27
- #define YTPHY_EXTREG_CHIP_CONFIG 0xa001
- #define YTPHY_EXTREG_RGMII_CONFIG1 0xa003
- #define YTPHY_PAD_DRIVES_STRENGTH_CFG 0xa010
- #define YTPHY_DUPLEX 0x2000
- #define YTPHY_DUPLEX_BIT 13
- #define YTPHY_SPEED_MODE 0xc000
- #define YTPHY_SPEED_MODE_BIT 14
- #define YTPHY_RGMII_SW_DR_MASK GENMASK(5, 4)
- #define YTPHY_RGMII_RXC_DR_MASK GENMASK(15, 13)
- #define YT8521_EXT_CLK_GATE 0xc
- #define YT8521_EN_SLEEP_SW_BIT 15
- #define SPEED_UNKNOWN -1
- #define PHY_ID_YT8531 0x4f51e91b
- #define MOTORCOMM_PHY_ID_MASK 0x00000fff
- #define YT8512_EXTREG_LED0 0x40c0
- #define YT8512_EXTREG_LED1 0x40c3
- #define YT8512_EXTREG_SLEEP_CONTROL1 0x2027
- #define YT8512_LED0_ACT_BLK_IND 0x1000
- #define YT8512_LED0_DIS_LED_AN_TRY 0x0001
- #define YT8512_LED0_BT_BLK_EN 0x0002
- #define YT8512_LED0_HT_BLK_EN 0x0004
- #define YT8512_LED0_COL_BLK_EN 0x0008
- #define YT8512_LED0_BT_ON_EN 0x0010
- #define YT8512_LED1_BT_ON_EN 0x0010
- #define YT8512_LED1_TXACT_BLK_EN 0x0100
- #define YT8512_LED1_RXACT_BLK_EN 0x0200
- #define YT8512_EN_SLEEP_SW_BIT 15
- struct ytphy_reg_field {
- const char *name;
- const u8 size; /* Size of the bitfield, in bits */
- const u8 off; /* Offset from bit 0 */
- const u8 dflt; /* Default value */
- };
- static const struct ytphy_reg_field ytphy_dr_grp[] = {
- { "rgmii_sw_dr", 2, 4, 0x3},
- { "rgmii_sw_dr_2", 1, 12, 0x0},
- { "rgmii_sw_dr_rxc", 3, 13, 0x3}
- };
- static const struct ytphy_reg_field ytphy_rxtxd_grp[] = {
- { "rx_delay_sel", 4, 10, 0x0 },
- { "tx_delay_sel_fe", 4, 4, 0xf },
- { "tx_delay_sel", 4, 0, 0x1 }
- };
- static const struct ytphy_reg_field ytphy_txinver_grp[] = {
- { "tx_inverted_1000", 1, 14, 0x0 },
- { "tx_inverted_100", 1, 14, 0x0 },
- { "tx_inverted_10", 1, 14, 0x0 }
- };
- static const struct ytphy_reg_field ytphy_rxden_grp[] = {
- { "rxc_dly_en", 1, 8, 0x1 }
- };
- static int ytphy_of_config(struct phy_device *phydev);
- static int ytphy_read_ext(struct phy_device *phydev, u32 regnum)
- {
- int ret;
- ret = phy_write(phydev, MDIO_DEVAD_NONE, REG_DEBUG_ADDR_OFFSET, regnum);
- if (ret < 0)
- return ret;
- return phy_read(phydev, MDIO_DEVAD_NONE, REG_DEBUG_DATA);
- }
- static int ytphy_write_ext(struct phy_device *phydev, u32 regnum, u16 val)
- {
- int ret;
- ret = phy_write(phydev, MDIO_DEVAD_NONE, REG_DEBUG_ADDR_OFFSET, regnum);
- if (ret < 0)
- return ret;
- return phy_write(phydev, MDIO_DEVAD_NONE, REG_DEBUG_DATA, val);
- }
- static int ytphy_parse_status(struct phy_device *phydev)
- {
- int val;
- int speed, speed_mode, duplex;
- val = phy_read(phydev, MDIO_DEVAD_NONE, REG_PHY_SPEC_STATUS);
- if (val < 0)
- return val;
- duplex = (val & YTPHY_DUPLEX) >> YTPHY_DUPLEX_BIT;
- speed_mode = (val & YTPHY_SPEED_MODE) >> YTPHY_SPEED_MODE_BIT;
- switch (speed_mode) {
- case 2:
- speed = SPEED_1000;
- break;
- case 1:
- speed = SPEED_100;
- break;
- default:
- speed = SPEED_10;
- break;
- }
- phydev->speed = speed;
- phydev->duplex = duplex;
- return 0;
- }
- static int ytphy_of_inverted(struct phy_device *phydev)
- {
- ofnode node;
- u32 val;
- u32 inver_10;
- u32 inver_100;
- u32 inver_1000;
- node = phydev->node;
- if (!ofnode_valid(node)) {
- /* Look for a PHY node under the Ethernet node */
- node = dev_read_subnode(phydev->dev, "ethernet-phy");
- }
- if (!ofnode_valid(node)) /* No node found*/
- return 0;
- val = ytphy_read_ext(phydev, YTPHY_EXTREG_RGMII_CONFIG1);
- inver_10 = ofnode_read_u32_default(node, "tx_inverted_10", 0);
- inver_100 = ofnode_read_u32_default(node, "tx_inverted_100", 0);
- inver_1000 = ofnode_read_u32_default(node, "tx_inverted_1000", 0);
- switch (phydev->speed) {
- case SPEED_1000:
- val = bitfield_replace(val, ytphy_txinver_grp[0].off,
- ytphy_txinver_grp[0].size, inver_1000);
- break;
- case SPEED_100:
- val = bitfield_replace(val, ytphy_txinver_grp[1].off,
- ytphy_txinver_grp[1].size, inver_100);
- break;
- case SPEED_10:
- val = bitfield_replace(val, ytphy_txinver_grp[2].off,
- ytphy_txinver_grp[2].size, inver_10);
- break;
- default:
- printf("UNKOWN SPEED\n");
- break;
- }
- return ytphy_write_ext(phydev, YTPHY_EXTREG_RGMII_CONFIG1, val);
- }
- static int ytphy_startup(struct phy_device *phydev)
- {
- int retval;
- /*set delay config*/
- retval = ytphy_of_config(phydev);
- if (retval < 0)
- return retval;
- retval = genphy_update_link(phydev);
- if (retval)
- return retval;
- ytphy_parse_status(phydev);
- ytphy_of_inverted(phydev);
- return 0;
- }
- static int ytphy_of_config(struct phy_device *phydev)
- {
- ofnode node;
- u32 val;
- u32 cfg;
- int i;
- node = phydev->node;
- if (!ofnode_valid(node)) {
- /* Look for a PHY node under the Ethernet node */
- node = dev_read_subnode(phydev->dev, "ethernet-phy");
- }
- if (!ofnode_valid(node)) /* No node found*/
- return 0;
- /*read rxc_dly_en config*/
- cfg = ofnode_read_u32_default(node, ytphy_rxden_grp[0].name, ~0);
- if (cfg != -1) {
- val = ytphy_read_ext(phydev, YTPHY_EXTREG_CHIP_CONFIG);
- /*check the cfg overflow or not*/
- cfg = (cfg > ((1 << ytphy_rxden_grp[0].size) - 1)) ?
- ((1 << ytphy_rxden_grp[0].size) - 1) : cfg;
- val = bitfield_replace(val, ytphy_rxden_grp[0].off,
- ytphy_rxden_grp[0].size, cfg);
- ytphy_write_ext(phydev, YTPHY_EXTREG_CHIP_CONFIG, val);
- }
- val = ytphy_read_ext(phydev, YTPHY_PAD_DRIVES_STRENGTH_CFG);
- for (i = 0; i < ARRAY_SIZE(ytphy_dr_grp); i++) {
- cfg = ofnode_read_u32_default(node,
- ytphy_dr_grp[i].name, ~0);
- cfg = (cfg != -1) ? cfg : ytphy_dr_grp[i].dflt;
- /*check the cfg overflow or not*/
- cfg = (cfg > ((1 << ytphy_dr_grp[i].size) - 1)) ?
- ((1 << ytphy_dr_grp[i].size) - 1) : cfg;
- val = bitfield_replace(val, ytphy_dr_grp[i].off,
- ytphy_dr_grp[i].size, cfg);
- }
- ytphy_write_ext(phydev, YTPHY_PAD_DRIVES_STRENGTH_CFG, val);
- val = ytphy_read_ext(phydev, YTPHY_EXTREG_RGMII_CONFIG1);
- for (i = 0; i < ARRAY_SIZE(ytphy_rxtxd_grp); i++) {
- cfg = ofnode_read_u32_default(node,
- ytphy_rxtxd_grp[i].name, ~0);
- cfg = (cfg != -1) ? cfg : ytphy_rxtxd_grp[i].dflt;
- /*check the cfg overflow or not*/
- cfg = (cfg > ((1 << ytphy_rxtxd_grp[i].size) - 1)) ?
- ((1 << ytphy_rxtxd_grp[i].size) - 1) : cfg;
- val = bitfield_replace(val, ytphy_rxtxd_grp[i].off,
- ytphy_rxtxd_grp[i].size, cfg);
- }
- return ytphy_write_ext(phydev, YTPHY_EXTREG_RGMII_CONFIG1, val);
- }
- static int yt8512_led_init(struct phy_device *phydev)
- {
- int ret;
- int val;
- int mask;
- val = ytphy_read_ext(phydev, YT8512_EXTREG_LED0);
- if (val < 0)
- return val;
- val |= YT8512_LED0_ACT_BLK_IND;
- mask = YT8512_LED0_DIS_LED_AN_TRY | YT8512_LED0_BT_BLK_EN |
- YT8512_LED0_HT_BLK_EN | YT8512_LED0_COL_BLK_EN |
- YT8512_LED0_BT_ON_EN;
- val &= ~mask;
- ret = ytphy_write_ext(phydev, YT8512_EXTREG_LED0, val);
- if (ret < 0)
- return ret;
- val = ytphy_read_ext(phydev, YT8512_EXTREG_LED1);
- if (val < 0)
- return val;
- val |= YT8512_LED1_BT_ON_EN;
- mask = YT8512_LED1_TXACT_BLK_EN | YT8512_LED1_RXACT_BLK_EN;
- val &= ~mask;
- ret = ytphy_write_ext(phydev, YT8512_LED1_BT_ON_EN, val);
- return ret;
- }
- static int yt8512_config(struct phy_device *phydev)
- {
- int ret;
- int val;
- ret = 0;
- genphy_config_aneg(phydev);
- ret = yt8512_led_init(phydev);
- /* disable auto sleep */
- val = ytphy_read_ext(phydev, YT8512_EXTREG_SLEEP_CONTROL1);
- if (val < 0)
- return val;
- val &= (~BIT(YT8512_EN_SLEEP_SW_BIT));
- ret = ytphy_write_ext(phydev, YT8512_EXTREG_SLEEP_CONTROL1, val);
- if (ret < 0)
- return ret;
- return ret;
- }
- static int yt8521_config(struct phy_device *phydev)
- {
- int ret, val;
- ret = 0;
- genphy_config_aneg(phydev);
- /* disable auto sleep */
- val = ytphy_read_ext(phydev, EXTREG_SLEEP_CONTROL);
- if (val < 0)
- return val;
- val &= ~(1 << YT8521_EN_SLEEP_SW_BIT);
- ret = ytphy_write_ext(phydev, EXTREG_SLEEP_CONTROL, val);
- if (ret < 0)
- return ret;
- /*set delay config*/
- ret = ytphy_of_config(phydev);
- if (ret < 0)
- return ret;
- val = ytphy_read_ext(phydev, YT8521_EXT_CLK_GATE);
- if (val < 0)
- return val;
- val &= ~(1 << 12);
- ret = ytphy_write_ext(phydev, YT8521_EXT_CLK_GATE, val);
- if (ret < 0)
- return ret;
- return 0;
- }
- static int yt8531_config(struct phy_device *phydev)
- {
- int ret;
- ret = 0;
- genphy_config_aneg(phydev);
- return 0;
- }
- static struct phy_driver YT8512_driver = {
- .name = "YuTai YT8512",
- .uid = 0x00000118,
- .mask = 0x00000fff,
- .features = PHY_GBIT_FEATURES,
- .config = &yt8512_config,
- .startup = &ytphy_startup,
- .shutdown = &genphy_shutdown,
- };
- static struct phy_driver YT8521_driver = {
- .name = "YuTai YT8521",
- .uid = 0x0000011a,
- .mask = 0x00000fff,
- .features = PHY_GBIT_FEATURES,
- .config = &yt8521_config,
- .startup = &ytphy_startup,
- .shutdown = &genphy_shutdown,
- };
- static struct phy_driver YT8531_driver = {
- .name = "YT8531 Gigabit Ethernet",
- .uid = PHY_ID_YT8531,
- .mask = MOTORCOMM_PHY_ID_MASK,
- .features = PHY_GBIT_FEATURES,
- .config = &yt8531_config,
- .startup = &ytphy_startup,
- .shutdown = &genphy_shutdown,
- };
- int phy_yutai_init(void)
- {
- phy_register(&YT8512_driver);
- phy_register(&YT8521_driver);
- phy_register(&YT8531_driver);
- return 0;
- }
|