2023-04-21 18:38:54 +02:00
// SPDX-License-Identifier: GPL-2.0+
/*
2023-05-26 20:53:43 +05:30
* Driver for Microchip 10 BASE - T1S PHYs
2023-04-21 18:38:54 +02:00
*
* Support : Microchip Phys :
2023-05-26 20:53:45 +05:30
* lan8670 / 1 / 2 Rev . B1
2023-04-21 18:38:54 +02:00
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/phy.h>
2023-05-26 20:53:45 +05:30
# define PHY_ID_LAN867X_REVB1 0x0007C162
2023-04-21 18:38:54 +02:00
# define LAN867X_REG_IRQ_1_CTL 0x001C
# define LAN867X_REG_IRQ_2_CTL 0x001D
/* The arrays below are pulled from the following table from AN1699
* Access MMD Address Value Mask
* RMW 0x1F 0x00D0 0x0002 0x0E03
* RMW 0x1F 0x00D1 0x0000 0x0300
* RMW 0x1F 0x0084 0x3380 0xFFC0
* RMW 0x1F 0x0085 0x0006 0x000F
* RMW 0x1F 0x008A 0xC000 0xF800
* RMW 0x1F 0x0087 0x801C 0x801C
* RMW 0x1F 0x0088 0x033F 0x1FFF
* W 0x1F 0x008B 0x0404 - - - - - -
* RMW 0x1F 0x0080 0x0600 0x0600
* RMW 0x1F 0x00F1 0x2400 0x7F00
* RMW 0x1F 0x0096 0x2000 0x2000
* W 0x1F 0x0099 0x7F80 - - - - - -
*/
2023-05-26 20:53:45 +05:30
static const u32 lan867x_revb1_fixup_registers [ 12 ] = {
2023-04-21 18:38:54 +02:00
0x00D0 , 0x00D1 , 0x0084 , 0x0085 ,
0x008A , 0x0087 , 0x0088 , 0x008B ,
0x0080 , 0x00F1 , 0x0096 , 0x0099 ,
} ;
2023-05-26 20:53:45 +05:30
static const u16 lan867x_revb1_fixup_values [ 12 ] = {
2023-04-21 18:38:54 +02:00
0x0002 , 0x0000 , 0x3380 , 0x0006 ,
0xC000 , 0x801C , 0x033F , 0x0404 ,
0x0600 , 0x2400 , 0x2000 , 0x7F80 ,
} ;
2023-05-26 20:53:45 +05:30
static const u16 lan867x_revb1_fixup_masks [ 12 ] = {
2023-04-21 18:38:54 +02:00
0x0E03 , 0x0300 , 0xFFC0 , 0x000F ,
0xF800 , 0x801C , 0x1FFF , 0xFFFF ,
0x0600 , 0x7F00 , 0x2000 , 0xFFFF ,
} ;
2023-05-26 20:53:45 +05:30
static int lan867x_revb1_config_init ( struct phy_device * phydev )
2023-04-21 18:38:54 +02:00
{
int err ;
2023-05-26 20:53:44 +05:30
/* Reference to AN1699
* https : //ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8670-1-2-config-60001699.pdf
* AN1699 says Read , Modify , Write , but the Write is not required if the
* register already has the required value . So it is safe to use
* phy_modify_mmd here .
2023-04-21 18:38:54 +02:00
*/
2023-05-26 20:53:45 +05:30
for ( int i = 0 ; i < ARRAY_SIZE ( lan867x_revb1_fixup_registers ) ; i + + ) {
2023-05-26 20:53:44 +05:30
err = phy_modify_mmd ( phydev , MDIO_MMD_VEND2 ,
2023-05-26 20:53:45 +05:30
lan867x_revb1_fixup_registers [ i ] ,
lan867x_revb1_fixup_masks [ i ] ,
lan867x_revb1_fixup_values [ i ] ) ;
2023-05-26 20:53:44 +05:30
if ( err )
2023-04-21 18:38:54 +02:00
return err ;
}
/* None of the interrupts in the lan867x phy seem relevant.
* Other phys inspect the link status and call phy_trigger_machine
* in the interrupt handler .
* This phy does not support link status , and thus has no interrupt
* for it either .
* So we ' ll just disable all interrupts on the chip .
*/
err = phy_write_mmd ( phydev , MDIO_MMD_VEND2 , LAN867X_REG_IRQ_1_CTL , 0xFFFF ) ;
if ( err ! = 0 )
return err ;
return phy_write_mmd ( phydev , MDIO_MMD_VEND2 , LAN867X_REG_IRQ_2_CTL , 0xFFFF ) ;
}
static int lan867x_read_status ( struct phy_device * phydev )
{
/* The phy has some limitations, namely:
* - always reports link up
* - only supports 10 MBit half duplex
* - does not support auto negotiate
*/
phydev - > link = 1 ;
phydev - > duplex = DUPLEX_HALF ;
phydev - > speed = SPEED_10 ;
phydev - > autoneg = AUTONEG_DISABLE ;
return 0 ;
}
2023-05-26 20:53:43 +05:30
static struct phy_driver microchip_t1s_driver [ ] = {
2023-04-21 18:38:54 +02:00
{
2023-05-26 20:53:45 +05:30
PHY_ID_MATCH_EXACT ( PHY_ID_LAN867X_REVB1 ) ,
. name = " LAN867X Rev.B1 " ,
2023-04-21 18:38:54 +02:00
. features = PHY_BASIC_T1S_P2MP_FEATURES ,
2023-05-26 20:53:45 +05:30
. config_init = lan867x_revb1_config_init ,
2023-04-21 18:38:54 +02:00
. read_status = lan867x_read_status ,
. get_plca_cfg = genphy_c45_plca_get_cfg ,
. set_plca_cfg = genphy_c45_plca_set_cfg ,
. get_plca_status = genphy_c45_plca_get_status ,
}
} ;
2023-05-26 20:53:43 +05:30
module_phy_driver ( microchip_t1s_driver ) ;
2023-04-21 18:38:54 +02:00
static struct mdio_device_id __maybe_unused tbl [ ] = {
2023-05-26 20:53:45 +05:30
{ PHY_ID_MATCH_EXACT ( PHY_ID_LAN867X_REVB1 ) } ,
2023-04-21 18:38:54 +02:00
{ }
} ;
MODULE_DEVICE_TABLE ( mdio , tbl ) ;
2023-05-26 20:53:43 +05:30
MODULE_DESCRIPTION ( " Microchip 10BASE-T1S PHYs driver " ) ;
2023-04-21 18:38:54 +02:00
MODULE_AUTHOR ( " Ramón Nordin Rodriguez " ) ;
MODULE_LICENSE ( " GPL " ) ;