162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * drivers/net/phy/et1011c.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Driver for LSI ET1011C PHYs 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Chaithrika U S 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Copyright (c) 2008 Texas Instruments 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/string.h> 1362306a36Sopenharmony_ci#include <linux/errno.h> 1462306a36Sopenharmony_ci#include <linux/unistd.h> 1562306a36Sopenharmony_ci#include <linux/interrupt.h> 1662306a36Sopenharmony_ci#include <linux/init.h> 1762306a36Sopenharmony_ci#include <linux/delay.h> 1862306a36Sopenharmony_ci#include <linux/netdevice.h> 1962306a36Sopenharmony_ci#include <linux/etherdevice.h> 2062306a36Sopenharmony_ci#include <linux/skbuff.h> 2162306a36Sopenharmony_ci#include <linux/spinlock.h> 2262306a36Sopenharmony_ci#include <linux/mm.h> 2362306a36Sopenharmony_ci#include <linux/module.h> 2462306a36Sopenharmony_ci#include <linux/mii.h> 2562306a36Sopenharmony_ci#include <linux/ethtool.h> 2662306a36Sopenharmony_ci#include <linux/phy.h> 2762306a36Sopenharmony_ci#include <linux/io.h> 2862306a36Sopenharmony_ci#include <linux/uaccess.h> 2962306a36Sopenharmony_ci#include <asm/irq.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define ET1011C_STATUS_REG (0x1A) 3262306a36Sopenharmony_ci#define ET1011C_CONFIG_REG (0x16) 3362306a36Sopenharmony_ci#define ET1011C_SPEED_MASK (0x0300) 3462306a36Sopenharmony_ci#define ET1011C_GIGABIT_SPEED (0x0200) 3562306a36Sopenharmony_ci#define ET1011C_TX_FIFO_MASK (0x3000) 3662306a36Sopenharmony_ci#define ET1011C_TX_FIFO_DEPTH_8 (0x0000) 3762306a36Sopenharmony_ci#define ET1011C_TX_FIFO_DEPTH_16 (0x1000) 3862306a36Sopenharmony_ci#define ET1011C_INTERFACE_MASK (0x0007) 3962306a36Sopenharmony_ci#define ET1011C_GMII_INTERFACE (0x0002) 4062306a36Sopenharmony_ci#define ET1011C_SYS_CLK_EN (0x01 << 4) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciMODULE_DESCRIPTION("LSI ET1011C PHY driver"); 4462306a36Sopenharmony_ciMODULE_AUTHOR("Chaithrika U S"); 4562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic int et1011c_config_aneg(struct phy_device *phydev) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci int ctl = phy_read(phydev, MII_BMCR); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci if (ctl < 0) 5262306a36Sopenharmony_ci return ctl; 5362306a36Sopenharmony_ci ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | 5462306a36Sopenharmony_ci BMCR_ANENABLE); 5562306a36Sopenharmony_ci /* First clear the PHY */ 5662306a36Sopenharmony_ci phy_write(phydev, MII_BMCR, ctl | BMCR_RESET); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci return genphy_config_aneg(phydev); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic int et1011c_read_status(struct phy_device *phydev) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci static int speed; 6462306a36Sopenharmony_ci int ret; 6562306a36Sopenharmony_ci u32 val; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci ret = genphy_read_status(phydev); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (speed != phydev->speed) { 7062306a36Sopenharmony_ci speed = phydev->speed; 7162306a36Sopenharmony_ci val = phy_read(phydev, ET1011C_STATUS_REG); 7262306a36Sopenharmony_ci if ((val & ET1011C_SPEED_MASK) == 7362306a36Sopenharmony_ci ET1011C_GIGABIT_SPEED) { 7462306a36Sopenharmony_ci val = phy_read(phydev, ET1011C_CONFIG_REG); 7562306a36Sopenharmony_ci val &= ~ET1011C_TX_FIFO_MASK; 7662306a36Sopenharmony_ci phy_write(phydev, ET1011C_CONFIG_REG, val | 7762306a36Sopenharmony_ci ET1011C_GMII_INTERFACE | 7862306a36Sopenharmony_ci ET1011C_SYS_CLK_EN | 7962306a36Sopenharmony_ci ET1011C_TX_FIFO_DEPTH_16); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci return ret; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic struct phy_driver et1011c_driver[] = { { 8762306a36Sopenharmony_ci .phy_id = 0x0282f014, 8862306a36Sopenharmony_ci .name = "ET1011C", 8962306a36Sopenharmony_ci .phy_id_mask = 0xfffffff0, 9062306a36Sopenharmony_ci /* PHY_GBIT_FEATURES */ 9162306a36Sopenharmony_ci .config_aneg = et1011c_config_aneg, 9262306a36Sopenharmony_ci .read_status = et1011c_read_status, 9362306a36Sopenharmony_ci} }; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cimodule_phy_driver(et1011c_driver); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic struct mdio_device_id __maybe_unused et1011c_tbl[] = { 9862306a36Sopenharmony_ci { 0x0282f014, 0xfffffff0 }, 9962306a36Sopenharmony_ci { } 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(mdio, et1011c_tbl); 103