Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1// SPDX-License-Identifier: GPL-2.0+
  2#include <linux/bitfield.h>
  3#include <linux/module.h>
  4#include <linux/phy.h>
  5
  6#include "mtk.h"
  7
  8#define MTK_GPHY_ID_MT7530		0x03a29412
  9#define MTK_GPHY_ID_MT7531		0x03a29441
 10
 11#define MTK_EXT_PAGE_ACCESS		0x1f
 12#define MTK_PHY_PAGE_STANDARD		0x0000
 13#define MTK_PHY_PAGE_EXTENDED		0x0001
 14#define MTK_PHY_PAGE_EXTENDED_2		0x0002
 15#define MTK_PHY_PAGE_EXTENDED_3		0x0003
 16#define MTK_PHY_PAGE_EXTENDED_2A30	0x2a30
 17#define MTK_PHY_PAGE_EXTENDED_52B5	0x52b5
 18
 19static void mtk_gephy_config_init(struct phy_device *phydev)
 20{
 21	/* Enable HW auto downshift */
 22	phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4));
 23
 24	/* Increase SlvDPSready time */
 25	phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
 26	__phy_write(phydev, 0x10, 0xafae);
 27	__phy_write(phydev, 0x12, 0x2f);
 28	__phy_write(phydev, 0x10, 0x8fae);
 29	phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
 30
 31	/* Adjust 100_mse_threshold */
 32	phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff);
 33
 34	/* Disable mcc */
 35	phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300);
 36}
 37
 38static int mt7530_phy_config_init(struct phy_device *phydev)
 39{
 40	mtk_gephy_config_init(phydev);
 41
 42	/* Increase post_update_timer */
 43	phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b);
 44
 45	return 0;
 46}
 47
 48static int mt7531_phy_config_init(struct phy_device *phydev)
 49{
 50	mtk_gephy_config_init(phydev);
 51
 52	/* PHY link down power saving enable */
 53	phy_set_bits(phydev, 0x17, BIT(4));
 54	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300);
 55
 56	/* Set TX Pair delay selection */
 57	phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
 58	phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
 59
 60	return 0;
 61}
 62
 63static struct phy_driver mtk_gephy_driver[] = {
 64	{
 65		PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
 66		.name		= "MediaTek MT7530 PHY",
 67		.config_init	= mt7530_phy_config_init,
 68		/* Interrupts are handled by the switch, not the PHY
 69		 * itself.
 70		 */
 71		.config_intr	= genphy_no_config_intr,
 72		.handle_interrupt = genphy_handle_interrupt_no_ack,
 73		.suspend	= genphy_suspend,
 74		.resume		= genphy_resume,
 75		.read_page	= mtk_phy_read_page,
 76		.write_page	= mtk_phy_write_page,
 77	},
 78	{
 79		PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
 80		.name		= "MediaTek MT7531 PHY",
 81		.config_init	= mt7531_phy_config_init,
 82		/* Interrupts are handled by the switch, not the PHY
 83		 * itself.
 84		 */
 85		.config_intr	= genphy_no_config_intr,
 86		.handle_interrupt = genphy_handle_interrupt_no_ack,
 87		.suspend	= genphy_suspend,
 88		.resume		= genphy_resume,
 89		.read_page	= mtk_phy_read_page,
 90		.write_page	= mtk_phy_write_page,
 91	},
 92};
 93
 94module_phy_driver(mtk_gephy_driver);
 95
 96static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
 97	{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) },
 98	{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) },
 99	{ }
100};
101
102MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver");
103MODULE_AUTHOR("DENG, Qingfang <dqfext@gmail.com>");
104MODULE_LICENSE("GPL");
105
106MODULE_DEVICE_TABLE(mdio, mtk_gephy_tbl);