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