xref: /openbmc/linux/drivers/net/phy/et1011c.c (revision 33ab4632)
1a2443fd1SAndrew Lunn // SPDX-License-Identifier: GPL-2.0+
2dbb7a95dSChaithrika U S /*
3dbb7a95dSChaithrika U S  * drivers/net/phy/et1011c.c
4dbb7a95dSChaithrika U S  *
5dbb7a95dSChaithrika U S  * Driver for LSI ET1011C PHYs
6dbb7a95dSChaithrika U S  *
7dbb7a95dSChaithrika U S  * Author: Chaithrika U S
8dbb7a95dSChaithrika U S  *
9dbb7a95dSChaithrika U S  * Copyright (c) 2008 Texas Instruments
10dbb7a95dSChaithrika U S  */
11dbb7a95dSChaithrika U S #include <linux/kernel.h>
12dbb7a95dSChaithrika U S #include <linux/string.h>
13dbb7a95dSChaithrika U S #include <linux/errno.h>
14dbb7a95dSChaithrika U S #include <linux/unistd.h>
15dbb7a95dSChaithrika U S #include <linux/interrupt.h>
16dbb7a95dSChaithrika U S #include <linux/init.h>
17dbb7a95dSChaithrika U S #include <linux/delay.h>
18dbb7a95dSChaithrika U S #include <linux/netdevice.h>
19dbb7a95dSChaithrika U S #include <linux/etherdevice.h>
20dbb7a95dSChaithrika U S #include <linux/skbuff.h>
21dbb7a95dSChaithrika U S #include <linux/spinlock.h>
22dbb7a95dSChaithrika U S #include <linux/mm.h>
23dbb7a95dSChaithrika U S #include <linux/module.h>
24dbb7a95dSChaithrika U S #include <linux/mii.h>
25dbb7a95dSChaithrika U S #include <linux/ethtool.h>
26dbb7a95dSChaithrika U S #include <linux/phy.h>
27dbb7a95dSChaithrika U S #include <linux/io.h>
28dbb7a95dSChaithrika U S #include <linux/uaccess.h>
29dbb7a95dSChaithrika U S #include <asm/irq.h>
30dbb7a95dSChaithrika U S 
31dbb7a95dSChaithrika U S #define ET1011C_STATUS_REG	(0x1A)
32dbb7a95dSChaithrika U S #define ET1011C_CONFIG_REG	(0x16)
33dbb7a95dSChaithrika U S #define ET1011C_SPEED_MASK		(0x0300)
34dbb7a95dSChaithrika U S #define ET1011C_GIGABIT_SPEED		(0x0200)
35dbb7a95dSChaithrika U S #define ET1011C_TX_FIFO_MASK		(0x3000)
36dbb7a95dSChaithrika U S #define ET1011C_TX_FIFO_DEPTH_8		(0x0000)
37dbb7a95dSChaithrika U S #define ET1011C_TX_FIFO_DEPTH_16	(0x1000)
38dbb7a95dSChaithrika U S #define ET1011C_INTERFACE_MASK		(0x0007)
39dbb7a95dSChaithrika U S #define ET1011C_GMII_INTERFACE		(0x0002)
40dbb7a95dSChaithrika U S #define ET1011C_SYS_CLK_EN		(0x01 << 4)
41dbb7a95dSChaithrika U S 
42dbb7a95dSChaithrika U S 
43dbb7a95dSChaithrika U S MODULE_DESCRIPTION("LSI ET1011C PHY driver");
44dbb7a95dSChaithrika U S MODULE_AUTHOR("Chaithrika U S");
45dbb7a95dSChaithrika U S MODULE_LICENSE("GPL");
46dbb7a95dSChaithrika U S 
et1011c_config_aneg(struct phy_device * phydev)47dbb7a95dSChaithrika U S static int et1011c_config_aneg(struct phy_device *phydev)
48dbb7a95dSChaithrika U S {
49775f2547SWenpeng Liang 	int ctl = phy_read(phydev, MII_BMCR);
50775f2547SWenpeng Liang 
51dbb7a95dSChaithrika U S 	if (ctl < 0)
52dbb7a95dSChaithrika U S 		return ctl;
53dbb7a95dSChaithrika U S 	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 |
54dbb7a95dSChaithrika U S 		 BMCR_ANENABLE);
55dbb7a95dSChaithrika U S 	/* First clear the PHY */
56dbb7a95dSChaithrika U S 	phy_write(phydev, MII_BMCR, ctl | BMCR_RESET);
57dbb7a95dSChaithrika U S 
58dbb7a95dSChaithrika U S 	return genphy_config_aneg(phydev);
59dbb7a95dSChaithrika U S }
60dbb7a95dSChaithrika U S 
et1011c_read_status(struct phy_device * phydev)61dbb7a95dSChaithrika U S static int et1011c_read_status(struct phy_device *phydev)
62dbb7a95dSChaithrika U S {
63775f2547SWenpeng Liang 	static int speed;
64dbb7a95dSChaithrika U S 	int ret;
65dbb7a95dSChaithrika U S 	u32 val;
66775f2547SWenpeng Liang 
67dbb7a95dSChaithrika U S 	ret = genphy_read_status(phydev);
68dbb7a95dSChaithrika U S 
69dbb7a95dSChaithrika U S 	if (speed != phydev->speed) {
70dbb7a95dSChaithrika U S 		speed = phydev->speed;
71dbb7a95dSChaithrika U S 		val = phy_read(phydev, ET1011C_STATUS_REG);
72dbb7a95dSChaithrika U S 		if ((val & ET1011C_SPEED_MASK) ==
73dbb7a95dSChaithrika U S 					ET1011C_GIGABIT_SPEED) {
74dbb7a95dSChaithrika U S 			val = phy_read(phydev, ET1011C_CONFIG_REG);
75dbb7a95dSChaithrika U S 			val &= ~ET1011C_TX_FIFO_MASK;
76*33ab4632SWenpeng Liang 			phy_write(phydev, ET1011C_CONFIG_REG, val |
77*33ab4632SWenpeng Liang 					  ET1011C_GMII_INTERFACE |
78*33ab4632SWenpeng Liang 					  ET1011C_SYS_CLK_EN |
79*33ab4632SWenpeng Liang 					  ET1011C_TX_FIFO_DEPTH_16);
80dbb7a95dSChaithrika U S 
81dbb7a95dSChaithrika U S 		}
82dbb7a95dSChaithrika U S 	}
83dbb7a95dSChaithrika U S 	return ret;
84dbb7a95dSChaithrika U S }
85dbb7a95dSChaithrika U S 
86116dffa0SJohan Hovold static struct phy_driver et1011c_driver[] = { {
87dbb7a95dSChaithrika U S 	.phy_id		= 0x0282f014,
88dbb7a95dSChaithrika U S 	.name		= "ET1011C",
89dbb7a95dSChaithrika U S 	.phy_id_mask	= 0xfffffff0,
90dcdecdcfSHeiner Kallweit 	/* PHY_GBIT_FEATURES */
91dbb7a95dSChaithrika U S 	.config_aneg	= et1011c_config_aneg,
92dbb7a95dSChaithrika U S 	.read_status	= et1011c_read_status,
93116dffa0SJohan Hovold } };
94dbb7a95dSChaithrika U S 
95116dffa0SJohan Hovold module_phy_driver(et1011c_driver);
964e4f10f6SDavid Woodhouse 
97cf93c945SUwe Kleine-König static struct mdio_device_id __maybe_unused et1011c_tbl[] = {
984e4f10f6SDavid Woodhouse 	{ 0x0282f014, 0xfffffff0 },
994e4f10f6SDavid Woodhouse 	{ }
1004e4f10f6SDavid Woodhouse };
1014e4f10f6SDavid Woodhouse 
1024e4f10f6SDavid Woodhouse MODULE_DEVICE_TABLE(mdio, et1011c_tbl);
103