1b050f2f1SRadu Pirea (NXP OSS) // SPDX-License-Identifier: GPL-2.0 2b050f2f1SRadu Pirea (NXP OSS) /* NXP C45 PHY driver 3b050f2f1SRadu Pirea (NXP OSS) * Copyright (C) 2021 NXP 4b050f2f1SRadu Pirea (NXP OSS) * Author: Radu Pirea <radu-nicolae.pirea@oss.nxp.com> 5b050f2f1SRadu Pirea (NXP OSS) */ 6b050f2f1SRadu Pirea (NXP OSS) 7b050f2f1SRadu Pirea (NXP OSS) #include <linux/delay.h> 8b050f2f1SRadu Pirea (NXP OSS) #include <linux/ethtool.h> 9b050f2f1SRadu Pirea (NXP OSS) #include <linux/ethtool_netlink.h> 10b050f2f1SRadu Pirea (NXP OSS) #include <linux/kernel.h> 11b050f2f1SRadu Pirea (NXP OSS) #include <linux/mii.h> 12b050f2f1SRadu Pirea (NXP OSS) #include <linux/module.h> 13b050f2f1SRadu Pirea (NXP OSS) #include <linux/phy.h> 14b050f2f1SRadu Pirea (NXP OSS) #include <linux/processor.h> 15b050f2f1SRadu Pirea (NXP OSS) #include <linux/property.h> 16514def5dSRadu Pirea (NXP OSS) #include <linux/ptp_classify.h> 17514def5dSRadu Pirea (NXP OSS) #include <linux/ptp_clock_kernel.h> 18514def5dSRadu Pirea (NXP OSS) #include <linux/net_tstamp.h> 19b050f2f1SRadu Pirea (NXP OSS) 20b050f2f1SRadu Pirea (NXP OSS) #define PHY_ID_TJA_1103 0x001BB010 21f1fe5dffSRadu Pirea (NXP OSS) #define PHY_ID_TJA_1120 0x001BB031 22b050f2f1SRadu Pirea (NXP OSS) 23b050f2f1SRadu Pirea (NXP OSS) #define VEND1_DEVICE_CONTROL 0x0040 24b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_RESET BIT(15) 25b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14) 26b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_ALL_EN BIT(13) 27b050f2f1SRadu Pirea (NXP OSS) 28f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_DEVICE_CONFIG 0x0048 29f1fe5dffSRadu Pirea (NXP OSS) 30f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_VEND1_EXT_TS_MODE 0x1012 31f1fe5dffSRadu Pirea (NXP OSS) 32425c8348SRadu Pirea (NXP OSS) #define TJA1120_GLOBAL_INFRA_IRQ_ACK 0x2C08 33425c8348SRadu Pirea (NXP OSS) #define TJA1120_GLOBAL_INFRA_IRQ_EN 0x2C0A 34425c8348SRadu Pirea (NXP OSS) #define TJA1120_GLOBAL_INFRA_IRQ_STATUS 0x2C0C 35425c8348SRadu Pirea (NXP OSS) #define TJA1120_DEV_BOOT_DONE BIT(1) 36425c8348SRadu Pirea (NXP OSS) 3708e6547cSRadu Pirea (NXP OSS) #define TJA1120_VEND1_PTP_TRIG_DATA_S 0x1070 3808e6547cSRadu Pirea (NXP OSS) 39bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_EGRESS_TS_DATA_S 0x9060 40bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_EGRESS_TS_END 0x9067 41bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_TS_VALID BIT(0) 42bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_MORE_TS BIT(15) 43bdb4c5b8SRadu Pirea (NXP OSS) 44b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_ACK 0x80A0 45b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_EN 0x80A1 46b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_STATUS 0x80A2 47b2f0ca00SRadu Pirea (NXP OSS) #define PHY_IRQ_LINK_EVENT BIT(1) 48b2f0ca00SRadu Pirea (NXP OSS) 49425c8348SRadu Pirea (NXP OSS) #define VEND1_ALWAYS_ACCESSIBLE 0x801F 50425c8348SRadu Pirea (NXP OSS) #define FUSA_PASS BIT(4) 51425c8348SRadu Pirea (NXP OSS) 52b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONTROL 0x8100 53b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_EN BIT(14) 54b050f2f1SRadu Pirea (NXP OSS) #define PHY_START_OP BIT(0) 55b050f2f1SRadu Pirea (NXP OSS) 56b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONFIG 0x8108 57b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_AUTO BIT(0) 58b050f2f1SRadu Pirea (NXP OSS) 59*68c6af72SRadu Pirea (NXP OSS) #define TJA1120_EPHY_RESETS 0x810A 60*68c6af72SRadu Pirea (NXP OSS) #define EPHY_PCS_RESET BIT(3) 61*68c6af72SRadu Pirea (NXP OSS) 62b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SIGNAL_QUALITY 0x8320 63b050f2f1SRadu Pirea (NXP OSS) #define SQI_VALID BIT(14) 64b050f2f1SRadu Pirea (NXP OSS) #define SQI_MASK GENMASK(2, 0) 65b050f2f1SRadu Pirea (NXP OSS) #define MAX_SQI SQI_MASK 66b050f2f1SRadu Pirea (NXP OSS) 67b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_ENABLE BIT(15) 68b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_START BIT(14) 69b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OK 0x00 70b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_SHORTED 0x01 71b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OPEN 0x02 72b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_UNKNOWN 0x07 73b050f2f1SRadu Pirea (NXP OSS) 74b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_CONTROL 0x8040 75b050f2f1SRadu Pirea (NXP OSS) #define PORT_CONTROL_EN BIT(14) 76b050f2f1SRadu Pirea (NXP OSS) 77514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_ABILITIES 0x8046 78514def5dSRadu Pirea (NXP OSS) #define PTP_ABILITY BIT(3) 79514def5dSRadu Pirea (NXP OSS) 80bdb4c5b8SRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_IRQ_EN 0x807A 81bdb4c5b8SRadu Pirea (NXP OSS) #define PTP_IRQS BIT(3) 82bdb4c5b8SRadu Pirea (NXP OSS) 83bdb4c5b8SRadu Pirea (NXP OSS) #define VEND1_PTP_IRQ_ACK 0x9008 84bdb4c5b8SRadu Pirea (NXP OSS) #define EGR_TS_IRQ BIT(1) 85bdb4c5b8SRadu Pirea (NXP OSS) 86b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_INFRA_CONTROL 0xAC00 87b050f2f1SRadu Pirea (NXP OSS) #define PORT_INFRA_CONTROL_EN BIT(14) 88b050f2f1SRadu Pirea (NXP OSS) 89b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RXID 0xAFCC 90b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TXID 0xAFCD 91b050f2f1SRadu Pirea (NXP OSS) #define ID_ENABLE BIT(15) 92b050f2f1SRadu Pirea (NXP OSS) 93b050f2f1SRadu Pirea (NXP OSS) #define VEND1_ABILITIES 0xAFC4 94b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ID_ABILITY BIT(15) 95b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ABILITY BIT(14) 96b050f2f1SRadu Pirea (NXP OSS) #define RMII_ABILITY BIT(10) 97b050f2f1SRadu Pirea (NXP OSS) #define REVMII_ABILITY BIT(9) 98b050f2f1SRadu Pirea (NXP OSS) #define MII_ABILITY BIT(8) 99b050f2f1SRadu Pirea (NXP OSS) #define SGMII_ABILITY BIT(0) 100b050f2f1SRadu Pirea (NXP OSS) 101b050f2f1SRadu Pirea (NXP OSS) #define VEND1_MII_BASIC_CONFIG 0xAFC6 1028ba57205SRadu Pirea (OSS) #define MII_BASIC_CONFIG_REV BIT(4) 103b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_SGMII 0x9 104b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RGMII 0x7 105b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RMII 0x5 106b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_MII 0x4 107b050f2f1SRadu Pirea (NXP OSS) 108f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_CNT_XTD 0x8351 109f1fe5dffSRadu Pirea (NXP OSS) #define EXTENDED_CNT_EN BIT(15) 110f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_STATUS 0xAC80 111f1fe5dffSRadu Pirea (NXP OSS) #define MONITOR_RESET BIT(15) 112f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_CONFIG 0xAC86 113f1fe5dffSRadu Pirea (NXP OSS) #define LOST_FRAMES_CNT_EN BIT(9) 114f1fe5dffSRadu Pirea (NXP OSS) #define ALL_FRAMES_CNT_EN BIT(8) 115f1fe5dffSRadu Pirea (NXP OSS) 116b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_COUNTER 0x8350 117b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_DROP_COUNTER 0x8352 118b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_LOSSES_AND_FAILURES 0x8353 119b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_PREAMBLE_COUNT 0xAFCE 120b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_PREAMBLE_COUNT 0xAFCF 121b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_IPG_LENGTH 0xAFD0 122b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_IPG_LENGTH 0xAFD1 123b050f2f1SRadu Pirea (NXP OSS) #define COUNTER_EN BIT(15) 124b050f2f1SRadu Pirea (NXP OSS) 1257a71c8aaSRadu Pirea (NXP OSS) #define VEND1_PTP_CONFIG 0x1102 1267a71c8aaSRadu Pirea (NXP OSS) #define EXT_TRG_EDGE BIT(1) 1277a71c8aaSRadu Pirea (NXP OSS) 128b0b2247dSRadu Pirea (NXP OSS) #define TJA1120_SYNC_TRIG_FILTER 0x1010 129b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_RISE_TS BIT(3) 130b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_FALLING_TS BIT(2) 131b0b2247dSRadu Pirea (NXP OSS) 132514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_LD BIT(15) 133514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_DIR BIT(14) 134514def5dSRadu Pirea (NXP OSS) 135514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_TS_INSRT_CTRL 0x114D 1366c0c85daSRadu Pirea (NXP OSS) #define TJA1103_RX_TS_INSRT_MODE2 0x02 137514def5dSRadu Pirea (NXP OSS) 138f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_CTRL 0x9012 139f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_EN BIT(15) 140f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_TS_INSRT_MODE BIT(4) 141f1fe5dffSRadu Pirea (NXP OSS) 142514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_0 0x114E 143514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_CTRL 0x1154 144514def5dSRadu Pirea (NXP OSS) 145514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_TS_VALID BIT(15) 146514def5dSRadu Pirea (NXP OSS) 147514def5dSRadu Pirea (NXP OSS) #define RING_DONE BIT(0) 148514def5dSRadu Pirea (NXP OSS) 149514def5dSRadu Pirea (NXP OSS) #define TS_SEC_MASK GENMASK(1, 0) 150514def5dSRadu Pirea (NXP OSS) 151514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_ENABLES 0x8048 152514def5dSRadu Pirea (NXP OSS) #define PTP_ENABLE BIT(3) 153c552c110SRadu Pirea (NXP OSS) #define PHY_TEST_ENABLE BIT(0) 154514def5dSRadu Pirea (NXP OSS) 155514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_PTP_CONTROL 0x9000 156514def5dSRadu Pirea (NXP OSS) #define PORT_PTP_CONTROL_BYPASS BIT(11) 157514def5dSRadu Pirea (NXP OSS) 158514def5dSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_100BT1 15ULL 159f1fe5dffSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_1000BT1 8ULL 160514def5dSRadu Pirea (NXP OSS) 161514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_ALL 0x0F 162514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_NONE 0x00 163514def5dSRadu Pirea (NXP OSS) 1647a71c8aaSRadu Pirea (NXP OSS) #define VEND1_GPIO_FUNC_CONFIG_BASE 0x2C40 1657a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_EN BIT(15) 1667a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_PTP BIT(6) 1677a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PTP_TRIGGER 0x01 1687a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PPS_OUT 0x12 1697a71c8aaSRadu Pirea (NXP OSS) #define GPIO_DISABLE 0 1707a71c8aaSRadu Pirea (NXP OSS) #define GPIO_PPS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \ 1717a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PPS_OUT) 1727a71c8aaSRadu Pirea (NXP OSS) #define GPIO_EXTTS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \ 1737a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PTP_TRIGGER) 1747a71c8aaSRadu Pirea (NXP OSS) 175b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS 8000U 176b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE div_u64(RGMII_PERIOD_PS, 360) 177b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS 1644U 178b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS 2260U 179b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS 2000U 180b050f2f1SRadu Pirea (NXP OSS) 1816c0c85daSRadu Pirea (NXP OSS) #define PPM_TO_SUBNS_INC(ppb, ptp_clk_period) div_u64(GENMASK_ULL(31, 0) * \ 1826c0c85daSRadu Pirea (NXP OSS) (ppb) * (ptp_clk_period), NSEC_PER_SEC) 183514def5dSRadu Pirea (NXP OSS) 184514def5dSRadu Pirea (NXP OSS) #define NXP_C45_SKB_CB(skb) ((struct nxp_c45_skb_cb *)(skb)->cb) 185514def5dSRadu Pirea (NXP OSS) 186bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_phy; 187bdb4c5b8SRadu Pirea (NXP OSS) 188514def5dSRadu Pirea (NXP OSS) struct nxp_c45_skb_cb { 189514def5dSRadu Pirea (NXP OSS) struct ptp_header *header; 190514def5dSRadu Pirea (NXP OSS) unsigned int type; 191514def5dSRadu Pirea (NXP OSS) }; 192514def5dSRadu Pirea (NXP OSS) 1936c0c85daSRadu Pirea (NXP OSS) #define NXP_C45_REG_FIELD(_reg, _devad, _offset, _size) \ 1946c0c85daSRadu Pirea (NXP OSS) ((struct nxp_c45_reg_field) { \ 1956c0c85daSRadu Pirea (NXP OSS) .reg = _reg, \ 1966c0c85daSRadu Pirea (NXP OSS) .devad = _devad, \ 1976c0c85daSRadu Pirea (NXP OSS) .offset = _offset, \ 1986c0c85daSRadu Pirea (NXP OSS) .size = _size, \ 1996c0c85daSRadu Pirea (NXP OSS) }) 2006c0c85daSRadu Pirea (NXP OSS) 2016c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field { 2026c0c85daSRadu Pirea (NXP OSS) u16 reg; 2036c0c85daSRadu Pirea (NXP OSS) u8 devad; 2046c0c85daSRadu Pirea (NXP OSS) u8 offset; 2056c0c85daSRadu Pirea (NXP OSS) u8 size; 2066c0c85daSRadu Pirea (NXP OSS) }; 2076c0c85daSRadu Pirea (NXP OSS) 208514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts { 209514def5dSRadu Pirea (NXP OSS) u32 nsec; 210514def5dSRadu Pirea (NXP OSS) u32 sec; 211514def5dSRadu Pirea (NXP OSS) u8 domain_number; 212514def5dSRadu Pirea (NXP OSS) u16 sequence_id; 213514def5dSRadu Pirea (NXP OSS) u8 msg_type; 214514def5dSRadu Pirea (NXP OSS) }; 215514def5dSRadu Pirea (NXP OSS) 2166c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap { 2176c0c85daSRadu Pirea (NXP OSS) /* PTP config regs. */ 2186c0c85daSRadu Pirea (NXP OSS) u16 vend1_ptp_clk_period; 2196c0c85daSRadu Pirea (NXP OSS) u16 vend1_event_msg_filt; 2206c0c85daSRadu Pirea (NXP OSS) 2216c0c85daSRadu Pirea (NXP OSS) /* LTC bits and regs. */ 2226c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_read; 2236c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_write; 2246c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_lock_ctrl; 2256c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_nsec_0; 2266c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_nsec_1; 2276c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_sec_0; 2286c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_sec_1; 2296c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_nsec_0; 2306c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_nsec_1; 2316c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_sec_0; 2326c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_sec_1; 2336c0c85daSRadu Pirea (NXP OSS) u16 vend1_rate_adj_subns_0; 2346c0c85daSRadu Pirea (NXP OSS) u16 vend1_rate_adj_subns_1; 2356c0c85daSRadu Pirea (NXP OSS) 2366c0c85daSRadu Pirea (NXP OSS) /* External trigger reg fields. */ 2376c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field irq_egr_ts_en; 2386c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field irq_egr_ts_status; 2396c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field domain_number; 2406c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field msg_type; 2416c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sequence_id; 2426c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sec_1_0; 2436c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sec_4_2; 2446c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field nsec_15_0; 2456c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field nsec_29_16; 2466c0c85daSRadu Pirea (NXP OSS) 2476c0c85daSRadu Pirea (NXP OSS) /* PPS and EXT Trigger bits and regs. */ 2486c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field pps_enable; 2496c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field pps_polarity; 2506c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_0; 2516c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_1; 2526c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_2; 2536c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_3; 2546c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_ctrl; 2556c0c85daSRadu Pirea (NXP OSS) 2566c0c85daSRadu Pirea (NXP OSS) /* Cable test reg fields. */ 2576c0c85daSRadu Pirea (NXP OSS) u16 cable_test; 2586c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field cable_test_valid; 2596c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field cable_test_result; 2606c0c85daSRadu Pirea (NXP OSS) }; 2616c0c85daSRadu Pirea (NXP OSS) 2626c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_stats { 2636c0c85daSRadu Pirea (NXP OSS) const char *name; 2646c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field counter; 2656c0c85daSRadu Pirea (NXP OSS) }; 2666c0c85daSRadu Pirea (NXP OSS) 2676c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data { 2686c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap; 2696c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_stats *stats; 2706c0c85daSRadu Pirea (NXP OSS) int n_stats; 2716c0c85daSRadu Pirea (NXP OSS) u8 ptp_clk_period; 272b0b2247dSRadu Pirea (NXP OSS) bool ext_ts_both_edges; 273bdb4c5b8SRadu Pirea (NXP OSS) bool ack_ptp_irq; 2746c0c85daSRadu Pirea (NXP OSS) void (*counters_enable)(struct phy_device *phydev); 275bdb4c5b8SRadu Pirea (NXP OSS) bool (*get_egressts)(struct nxp_c45_phy *priv, 276bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts); 27708e6547cSRadu Pirea (NXP OSS) bool (*get_extts)(struct nxp_c45_phy *priv, struct timespec64 *extts); 2786c0c85daSRadu Pirea (NXP OSS) void (*ptp_init)(struct phy_device *phydev); 2796c0c85daSRadu Pirea (NXP OSS) void (*ptp_enable)(struct phy_device *phydev, bool enable); 280425c8348SRadu Pirea (NXP OSS) void (*nmi_handler)(struct phy_device *phydev, 281425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status); 2826c0c85daSRadu Pirea (NXP OSS) }; 2836c0c85daSRadu Pirea (NXP OSS) 284b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy { 2856c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data; 286514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev; 287514def5dSRadu Pirea (NXP OSS) struct mii_timestamper mii_ts; 288514def5dSRadu Pirea (NXP OSS) struct ptp_clock *ptp_clock; 289514def5dSRadu Pirea (NXP OSS) struct ptp_clock_info caps; 290514def5dSRadu Pirea (NXP OSS) struct sk_buff_head tx_queue; 291514def5dSRadu Pirea (NXP OSS) struct sk_buff_head rx_queue; 292514def5dSRadu Pirea (NXP OSS) /* used to access the PTP registers atomic */ 293514def5dSRadu Pirea (NXP OSS) struct mutex ptp_lock; 294514def5dSRadu Pirea (NXP OSS) int hwts_tx; 295514def5dSRadu Pirea (NXP OSS) int hwts_rx; 296b050f2f1SRadu Pirea (NXP OSS) u32 tx_delay; 297b050f2f1SRadu Pirea (NXP OSS) u32 rx_delay; 2987a71c8aaSRadu Pirea (NXP OSS) struct timespec64 extts_ts; 2997a71c8aaSRadu Pirea (NXP OSS) int extts_index; 3007a71c8aaSRadu Pirea (NXP OSS) bool extts; 301b050f2f1SRadu Pirea (NXP OSS) }; 302b050f2f1SRadu Pirea (NXP OSS) 3036c0c85daSRadu Pirea (NXP OSS) static const 3046c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data *nxp_c45_get_data(struct phy_device *phydev) 3056c0c85daSRadu Pirea (NXP OSS) { 3066c0c85daSRadu Pirea (NXP OSS) return phydev->drv->driver_data; 3076c0c85daSRadu Pirea (NXP OSS) } 3086c0c85daSRadu Pirea (NXP OSS) 3096c0c85daSRadu Pirea (NXP OSS) static const 3106c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap *nxp_c45_get_regmap(struct phy_device *phydev) 3116c0c85daSRadu Pirea (NXP OSS) { 3126c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 3136c0c85daSRadu Pirea (NXP OSS) 3146c0c85daSRadu Pirea (NXP OSS) return phy_data->regmap; 3156c0c85daSRadu Pirea (NXP OSS) } 3166c0c85daSRadu Pirea (NXP OSS) 3176c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_read_reg_field(struct phy_device *phydev, 3186c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 3196c0c85daSRadu Pirea (NXP OSS) { 320b050f2f1SRadu Pirea (NXP OSS) u16 mask; 3216c0c85daSRadu Pirea (NXP OSS) int ret; 3226c0c85daSRadu Pirea (NXP OSS) 3236c0c85daSRadu Pirea (NXP OSS) if (reg_field->size == 0) { 3246c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to read a reg field of size 0.\n"); 3256c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3266c0c85daSRadu Pirea (NXP OSS) } 3276c0c85daSRadu Pirea (NXP OSS) 3286c0c85daSRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, reg_field->devad, reg_field->reg); 3296c0c85daSRadu Pirea (NXP OSS) if (ret < 0) 3306c0c85daSRadu Pirea (NXP OSS) return ret; 3316c0c85daSRadu Pirea (NXP OSS) 3326c0c85daSRadu Pirea (NXP OSS) mask = reg_field->size == 1 ? BIT(reg_field->offset) : 3336c0c85daSRadu Pirea (NXP OSS) GENMASK(reg_field->offset + reg_field->size - 1, 3346c0c85daSRadu Pirea (NXP OSS) reg_field->offset); 3356c0c85daSRadu Pirea (NXP OSS) ret &= mask; 3366c0c85daSRadu Pirea (NXP OSS) ret >>= reg_field->offset; 3376c0c85daSRadu Pirea (NXP OSS) 3386c0c85daSRadu Pirea (NXP OSS) return ret; 3396c0c85daSRadu Pirea (NXP OSS) } 3406c0c85daSRadu Pirea (NXP OSS) 3416c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_write_reg_field(struct phy_device *phydev, 3426c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field, 3436c0c85daSRadu Pirea (NXP OSS) u16 val) 3446c0c85daSRadu Pirea (NXP OSS) { 3456c0c85daSRadu Pirea (NXP OSS) u16 mask; 3466c0c85daSRadu Pirea (NXP OSS) u16 set; 3476c0c85daSRadu Pirea (NXP OSS) 3486c0c85daSRadu Pirea (NXP OSS) if (reg_field->size == 0) { 3496c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to write a reg field of size 0.\n"); 3506c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3516c0c85daSRadu Pirea (NXP OSS) } 3526c0c85daSRadu Pirea (NXP OSS) 3536c0c85daSRadu Pirea (NXP OSS) mask = reg_field->size == 1 ? BIT(reg_field->offset) : 3546c0c85daSRadu Pirea (NXP OSS) GENMASK(reg_field->offset + reg_field->size - 1, 3556c0c85daSRadu Pirea (NXP OSS) reg_field->offset); 3566c0c85daSRadu Pirea (NXP OSS) set = val << reg_field->offset; 3576c0c85daSRadu Pirea (NXP OSS) 3586c0c85daSRadu Pirea (NXP OSS) return phy_modify_mmd_changed(phydev, reg_field->devad, 3596c0c85daSRadu Pirea (NXP OSS) reg_field->reg, mask, set); 3606c0c85daSRadu Pirea (NXP OSS) } 3616c0c85daSRadu Pirea (NXP OSS) 3626c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_set_reg_field(struct phy_device *phydev, 3636c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 3646c0c85daSRadu Pirea (NXP OSS) { 3656c0c85daSRadu Pirea (NXP OSS) if (reg_field->size != 1) { 3666c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to set a reg field of size different than 1.\n"); 3676c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3686c0c85daSRadu Pirea (NXP OSS) } 3696c0c85daSRadu Pirea (NXP OSS) 3706c0c85daSRadu Pirea (NXP OSS) return nxp_c45_write_reg_field(phydev, reg_field, 1); 3716c0c85daSRadu Pirea (NXP OSS) } 3726c0c85daSRadu Pirea (NXP OSS) 3736c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_clear_reg_field(struct phy_device *phydev, 3746c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 3756c0c85daSRadu Pirea (NXP OSS) { 3766c0c85daSRadu Pirea (NXP OSS) if (reg_field->size != 1) { 3776c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to set a reg field of size different than 1.\n"); 3786c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3796c0c85daSRadu Pirea (NXP OSS) } 3806c0c85daSRadu Pirea (NXP OSS) 3816c0c85daSRadu Pirea (NXP OSS) return nxp_c45_write_reg_field(phydev, reg_field, 0); 3826c0c85daSRadu Pirea (NXP OSS) } 383b050f2f1SRadu Pirea (NXP OSS) 384514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_poll_txts(struct phy_device *phydev) 385514def5dSRadu Pirea (NXP OSS) { 386514def5dSRadu Pirea (NXP OSS) return phydev->irq <= 0; 387514def5dSRadu Pirea (NXP OSS) } 388514def5dSRadu Pirea (NXP OSS) 389514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, 390514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts, 391514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts) 392514def5dSRadu Pirea (NXP OSS) { 393514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 3946c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 395514def5dSRadu Pirea (NXP OSS) 3966c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->ltc_read); 397514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3986c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_nsec_0); 399514def5dSRadu Pirea (NXP OSS) ts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 4006c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_nsec_1) << 16; 401514def5dSRadu Pirea (NXP OSS) ts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 4026c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_sec_0); 403514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 4046c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_sec_1) << 16; 405514def5dSRadu Pirea (NXP OSS) 406514def5dSRadu Pirea (NXP OSS) return 0; 407514def5dSRadu Pirea (NXP OSS) } 408514def5dSRadu Pirea (NXP OSS) 409514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, 410514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts, 411514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts) 412514def5dSRadu Pirea (NXP OSS) { 413514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 414514def5dSRadu Pirea (NXP OSS) 415514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 416514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, ts, sts); 417514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 418514def5dSRadu Pirea (NXP OSS) 419514def5dSRadu Pirea (NXP OSS) return 0; 420514def5dSRadu Pirea (NXP OSS) } 421514def5dSRadu Pirea (NXP OSS) 422514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, 423514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts) 424514def5dSRadu Pirea (NXP OSS) { 425514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 4266c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 427514def5dSRadu Pirea (NXP OSS) 4286c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_0, 429514def5dSRadu Pirea (NXP OSS) ts->tv_nsec); 4306c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_1, 431514def5dSRadu Pirea (NXP OSS) ts->tv_nsec >> 16); 4326c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_0, 433514def5dSRadu Pirea (NXP OSS) ts->tv_sec); 4346c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_1, 435514def5dSRadu Pirea (NXP OSS) ts->tv_sec >> 16); 4366c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->ltc_write); 437514def5dSRadu Pirea (NXP OSS) 438514def5dSRadu Pirea (NXP OSS) return 0; 439514def5dSRadu Pirea (NXP OSS) } 440514def5dSRadu Pirea (NXP OSS) 441514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, 442514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts) 443514def5dSRadu Pirea (NXP OSS) { 444514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 445514def5dSRadu Pirea (NXP OSS) 446514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 447514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, ts); 448514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 449514def5dSRadu Pirea (NXP OSS) 450514def5dSRadu Pirea (NXP OSS) return 0; 451514def5dSRadu Pirea (NXP OSS) } 452514def5dSRadu Pirea (NXP OSS) 453514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 454514def5dSRadu Pirea (NXP OSS) { 455514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 4566c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); 4576c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = data->regmap; 458514def5dSRadu Pirea (NXP OSS) s32 ppb = scaled_ppm_to_ppb(scaled_ppm); 459514def5dSRadu Pirea (NXP OSS) u64 subns_inc_val; 460514def5dSRadu Pirea (NXP OSS) bool inc; 461514def5dSRadu Pirea (NXP OSS) 462514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 463514def5dSRadu Pirea (NXP OSS) inc = ppb >= 0; 464514def5dSRadu Pirea (NXP OSS) ppb = abs(ppb); 465514def5dSRadu Pirea (NXP OSS) 4666c0c85daSRadu Pirea (NXP OSS) subns_inc_val = PPM_TO_SUBNS_INC(ppb, data->ptp_clk_period); 467514def5dSRadu Pirea (NXP OSS) 4686c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 4696c0c85daSRadu Pirea (NXP OSS) regmap->vend1_rate_adj_subns_0, 470514def5dSRadu Pirea (NXP OSS) subns_inc_val); 471514def5dSRadu Pirea (NXP OSS) subns_inc_val >>= 16; 472514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_LD; 473514def5dSRadu Pirea (NXP OSS) if (inc) 474514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_DIR; 475514def5dSRadu Pirea (NXP OSS) 4766c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 4776c0c85daSRadu Pirea (NXP OSS) regmap->vend1_rate_adj_subns_1, 478514def5dSRadu Pirea (NXP OSS) subns_inc_val); 479514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 480514def5dSRadu Pirea (NXP OSS) 481514def5dSRadu Pirea (NXP OSS) return 0; 482514def5dSRadu Pirea (NXP OSS) } 483514def5dSRadu Pirea (NXP OSS) 484514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) 485514def5dSRadu Pirea (NXP OSS) { 486514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 487514def5dSRadu Pirea (NXP OSS) struct timespec64 now, then; 488514def5dSRadu Pirea (NXP OSS) 489514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 490514def5dSRadu Pirea (NXP OSS) then = ns_to_timespec64(delta); 491514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, &now, NULL); 492514def5dSRadu Pirea (NXP OSS) now = timespec64_add(now, then); 493514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, &now); 494514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 495514def5dSRadu Pirea (NXP OSS) 496514def5dSRadu Pirea (NXP OSS) return 0; 497514def5dSRadu Pirea (NXP OSS) } 498514def5dSRadu Pirea (NXP OSS) 499514def5dSRadu Pirea (NXP OSS) static void nxp_c45_reconstruct_ts(struct timespec64 *ts, 500514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 501514def5dSRadu Pirea (NXP OSS) { 502514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = hwts->nsec; 503514def5dSRadu Pirea (NXP OSS) if ((ts->tv_sec & TS_SEC_MASK) < (hwts->sec & TS_SEC_MASK)) 504661fef56SVladimir Oltean ts->tv_sec -= TS_SEC_MASK + 1; 505514def5dSRadu Pirea (NXP OSS) ts->tv_sec &= ~TS_SEC_MASK; 506514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= hwts->sec & TS_SEC_MASK; 507514def5dSRadu Pirea (NXP OSS) } 508514def5dSRadu Pirea (NXP OSS) 509514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_match_ts(struct ptp_header *header, 510514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts, 511514def5dSRadu Pirea (NXP OSS) unsigned int type) 512514def5dSRadu Pirea (NXP OSS) { 513514def5dSRadu Pirea (NXP OSS) return ntohs(header->sequence_id) == hwts->sequence_id && 514514def5dSRadu Pirea (NXP OSS) ptp_get_msgtype(header, type) == hwts->msg_type && 515514def5dSRadu Pirea (NXP OSS) header->domain_number == hwts->domain_number; 516514def5dSRadu Pirea (NXP OSS) } 517514def5dSRadu Pirea (NXP OSS) 51808e6547cSRadu Pirea (NXP OSS) static bool nxp_c45_get_extts(struct nxp_c45_phy *priv, 5197a71c8aaSRadu Pirea (NXP OSS) struct timespec64 *extts) 5207a71c8aaSRadu Pirea (NXP OSS) { 5216c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 5226c0c85daSRadu Pirea (NXP OSS) 5237a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 5246c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_0); 5257a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 5266c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_1) << 16; 5277a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 5286c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_2); 5297a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 5306c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_3) << 16; 5316c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 5326c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_ctrl, RING_DONE); 53308e6547cSRadu Pirea (NXP OSS) 53408e6547cSRadu Pirea (NXP OSS) return true; 53508e6547cSRadu Pirea (NXP OSS) } 53608e6547cSRadu Pirea (NXP OSS) 53708e6547cSRadu Pirea (NXP OSS) static bool tja1120_extts_is_valid(struct phy_device *phydev) 53808e6547cSRadu Pirea (NXP OSS) { 53908e6547cSRadu Pirea (NXP OSS) bool valid; 54008e6547cSRadu Pirea (NXP OSS) int reg; 54108e6547cSRadu Pirea (NXP OSS) 54208e6547cSRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, 54308e6547cSRadu Pirea (NXP OSS) TJA1120_VEND1_PTP_TRIG_DATA_S); 54408e6547cSRadu Pirea (NXP OSS) valid = !!(reg & TJA1120_TS_VALID); 54508e6547cSRadu Pirea (NXP OSS) 54608e6547cSRadu Pirea (NXP OSS) return valid; 54708e6547cSRadu Pirea (NXP OSS) } 54808e6547cSRadu Pirea (NXP OSS) 54908e6547cSRadu Pirea (NXP OSS) static bool tja1120_get_extts(struct nxp_c45_phy *priv, 55008e6547cSRadu Pirea (NXP OSS) struct timespec64 *extts) 55108e6547cSRadu Pirea (NXP OSS) { 55208e6547cSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 55308e6547cSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 55408e6547cSRadu Pirea (NXP OSS) bool more_ts; 55508e6547cSRadu Pirea (NXP OSS) bool valid; 55608e6547cSRadu Pirea (NXP OSS) u16 reg; 55708e6547cSRadu Pirea (NXP OSS) 55808e6547cSRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, 55908e6547cSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_ctrl); 56008e6547cSRadu Pirea (NXP OSS) more_ts = !!(reg & TJA1120_MORE_TS); 56108e6547cSRadu Pirea (NXP OSS) 56208e6547cSRadu Pirea (NXP OSS) valid = tja1120_extts_is_valid(phydev); 56308e6547cSRadu Pirea (NXP OSS) if (!valid) { 56408e6547cSRadu Pirea (NXP OSS) if (!more_ts) 56508e6547cSRadu Pirea (NXP OSS) goto tja1120_get_extts_out; 56608e6547cSRadu Pirea (NXP OSS) 56708e6547cSRadu Pirea (NXP OSS) /* Bug workaround for TJA1120 engineering samples: move the new 56808e6547cSRadu Pirea (NXP OSS) * timestamp from the FIFO to the buffer. 56908e6547cSRadu Pirea (NXP OSS) */ 57008e6547cSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 57108e6547cSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_ctrl, RING_DONE); 57208e6547cSRadu Pirea (NXP OSS) valid = tja1120_extts_is_valid(phydev); 57308e6547cSRadu Pirea (NXP OSS) if (!valid) 57408e6547cSRadu Pirea (NXP OSS) goto tja1120_get_extts_out; 57508e6547cSRadu Pirea (NXP OSS) } 57608e6547cSRadu Pirea (NXP OSS) 57708e6547cSRadu Pirea (NXP OSS) nxp_c45_get_extts(priv, extts); 57808e6547cSRadu Pirea (NXP OSS) tja1120_get_extts_out: 57908e6547cSRadu Pirea (NXP OSS) return valid; 5807a71c8aaSRadu Pirea (NXP OSS) } 5817a71c8aaSRadu Pirea (NXP OSS) 582bdb4c5b8SRadu Pirea (NXP OSS) static void nxp_c45_read_egress_ts(struct nxp_c45_phy *priv, 583514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 584514def5dSRadu Pirea (NXP OSS) { 5856c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 5866c0c85daSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 587514def5dSRadu Pirea (NXP OSS) 5886c0c85daSRadu Pirea (NXP OSS) hwts->domain_number = 5896c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->domain_number); 5906c0c85daSRadu Pirea (NXP OSS) hwts->msg_type = 5916c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->msg_type); 5926c0c85daSRadu Pirea (NXP OSS) hwts->sequence_id = 5936c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->sequence_id); 5946c0c85daSRadu Pirea (NXP OSS) hwts->nsec = 5956c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->nsec_15_0); 5966c0c85daSRadu Pirea (NXP OSS) hwts->nsec |= 5976c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->nsec_29_16) << 16; 5986c0c85daSRadu Pirea (NXP OSS) hwts->sec = nxp_c45_read_reg_field(phydev, ®map->sec_1_0); 5996c0c85daSRadu Pirea (NXP OSS) hwts->sec |= nxp_c45_read_reg_field(phydev, ®map->sec_4_2) << 2; 600bdb4c5b8SRadu Pirea (NXP OSS) } 601514def5dSRadu Pirea (NXP OSS) 602bdb4c5b8SRadu Pirea (NXP OSS) static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, 603bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 604bdb4c5b8SRadu Pirea (NXP OSS) { 605bdb4c5b8SRadu Pirea (NXP OSS) bool valid; 606bdb4c5b8SRadu Pirea (NXP OSS) u16 reg; 607bdb4c5b8SRadu Pirea (NXP OSS) 608bdb4c5b8SRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 609bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL, 610bdb4c5b8SRadu Pirea (NXP OSS) RING_DONE); 611bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0); 612bdb4c5b8SRadu Pirea (NXP OSS) valid = !!(reg & RING_DATA_0_TS_VALID); 613bdb4c5b8SRadu Pirea (NXP OSS) if (!valid) 614bdb4c5b8SRadu Pirea (NXP OSS) goto nxp_c45_get_hwtxts_out; 615bdb4c5b8SRadu Pirea (NXP OSS) 616bdb4c5b8SRadu Pirea (NXP OSS) nxp_c45_read_egress_ts(priv, hwts); 617514def5dSRadu Pirea (NXP OSS) nxp_c45_get_hwtxts_out: 618514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 619514def5dSRadu Pirea (NXP OSS) return valid; 620514def5dSRadu Pirea (NXP OSS) } 621514def5dSRadu Pirea (NXP OSS) 622bdb4c5b8SRadu Pirea (NXP OSS) static bool tja1120_egress_ts_is_valid(struct phy_device *phydev) 623bdb4c5b8SRadu Pirea (NXP OSS) { 624bdb4c5b8SRadu Pirea (NXP OSS) bool valid; 625bdb4c5b8SRadu Pirea (NXP OSS) u16 reg; 626bdb4c5b8SRadu Pirea (NXP OSS) 627bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S); 628bdb4c5b8SRadu Pirea (NXP OSS) valid = !!(reg & TJA1120_TS_VALID); 629bdb4c5b8SRadu Pirea (NXP OSS) 630bdb4c5b8SRadu Pirea (NXP OSS) return valid; 631bdb4c5b8SRadu Pirea (NXP OSS) } 632bdb4c5b8SRadu Pirea (NXP OSS) 633bdb4c5b8SRadu Pirea (NXP OSS) static bool tja1120_get_hwtxts(struct nxp_c45_phy *priv, 634bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 635bdb4c5b8SRadu Pirea (NXP OSS) { 636bdb4c5b8SRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 637bdb4c5b8SRadu Pirea (NXP OSS) bool more_ts; 638bdb4c5b8SRadu Pirea (NXP OSS) bool valid; 639bdb4c5b8SRadu Pirea (NXP OSS) u16 reg; 640bdb4c5b8SRadu Pirea (NXP OSS) 641bdb4c5b8SRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 642bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_END); 643bdb4c5b8SRadu Pirea (NXP OSS) more_ts = !!(reg & TJA1120_MORE_TS); 644bdb4c5b8SRadu Pirea (NXP OSS) valid = tja1120_egress_ts_is_valid(phydev); 645bdb4c5b8SRadu Pirea (NXP OSS) if (!valid) { 646bdb4c5b8SRadu Pirea (NXP OSS) if (!more_ts) 647bdb4c5b8SRadu Pirea (NXP OSS) goto tja1120_get_hwtxts_out; 648bdb4c5b8SRadu Pirea (NXP OSS) 649bdb4c5b8SRadu Pirea (NXP OSS) /* Bug workaround for TJA1120 engineering samples: move the 650bdb4c5b8SRadu Pirea (NXP OSS) * new timestamp from the FIFO to the buffer. 651bdb4c5b8SRadu Pirea (NXP OSS) */ 652bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 653bdb4c5b8SRadu Pirea (NXP OSS) TJA1120_EGRESS_TS_END, TJA1120_TS_VALID); 654bdb4c5b8SRadu Pirea (NXP OSS) valid = tja1120_egress_ts_is_valid(phydev); 655bdb4c5b8SRadu Pirea (NXP OSS) if (!valid) 656bdb4c5b8SRadu Pirea (NXP OSS) goto tja1120_get_hwtxts_out; 657bdb4c5b8SRadu Pirea (NXP OSS) } 658bdb4c5b8SRadu Pirea (NXP OSS) nxp_c45_read_egress_ts(priv, hwts); 659bdb4c5b8SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S, 660bdb4c5b8SRadu Pirea (NXP OSS) TJA1120_TS_VALID); 661bdb4c5b8SRadu Pirea (NXP OSS) tja1120_get_hwtxts_out: 662bdb4c5b8SRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 663bdb4c5b8SRadu Pirea (NXP OSS) return valid; 664bdb4c5b8SRadu Pirea (NXP OSS) } 665bdb4c5b8SRadu Pirea (NXP OSS) 666514def5dSRadu Pirea (NXP OSS) static void nxp_c45_process_txts(struct nxp_c45_phy *priv, 667514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *txts) 668514def5dSRadu Pirea (NXP OSS) { 669514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, *tmp, *skb_match = NULL; 670514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps shhwtstamps; 671514def5dSRadu Pirea (NXP OSS) struct timespec64 ts; 672514def5dSRadu Pirea (NXP OSS) unsigned long flags; 673514def5dSRadu Pirea (NXP OSS) bool ts_match; 674514def5dSRadu Pirea (NXP OSS) s64 ts_ns; 675514def5dSRadu Pirea (NXP OSS) 676514def5dSRadu Pirea (NXP OSS) spin_lock_irqsave(&priv->tx_queue.lock, flags); 677514def5dSRadu Pirea (NXP OSS) skb_queue_walk_safe(&priv->tx_queue, skb, tmp) { 678514def5dSRadu Pirea (NXP OSS) ts_match = nxp_c45_match_ts(NXP_C45_SKB_CB(skb)->header, txts, 679514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type); 680514def5dSRadu Pirea (NXP OSS) if (!ts_match) 681514def5dSRadu Pirea (NXP OSS) continue; 682514def5dSRadu Pirea (NXP OSS) skb_match = skb; 683514def5dSRadu Pirea (NXP OSS) __skb_unlink(skb, &priv->tx_queue); 684514def5dSRadu Pirea (NXP OSS) break; 685514def5dSRadu Pirea (NXP OSS) } 686514def5dSRadu Pirea (NXP OSS) spin_unlock_irqrestore(&priv->tx_queue.lock, flags); 687514def5dSRadu Pirea (NXP OSS) 688514def5dSRadu Pirea (NXP OSS) if (skb_match) { 689514def5dSRadu Pirea (NXP OSS) nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL); 690514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, txts); 691514def5dSRadu Pirea (NXP OSS) memset(&shhwtstamps, 0, sizeof(shhwtstamps)); 692514def5dSRadu Pirea (NXP OSS) ts_ns = timespec64_to_ns(&ts); 693514def5dSRadu Pirea (NXP OSS) shhwtstamps.hwtstamp = ns_to_ktime(ts_ns); 694514def5dSRadu Pirea (NXP OSS) skb_complete_tx_timestamp(skb_match, &shhwtstamps); 695514def5dSRadu Pirea (NXP OSS) } else { 696514def5dSRadu Pirea (NXP OSS) phydev_warn(priv->phydev, 697514def5dSRadu Pirea (NXP OSS) "the tx timestamp doesn't match with any skb\n"); 698514def5dSRadu Pirea (NXP OSS) } 699514def5dSRadu Pirea (NXP OSS) } 700514def5dSRadu Pirea (NXP OSS) 701514def5dSRadu Pirea (NXP OSS) static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp) 702514def5dSRadu Pirea (NXP OSS) { 703514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 704bdb4c5b8SRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); 705514def5dSRadu Pirea (NXP OSS) bool poll_txts = nxp_c45_poll_txts(priv->phydev); 706514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps *shhwtstamps_rx; 7077a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_event event; 708514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts; 709514def5dSRadu Pirea (NXP OSS) bool reschedule = false; 710514def5dSRadu Pirea (NXP OSS) struct timespec64 ts; 711514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb; 71208e6547cSRadu Pirea (NXP OSS) bool ts_valid; 713514def5dSRadu Pirea (NXP OSS) u32 ts_raw; 714514def5dSRadu Pirea (NXP OSS) 715514def5dSRadu Pirea (NXP OSS) while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) { 71608e6547cSRadu Pirea (NXP OSS) ts_valid = data->get_egressts(priv, &hwts); 71708e6547cSRadu Pirea (NXP OSS) if (unlikely(!ts_valid)) { 718514def5dSRadu Pirea (NXP OSS) /* Still more skbs in the queue */ 719514def5dSRadu Pirea (NXP OSS) reschedule = true; 720514def5dSRadu Pirea (NXP OSS) break; 721514def5dSRadu Pirea (NXP OSS) } 722514def5dSRadu Pirea (NXP OSS) 723514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts); 724514def5dSRadu Pirea (NXP OSS) } 725514def5dSRadu Pirea (NXP OSS) 726514def5dSRadu Pirea (NXP OSS) while ((skb = skb_dequeue(&priv->rx_queue)) != NULL) { 727109258edSVladimir Oltean nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL); 728514def5dSRadu Pirea (NXP OSS) ts_raw = __be32_to_cpu(NXP_C45_SKB_CB(skb)->header->reserved2); 729514def5dSRadu Pirea (NXP OSS) hwts.sec = ts_raw >> 30; 730514def5dSRadu Pirea (NXP OSS) hwts.nsec = ts_raw & GENMASK(29, 0); 731514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, &hwts); 732514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx = skb_hwtstamps(skb); 733514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx->hwtstamp = ns_to_ktime(timespec64_to_ns(&ts)); 734514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header->reserved2 = 0; 735a3d73e15SSebastian Andrzej Siewior netif_rx(skb); 736514def5dSRadu Pirea (NXP OSS) } 737514def5dSRadu Pirea (NXP OSS) 7387a71c8aaSRadu Pirea (NXP OSS) if (priv->extts) { 73908e6547cSRadu Pirea (NXP OSS) ts_valid = data->get_extts(priv, &ts); 74008e6547cSRadu Pirea (NXP OSS) if (ts_valid && timespec64_compare(&ts, &priv->extts_ts) != 0) { 7417a71c8aaSRadu Pirea (NXP OSS) priv->extts_ts = ts; 7427a71c8aaSRadu Pirea (NXP OSS) event.index = priv->extts_index; 7437a71c8aaSRadu Pirea (NXP OSS) event.type = PTP_CLOCK_EXTTS; 7447a71c8aaSRadu Pirea (NXP OSS) event.timestamp = ns_to_ktime(timespec64_to_ns(&ts)); 7457a71c8aaSRadu Pirea (NXP OSS) ptp_clock_event(priv->ptp_clock, &event); 7467a71c8aaSRadu Pirea (NXP OSS) } 7477a71c8aaSRadu Pirea (NXP OSS) reschedule = true; 7487a71c8aaSRadu Pirea (NXP OSS) } 7497a71c8aaSRadu Pirea (NXP OSS) 750514def5dSRadu Pirea (NXP OSS) return reschedule ? 1 : -1; 751514def5dSRadu Pirea (NXP OSS) } 752514def5dSRadu Pirea (NXP OSS) 7537a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_gpio_config(struct nxp_c45_phy *priv, 7547a71c8aaSRadu Pirea (NXP OSS) int pin, u16 pin_cfg) 7557a71c8aaSRadu Pirea (NXP OSS) { 7567a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 7577a71c8aaSRadu Pirea (NXP OSS) 7587a71c8aaSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 7597a71c8aaSRadu Pirea (NXP OSS) VEND1_GPIO_FUNC_CONFIG_BASE + pin, pin_cfg); 7607a71c8aaSRadu Pirea (NXP OSS) } 7617a71c8aaSRadu Pirea (NXP OSS) 7627a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_perout_enable(struct nxp_c45_phy *priv, 7637a71c8aaSRadu Pirea (NXP OSS) struct ptp_perout_request *perout, int on) 7647a71c8aaSRadu Pirea (NXP OSS) { 7656c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 7667a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 7677a71c8aaSRadu Pirea (NXP OSS) int pin; 7687a71c8aaSRadu Pirea (NXP OSS) 7697a71c8aaSRadu Pirea (NXP OSS) if (perout->flags & ~PTP_PEROUT_PHASE) 7707a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 7717a71c8aaSRadu Pirea (NXP OSS) 7727a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_PEROUT, perout->index); 7737a71c8aaSRadu Pirea (NXP OSS) if (pin < 0) 7747a71c8aaSRadu Pirea (NXP OSS) return pin; 7757a71c8aaSRadu Pirea (NXP OSS) 7767a71c8aaSRadu Pirea (NXP OSS) if (!on) { 7776c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 7786c0c85daSRadu Pirea (NXP OSS) ®map->pps_enable); 7796c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 7806c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 7817a71c8aaSRadu Pirea (NXP OSS) 7827a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); 7837a71c8aaSRadu Pirea (NXP OSS) 7847a71c8aaSRadu Pirea (NXP OSS) return 0; 7857a71c8aaSRadu Pirea (NXP OSS) } 7867a71c8aaSRadu Pirea (NXP OSS) 7877a71c8aaSRadu Pirea (NXP OSS) /* The PPS signal is fixed to 1 second and is always generated when the 7887a71c8aaSRadu Pirea (NXP OSS) * seconds counter is incremented. The start time is not configurable. 7897a71c8aaSRadu Pirea (NXP OSS) * If the clock is adjusted, the PPS signal is automatically readjusted. 7907a71c8aaSRadu Pirea (NXP OSS) */ 7917a71c8aaSRadu Pirea (NXP OSS) if (perout->period.sec != 1 || perout->period.nsec != 0) { 7927a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The period can be set only to 1 second."); 7937a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 7947a71c8aaSRadu Pirea (NXP OSS) } 7957a71c8aaSRadu Pirea (NXP OSS) 7967a71c8aaSRadu Pirea (NXP OSS) if (!(perout->flags & PTP_PEROUT_PHASE)) { 7977a71c8aaSRadu Pirea (NXP OSS) if (perout->start.sec != 0 || perout->start.nsec != 0) { 7987a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The start time is not configurable. Should be set to 0 seconds and 0 nanoseconds."); 7997a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 8007a71c8aaSRadu Pirea (NXP OSS) } 8017a71c8aaSRadu Pirea (NXP OSS) } else { 8027a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec != 0 && 8037a71c8aaSRadu Pirea (NXP OSS) perout->phase.nsec != (NSEC_PER_SEC >> 1)) { 8047a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The phase can be set only to 0 or 500000000 nanoseconds."); 8057a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 8067a71c8aaSRadu Pirea (NXP OSS) } 8077a71c8aaSRadu Pirea (NXP OSS) 8087a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec == 0) 8096c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 8106c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 8117a71c8aaSRadu Pirea (NXP OSS) else 8126c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, 8136c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 8147a71c8aaSRadu Pirea (NXP OSS) } 8157a71c8aaSRadu Pirea (NXP OSS) 8167a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_PPS_OUT_CFG); 8177a71c8aaSRadu Pirea (NXP OSS) 8186c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->pps_enable); 8197a71c8aaSRadu Pirea (NXP OSS) 8207a71c8aaSRadu Pirea (NXP OSS) return 0; 8217a71c8aaSRadu Pirea (NXP OSS) } 8227a71c8aaSRadu Pirea (NXP OSS) 823b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_or_falling(struct phy_device *phydev, 824b0b2247dSRadu Pirea (NXP OSS) struct ptp_extts_request *extts) 825b0b2247dSRadu Pirea (NXP OSS) { 826b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE) 827b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 828b0b2247dSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE); 829b0b2247dSRadu Pirea (NXP OSS) 830b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE) 831b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 832b0b2247dSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE); 833b0b2247dSRadu Pirea (NXP OSS) } 834b0b2247dSRadu Pirea (NXP OSS) 835b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_and_falling(struct phy_device *phydev, 836b0b2247dSRadu Pirea (NXP OSS) struct ptp_extts_request *extts) 837b0b2247dSRadu Pirea (NXP OSS) { 838b0b2247dSRadu Pirea (NXP OSS) /* PTP_EXTTS_REQUEST may have only the PTP_ENABLE_FEATURE flag set. In 839b0b2247dSRadu Pirea (NXP OSS) * this case external ts will be enabled on rising edge. 840b0b2247dSRadu Pirea (NXP OSS) */ 841b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE || 842b0b2247dSRadu Pirea (NXP OSS) extts->flags == PTP_ENABLE_FEATURE) 843b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 844b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 845b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_RISE_TS); 846b0b2247dSRadu Pirea (NXP OSS) else 847b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 848b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 849b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_RISE_TS); 850b0b2247dSRadu Pirea (NXP OSS) 851b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE) 852b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 853b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 854b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_FALLING_TS); 855b0b2247dSRadu Pirea (NXP OSS) else 856b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 857b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 858b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_FALLING_TS); 859b0b2247dSRadu Pirea (NXP OSS) } 860b0b2247dSRadu Pirea (NXP OSS) 8617a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_extts_enable(struct nxp_c45_phy *priv, 8627a71c8aaSRadu Pirea (NXP OSS) struct ptp_extts_request *extts, int on) 8637a71c8aaSRadu Pirea (NXP OSS) { 864b0b2247dSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); 8657a71c8aaSRadu Pirea (NXP OSS) int pin; 8667a71c8aaSRadu Pirea (NXP OSS) 8677a71c8aaSRadu Pirea (NXP OSS) if (extts->flags & ~(PTP_ENABLE_FEATURE | 8687a71c8aaSRadu Pirea (NXP OSS) PTP_RISING_EDGE | 8697a71c8aaSRadu Pirea (NXP OSS) PTP_FALLING_EDGE | 8707a71c8aaSRadu Pirea (NXP OSS) PTP_STRICT_FLAGS)) 8717a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 8727a71c8aaSRadu Pirea (NXP OSS) 8737a71c8aaSRadu Pirea (NXP OSS) /* Sampling on both edges is not supported */ 8747a71c8aaSRadu Pirea (NXP OSS) if ((extts->flags & PTP_RISING_EDGE) && 875b0b2247dSRadu Pirea (NXP OSS) (extts->flags & PTP_FALLING_EDGE) && 876b0b2247dSRadu Pirea (NXP OSS) !data->ext_ts_both_edges) 8777a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 8787a71c8aaSRadu Pirea (NXP OSS) 8797a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_EXTTS, extts->index); 8807a71c8aaSRadu Pirea (NXP OSS) if (pin < 0) 8817a71c8aaSRadu Pirea (NXP OSS) return pin; 8827a71c8aaSRadu Pirea (NXP OSS) 8837a71c8aaSRadu Pirea (NXP OSS) if (!on) { 8847a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); 8857a71c8aaSRadu Pirea (NXP OSS) priv->extts = false; 8867a71c8aaSRadu Pirea (NXP OSS) 8877a71c8aaSRadu Pirea (NXP OSS) return 0; 8887a71c8aaSRadu Pirea (NXP OSS) } 8897a71c8aaSRadu Pirea (NXP OSS) 890b0b2247dSRadu Pirea (NXP OSS) if (data->ext_ts_both_edges) 891b0b2247dSRadu Pirea (NXP OSS) nxp_c45_set_rising_and_falling(priv->phydev, extts); 892b0b2247dSRadu Pirea (NXP OSS) else 893b0b2247dSRadu Pirea (NXP OSS) nxp_c45_set_rising_or_falling(priv->phydev, extts); 8947a71c8aaSRadu Pirea (NXP OSS) 8957a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_EXTTS_OUT_CFG); 8967a71c8aaSRadu Pirea (NXP OSS) priv->extts = true; 8977a71c8aaSRadu Pirea (NXP OSS) priv->extts_index = extts->index; 8987a71c8aaSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 8997a71c8aaSRadu Pirea (NXP OSS) 9007a71c8aaSRadu Pirea (NXP OSS) return 0; 9017a71c8aaSRadu Pirea (NXP OSS) } 9027a71c8aaSRadu Pirea (NXP OSS) 9037a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_enable(struct ptp_clock_info *ptp, 9047a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_request *req, int on) 9057a71c8aaSRadu Pirea (NXP OSS) { 9067a71c8aaSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 9077a71c8aaSRadu Pirea (NXP OSS) 9087a71c8aaSRadu Pirea (NXP OSS) switch (req->type) { 9097a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_EXTTS: 9107a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_extts_enable(priv, &req->extts, on); 9117a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_PEROUT: 9127a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_perout_enable(priv, &req->perout, on); 9137a71c8aaSRadu Pirea (NXP OSS) default: 9147a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 9157a71c8aaSRadu Pirea (NXP OSS) } 9167a71c8aaSRadu Pirea (NXP OSS) } 9177a71c8aaSRadu Pirea (NXP OSS) 9187a71c8aaSRadu Pirea (NXP OSS) static struct ptp_pin_desc nxp_c45_ptp_pins[] = { 9197a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio0", 0, PTP_PF_NONE}, 9207a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio1", 1, PTP_PF_NONE}, 9217a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio2", 2, PTP_PF_NONE}, 9227a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio3", 3, PTP_PF_NONE}, 9237a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio4", 4, PTP_PF_NONE}, 9247a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio5", 5, PTP_PF_NONE}, 9257a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio6", 6, PTP_PF_NONE}, 9267a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio7", 7, PTP_PF_NONE}, 9277a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio8", 8, PTP_PF_NONE}, 9287a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio9", 9, PTP_PF_NONE}, 9297a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio10", 10, PTP_PF_NONE}, 9307a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio11", 11, PTP_PF_NONE}, 9317a71c8aaSRadu Pirea (NXP OSS) }; 9327a71c8aaSRadu Pirea (NXP OSS) 9337a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, 9347a71c8aaSRadu Pirea (NXP OSS) enum ptp_pin_function func, unsigned int chan) 9357a71c8aaSRadu Pirea (NXP OSS) { 9367a71c8aaSRadu Pirea (NXP OSS) if (pin >= ARRAY_SIZE(nxp_c45_ptp_pins)) 9377a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 9387a71c8aaSRadu Pirea (NXP OSS) 9397a71c8aaSRadu Pirea (NXP OSS) switch (func) { 9407a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_NONE: 9417a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_PEROUT: 9427a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_EXTTS: 9437a71c8aaSRadu Pirea (NXP OSS) break; 9447a71c8aaSRadu Pirea (NXP OSS) default: 9457a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 9467a71c8aaSRadu Pirea (NXP OSS) } 9477a71c8aaSRadu Pirea (NXP OSS) 9487a71c8aaSRadu Pirea (NXP OSS) return 0; 9497a71c8aaSRadu Pirea (NXP OSS) } 9507a71c8aaSRadu Pirea (NXP OSS) 951514def5dSRadu Pirea (NXP OSS) static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv) 952514def5dSRadu Pirea (NXP OSS) { 953514def5dSRadu Pirea (NXP OSS) priv->caps = (struct ptp_clock_info) { 954514def5dSRadu Pirea (NXP OSS) .owner = THIS_MODULE, 955514def5dSRadu Pirea (NXP OSS) .name = "NXP C45 PHC", 956514def5dSRadu Pirea (NXP OSS) .max_adj = 16666666, 957514def5dSRadu Pirea (NXP OSS) .adjfine = nxp_c45_ptp_adjfine, 958514def5dSRadu Pirea (NXP OSS) .adjtime = nxp_c45_ptp_adjtime, 959514def5dSRadu Pirea (NXP OSS) .gettimex64 = nxp_c45_ptp_gettimex64, 960514def5dSRadu Pirea (NXP OSS) .settime64 = nxp_c45_ptp_settime64, 9617a71c8aaSRadu Pirea (NXP OSS) .enable = nxp_c45_ptp_enable, 9627a71c8aaSRadu Pirea (NXP OSS) .verify = nxp_c45_ptp_verify_pin, 963514def5dSRadu Pirea (NXP OSS) .do_aux_work = nxp_c45_do_aux_work, 9647a71c8aaSRadu Pirea (NXP OSS) .pin_config = nxp_c45_ptp_pins, 9657a71c8aaSRadu Pirea (NXP OSS) .n_pins = ARRAY_SIZE(nxp_c45_ptp_pins), 9667a71c8aaSRadu Pirea (NXP OSS) .n_ext_ts = 1, 9677a71c8aaSRadu Pirea (NXP OSS) .n_per_out = 1, 968514def5dSRadu Pirea (NXP OSS) }; 969514def5dSRadu Pirea (NXP OSS) 970514def5dSRadu Pirea (NXP OSS) priv->ptp_clock = ptp_clock_register(&priv->caps, 971514def5dSRadu Pirea (NXP OSS) &priv->phydev->mdio.dev); 972514def5dSRadu Pirea (NXP OSS) 973514def5dSRadu Pirea (NXP OSS) if (IS_ERR(priv->ptp_clock)) 974514def5dSRadu Pirea (NXP OSS) return PTR_ERR(priv->ptp_clock); 975514def5dSRadu Pirea (NXP OSS) 976514def5dSRadu Pirea (NXP OSS) if (!priv->ptp_clock) 977514def5dSRadu Pirea (NXP OSS) return -ENOMEM; 978514def5dSRadu Pirea (NXP OSS) 979514def5dSRadu Pirea (NXP OSS) return 0; 980514def5dSRadu Pirea (NXP OSS) } 981514def5dSRadu Pirea (NXP OSS) 982514def5dSRadu Pirea (NXP OSS) static void nxp_c45_txtstamp(struct mii_timestamper *mii_ts, 983514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type) 984514def5dSRadu Pirea (NXP OSS) { 985514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 986514def5dSRadu Pirea (NXP OSS) mii_ts); 987514def5dSRadu Pirea (NXP OSS) 988514def5dSRadu Pirea (NXP OSS) switch (priv->hwts_tx) { 989514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_ON: 990514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type = type; 991514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = ptp_parse_header(skb, type); 992514def5dSRadu Pirea (NXP OSS) skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 993514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->tx_queue, skb); 994514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev)) 995514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 996514def5dSRadu Pirea (NXP OSS) break; 997514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_OFF: 998514def5dSRadu Pirea (NXP OSS) default: 999514def5dSRadu Pirea (NXP OSS) kfree_skb(skb); 1000514def5dSRadu Pirea (NXP OSS) break; 1001514def5dSRadu Pirea (NXP OSS) } 1002514def5dSRadu Pirea (NXP OSS) } 1003514def5dSRadu Pirea (NXP OSS) 1004514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_rxtstamp(struct mii_timestamper *mii_ts, 1005514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type) 1006514def5dSRadu Pirea (NXP OSS) { 1007514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 1008514def5dSRadu Pirea (NXP OSS) mii_ts); 1009514def5dSRadu Pirea (NXP OSS) struct ptp_header *header = ptp_parse_header(skb, type); 1010514def5dSRadu Pirea (NXP OSS) 1011514def5dSRadu Pirea (NXP OSS) if (!header) 1012514def5dSRadu Pirea (NXP OSS) return false; 1013514def5dSRadu Pirea (NXP OSS) 1014514def5dSRadu Pirea (NXP OSS) if (!priv->hwts_rx) 1015514def5dSRadu Pirea (NXP OSS) return false; 1016514def5dSRadu Pirea (NXP OSS) 1017514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = header; 1018514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->rx_queue, skb); 1019514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 1020514def5dSRadu Pirea (NXP OSS) 1021514def5dSRadu Pirea (NXP OSS) return true; 1022514def5dSRadu Pirea (NXP OSS) } 1023514def5dSRadu Pirea (NXP OSS) 1024514def5dSRadu Pirea (NXP OSS) static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts, 1025514def5dSRadu Pirea (NXP OSS) struct ifreq *ifreq) 1026514def5dSRadu Pirea (NXP OSS) { 1027514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 1028514def5dSRadu Pirea (NXP OSS) mii_ts); 1029514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 10306c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data; 1031514def5dSRadu Pirea (NXP OSS) struct hwtstamp_config cfg; 1032514def5dSRadu Pirea (NXP OSS) 1033514def5dSRadu Pirea (NXP OSS) if (copy_from_user(&cfg, ifreq->ifr_data, sizeof(cfg))) 1034514def5dSRadu Pirea (NXP OSS) return -EFAULT; 1035514def5dSRadu Pirea (NXP OSS) 1036514def5dSRadu Pirea (NXP OSS) if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ON) 1037514def5dSRadu Pirea (NXP OSS) return -ERANGE; 1038514def5dSRadu Pirea (NXP OSS) 10396c0c85daSRadu Pirea (NXP OSS) data = nxp_c45_get_data(phydev); 1040514def5dSRadu Pirea (NXP OSS) priv->hwts_tx = cfg.tx_type; 1041514def5dSRadu Pirea (NXP OSS) 1042514def5dSRadu Pirea (NXP OSS) switch (cfg.rx_filter) { 1043514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_NONE: 1044514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 0; 1045514def5dSRadu Pirea (NXP OSS) break; 1046514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 1047514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 1048514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 1049514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 1; 1050514def5dSRadu Pirea (NXP OSS) cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; 1051514def5dSRadu Pirea (NXP OSS) break; 1052514def5dSRadu Pirea (NXP OSS) default: 1053514def5dSRadu Pirea (NXP OSS) return -ERANGE; 1054514def5dSRadu Pirea (NXP OSS) } 1055514def5dSRadu Pirea (NXP OSS) 1056514def5dSRadu Pirea (NXP OSS) if (priv->hwts_rx || priv->hwts_tx) { 10576c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 10586c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_event_msg_filt, 1059514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_ALL); 10606c0c85daSRadu Pirea (NXP OSS) data->ptp_enable(phydev, true); 1061514def5dSRadu Pirea (NXP OSS) } else { 10626c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 10636c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_event_msg_filt, 1064514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_NONE); 10656c0c85daSRadu Pirea (NXP OSS) data->ptp_enable(phydev, false); 1066514def5dSRadu Pirea (NXP OSS) } 1067514def5dSRadu Pirea (NXP OSS) 1068514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev)) 1069514def5dSRadu Pirea (NXP OSS) goto nxp_c45_no_ptp_irq; 1070514def5dSRadu Pirea (NXP OSS) 1071514def5dSRadu Pirea (NXP OSS) if (priv->hwts_tx) 10726c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(phydev, &data->regmap->irq_egr_ts_en); 1073514def5dSRadu Pirea (NXP OSS) else 10746c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(phydev, &data->regmap->irq_egr_ts_en); 1075514def5dSRadu Pirea (NXP OSS) 1076514def5dSRadu Pirea (NXP OSS) nxp_c45_no_ptp_irq: 1077514def5dSRadu Pirea (NXP OSS) return copy_to_user(ifreq->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 1078514def5dSRadu Pirea (NXP OSS) } 1079514def5dSRadu Pirea (NXP OSS) 1080514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ts_info(struct mii_timestamper *mii_ts, 1081514def5dSRadu Pirea (NXP OSS) struct ethtool_ts_info *ts_info) 1082514def5dSRadu Pirea (NXP OSS) { 1083514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 1084514def5dSRadu Pirea (NXP OSS) mii_ts); 1085514def5dSRadu Pirea (NXP OSS) 1086514def5dSRadu Pirea (NXP OSS) ts_info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | 1087514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RX_HARDWARE | 1088514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RAW_HARDWARE; 1089514def5dSRadu Pirea (NXP OSS) ts_info->phc_index = ptp_clock_index(priv->ptp_clock); 1090514def5dSRadu Pirea (NXP OSS) ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); 1091514def5dSRadu Pirea (NXP OSS) ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | 1092514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | 1093514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | 1094514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT); 1095514def5dSRadu Pirea (NXP OSS) 1096514def5dSRadu Pirea (NXP OSS) return 0; 1097514def5dSRadu Pirea (NXP OSS) } 1098514def5dSRadu Pirea (NXP OSS) 10996c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats common_hw_stats[] = { 11006c0c85daSRadu Pirea (NXP OSS) { "phy_link_status_drop_cnt", 11016c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 8, 6), }, 11026c0c85daSRadu Pirea (NXP OSS) { "phy_link_availability_drop_cnt", 11036c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 0, 6), }, 11046c0c85daSRadu Pirea (NXP OSS) { "phy_link_loss_cnt", 11056c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 10, 6), }, 11066c0c85daSRadu Pirea (NXP OSS) { "phy_link_failure_cnt", 11076c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 0, 10), }, 11086c0c85daSRadu Pirea (NXP OSS) { "phy_symbol_error_cnt", 11096c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8350, MDIO_MMD_VEND1, 0, 16) }, 11106c0c85daSRadu Pirea (NXP OSS) }; 11116c0c85daSRadu Pirea (NXP OSS) 11126c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1103_hw_stats[] = { 11136c0c85daSRadu Pirea (NXP OSS) { "rx_preamble_count", 11146c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFCE, MDIO_MMD_VEND1, 0, 6), }, 11156c0c85daSRadu Pirea (NXP OSS) { "tx_preamble_count", 11166c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFCF, MDIO_MMD_VEND1, 0, 6), }, 11176c0c85daSRadu Pirea (NXP OSS) { "rx_ipg_length", 11186c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFD0, MDIO_MMD_VEND1, 0, 9), }, 11196c0c85daSRadu Pirea (NXP OSS) { "tx_ipg_length", 11206c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFD1, MDIO_MMD_VEND1, 0, 9), }, 1121b050f2f1SRadu Pirea (NXP OSS) }; 1122b050f2f1SRadu Pirea (NXP OSS) 1123f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1120_hw_stats[] = { 1124f1fe5dffSRadu Pirea (NXP OSS) { "phy_symbol_error_cnt_ext", 1125f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8351, MDIO_MMD_VEND1, 0, 14) }, 1126f1fe5dffSRadu Pirea (NXP OSS) { "tx_frames_xtd", 1127f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA1, MDIO_MMD_VEND1, 0, 8), }, 1128f1fe5dffSRadu Pirea (NXP OSS) { "tx_frames", 1129f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA0, MDIO_MMD_VEND1, 0, 16), }, 1130f1fe5dffSRadu Pirea (NXP OSS) { "rx_frames_xtd", 1131f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA3, MDIO_MMD_VEND1, 0, 8), }, 1132f1fe5dffSRadu Pirea (NXP OSS) { "rx_frames", 1133f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA2, MDIO_MMD_VEND1, 0, 16), }, 1134f1fe5dffSRadu Pirea (NXP OSS) { "tx_lost_frames_xtd", 1135f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA5, MDIO_MMD_VEND1, 0, 8), }, 1136f1fe5dffSRadu Pirea (NXP OSS) { "tx_lost_frames", 1137f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA4, MDIO_MMD_VEND1, 0, 16), }, 1138f1fe5dffSRadu Pirea (NXP OSS) { "rx_lost_frames_xtd", 1139f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA7, MDIO_MMD_VEND1, 0, 8), }, 1140f1fe5dffSRadu Pirea (NXP OSS) { "rx_lost_frames", 1141f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA6, MDIO_MMD_VEND1, 0, 16), }, 1142f1fe5dffSRadu Pirea (NXP OSS) }; 1143f1fe5dffSRadu Pirea (NXP OSS) 1144b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev) 1145b050f2f1SRadu Pirea (NXP OSS) { 11466c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 11476c0c85daSRadu Pirea (NXP OSS) 11486c0c85daSRadu Pirea (NXP OSS) return ARRAY_SIZE(common_hw_stats) + (phy_data ? phy_data->n_stats : 0); 1149b050f2f1SRadu Pirea (NXP OSS) } 1150b050f2f1SRadu Pirea (NXP OSS) 1151b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data) 1152b050f2f1SRadu Pirea (NXP OSS) { 11536c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 11546c0c85daSRadu Pirea (NXP OSS) size_t count = nxp_c45_get_sset_count(phydev); 11556c0c85daSRadu Pirea (NXP OSS) size_t idx; 1156b050f2f1SRadu Pirea (NXP OSS) size_t i; 1157b050f2f1SRadu Pirea (NXP OSS) 11586c0c85daSRadu Pirea (NXP OSS) for (i = 0; i < count; i++) { 11596c0c85daSRadu Pirea (NXP OSS) if (i < ARRAY_SIZE(common_hw_stats)) { 11606c0c85daSRadu Pirea (NXP OSS) strscpy(data + i * ETH_GSTRING_LEN, 11616c0c85daSRadu Pirea (NXP OSS) common_hw_stats[i].name, ETH_GSTRING_LEN); 11626c0c85daSRadu Pirea (NXP OSS) continue; 11636c0c85daSRadu Pirea (NXP OSS) } 11646c0c85daSRadu Pirea (NXP OSS) idx = i - ARRAY_SIZE(common_hw_stats); 11656c0c85daSRadu Pirea (NXP OSS) strscpy(data + i * ETH_GSTRING_LEN, 11666c0c85daSRadu Pirea (NXP OSS) phy_data->stats[idx].name, ETH_GSTRING_LEN); 1167b050f2f1SRadu Pirea (NXP OSS) } 1168b050f2f1SRadu Pirea (NXP OSS) } 1169b050f2f1SRadu Pirea (NXP OSS) 1170b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev, 1171b050f2f1SRadu Pirea (NXP OSS) struct ethtool_stats *stats, u64 *data) 1172b050f2f1SRadu Pirea (NXP OSS) { 11736c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 11746c0c85daSRadu Pirea (NXP OSS) size_t count = nxp_c45_get_sset_count(phydev); 11756c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field; 11766c0c85daSRadu Pirea (NXP OSS) size_t idx; 1177b050f2f1SRadu Pirea (NXP OSS) size_t i; 1178b050f2f1SRadu Pirea (NXP OSS) int ret; 1179b050f2f1SRadu Pirea (NXP OSS) 11806c0c85daSRadu Pirea (NXP OSS) for (i = 0; i < count; i++) { 11816c0c85daSRadu Pirea (NXP OSS) if (i < ARRAY_SIZE(common_hw_stats)) { 11826c0c85daSRadu Pirea (NXP OSS) reg_field = &common_hw_stats[i].counter; 1183b050f2f1SRadu Pirea (NXP OSS) } else { 11846c0c85daSRadu Pirea (NXP OSS) idx = i - ARRAY_SIZE(common_hw_stats); 11856c0c85daSRadu Pirea (NXP OSS) reg_field = &phy_data->stats[idx].counter; 1186b050f2f1SRadu Pirea (NXP OSS) } 11876c0c85daSRadu Pirea (NXP OSS) 11886c0c85daSRadu Pirea (NXP OSS) ret = nxp_c45_read_reg_field(phydev, reg_field); 11896c0c85daSRadu Pirea (NXP OSS) if (ret < 0) 11906c0c85daSRadu Pirea (NXP OSS) data[i] = U64_MAX; 11916c0c85daSRadu Pirea (NXP OSS) else 11926c0c85daSRadu Pirea (NXP OSS) data[i] = ret; 1193b050f2f1SRadu Pirea (NXP OSS) } 1194b050f2f1SRadu Pirea (NXP OSS) } 1195b050f2f1SRadu Pirea (NXP OSS) 1196b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev) 1197b050f2f1SRadu Pirea (NXP OSS) { 1198b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 1199b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_GLOBAL_EN | 1200b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_ALL_EN); 1201b050f2f1SRadu Pirea (NXP OSS) usleep_range(400, 450); 1202b050f2f1SRadu Pirea (NXP OSS) 1203b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL, 1204b050f2f1SRadu Pirea (NXP OSS) PORT_CONTROL_EN); 1205b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 1206b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_EN); 1207b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL, 1208b050f2f1SRadu Pirea (NXP OSS) PORT_INFRA_CONTROL_EN); 1209b050f2f1SRadu Pirea (NXP OSS) 1210b050f2f1SRadu Pirea (NXP OSS) return 0; 1211b050f2f1SRadu Pirea (NXP OSS) } 1212b050f2f1SRadu Pirea (NXP OSS) 1213b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev) 1214b050f2f1SRadu Pirea (NXP OSS) { 1215b050f2f1SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 1216b050f2f1SRadu Pirea (NXP OSS) PHY_START_OP); 1217b050f2f1SRadu Pirea (NXP OSS) } 1218b050f2f1SRadu Pirea (NXP OSS) 1219b2f0ca00SRadu Pirea (NXP OSS) static int nxp_c45_config_intr(struct phy_device *phydev) 1220b2f0ca00SRadu Pirea (NXP OSS) { 1221b2f0ca00SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1222b2f0ca00SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1223b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 1224b2f0ca00SRadu Pirea (NXP OSS) else 1225b2f0ca00SRadu Pirea (NXP OSS) return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1226b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 1227b2f0ca00SRadu Pirea (NXP OSS) } 1228b2f0ca00SRadu Pirea (NXP OSS) 1229425c8348SRadu Pirea (NXP OSS) static int tja1103_config_intr(struct phy_device *phydev) 1230425c8348SRadu Pirea (NXP OSS) { 1231425c8348SRadu Pirea (NXP OSS) int ret; 1232425c8348SRadu Pirea (NXP OSS) 1233425c8348SRadu Pirea (NXP OSS) /* We can't disable the FUSA IRQ for TJA1103, but we can clean it up. */ 1234425c8348SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_ALWAYS_ACCESSIBLE, 1235425c8348SRadu Pirea (NXP OSS) FUSA_PASS); 1236425c8348SRadu Pirea (NXP OSS) if (ret) 1237425c8348SRadu Pirea (NXP OSS) return ret; 1238425c8348SRadu Pirea (NXP OSS) 1239425c8348SRadu Pirea (NXP OSS) return nxp_c45_config_intr(phydev); 1240425c8348SRadu Pirea (NXP OSS) } 1241425c8348SRadu Pirea (NXP OSS) 1242425c8348SRadu Pirea (NXP OSS) static int tja1120_config_intr(struct phy_device *phydev) 1243425c8348SRadu Pirea (NXP OSS) { 1244425c8348SRadu Pirea (NXP OSS) int ret; 1245425c8348SRadu Pirea (NXP OSS) 1246425c8348SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1247425c8348SRadu Pirea (NXP OSS) ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1248425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_EN, 1249425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE); 1250425c8348SRadu Pirea (NXP OSS) else 1251425c8348SRadu Pirea (NXP OSS) ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1252425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_EN, 1253425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE); 1254425c8348SRadu Pirea (NXP OSS) if (ret) 1255425c8348SRadu Pirea (NXP OSS) return ret; 1256425c8348SRadu Pirea (NXP OSS) 1257425c8348SRadu Pirea (NXP OSS) return nxp_c45_config_intr(phydev); 1258425c8348SRadu Pirea (NXP OSS) } 1259425c8348SRadu Pirea (NXP OSS) 1260b2f0ca00SRadu Pirea (NXP OSS) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) 1261b2f0ca00SRadu Pirea (NXP OSS) { 12626c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 1263514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1264b2f0ca00SRadu Pirea (NXP OSS) irqreturn_t ret = IRQ_NONE; 1265514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts; 1266b2f0ca00SRadu Pirea (NXP OSS) int irq; 1267b2f0ca00SRadu Pirea (NXP OSS) 1268b2f0ca00SRadu Pirea (NXP OSS) irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS); 1269b2f0ca00SRadu Pirea (NXP OSS) if (irq & PHY_IRQ_LINK_EVENT) { 1270b2f0ca00SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK, 1271b2f0ca00SRadu Pirea (NXP OSS) PHY_IRQ_LINK_EVENT); 1272b2f0ca00SRadu Pirea (NXP OSS) phy_trigger_machine(phydev); 1273b2f0ca00SRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 1274b2f0ca00SRadu Pirea (NXP OSS) } 1275b2f0ca00SRadu Pirea (NXP OSS) 12766c0c85daSRadu Pirea (NXP OSS) irq = nxp_c45_read_reg_field(phydev, &data->regmap->irq_egr_ts_status); 12776c0c85daSRadu Pirea (NXP OSS) if (irq) { 1278bdb4c5b8SRadu Pirea (NXP OSS) /* If ack_ptp_irq is false, the IRQ bit is self-clear and will 1279bdb4c5b8SRadu Pirea (NXP OSS) * be cleared when the EGR TS FIFO is empty. Otherwise, the 1280bdb4c5b8SRadu Pirea (NXP OSS) * IRQ bit should be cleared before reading the timestamp, 1281bdb4c5b8SRadu Pirea (NXP OSS) */ 1282bdb4c5b8SRadu Pirea (NXP OSS) if (data->ack_ptp_irq) 1283bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 1284bdb4c5b8SRadu Pirea (NXP OSS) VEND1_PTP_IRQ_ACK, EGR_TS_IRQ); 1285bdb4c5b8SRadu Pirea (NXP OSS) while (data->get_egressts(priv, &hwts)) 1286514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts); 1287514def5dSRadu Pirea (NXP OSS) 1288514def5dSRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 1289514def5dSRadu Pirea (NXP OSS) } 1290514def5dSRadu Pirea (NXP OSS) 1291425c8348SRadu Pirea (NXP OSS) data->nmi_handler(phydev, &ret); 1292425c8348SRadu Pirea (NXP OSS) 1293b2f0ca00SRadu Pirea (NXP OSS) return ret; 1294b2f0ca00SRadu Pirea (NXP OSS) } 1295b2f0ca00SRadu Pirea (NXP OSS) 1296b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev) 1297b050f2f1SRadu Pirea (NXP OSS) { 1298b050f2f1SRadu Pirea (NXP OSS) int ret; 1299b050f2f1SRadu Pirea (NXP OSS) 1300b050f2f1SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 1301b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_RESET); 1302b050f2f1SRadu Pirea (NXP OSS) if (ret) 1303b050f2f1SRadu Pirea (NXP OSS) return ret; 1304b050f2f1SRadu Pirea (NXP OSS) 1305b050f2f1SRadu Pirea (NXP OSS) return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 1306b050f2f1SRadu Pirea (NXP OSS) VEND1_DEVICE_CONTROL, ret, 1307b050f2f1SRadu Pirea (NXP OSS) !(ret & DEVICE_CONTROL_RESET), 20000, 1308b050f2f1SRadu Pirea (NXP OSS) 240000, false); 1309b050f2f1SRadu Pirea (NXP OSS) } 1310b050f2f1SRadu Pirea (NXP OSS) 1311b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev) 1312b050f2f1SRadu Pirea (NXP OSS) { 13136c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); 13146c0c85daSRadu Pirea (NXP OSS) 1315c552c110SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1316c552c110SRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE); 13176c0c85daSRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, 1318b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE | CABLE_TEST_START); 1319b050f2f1SRadu Pirea (NXP OSS) } 1320b050f2f1SRadu Pirea (NXP OSS) 1321b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev, 1322b050f2f1SRadu Pirea (NXP OSS) bool *finished) 1323b050f2f1SRadu Pirea (NXP OSS) { 13246c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); 1325b050f2f1SRadu Pirea (NXP OSS) int ret; 1326b050f2f1SRadu Pirea (NXP OSS) u8 cable_test_result; 1327b050f2f1SRadu Pirea (NXP OSS) 13286c0c85daSRadu Pirea (NXP OSS) ret = nxp_c45_read_reg_field(phydev, ®map->cable_test_valid); 13296c0c85daSRadu Pirea (NXP OSS) if (!ret) { 1330b050f2f1SRadu Pirea (NXP OSS) *finished = false; 1331b050f2f1SRadu Pirea (NXP OSS) return 0; 1332b050f2f1SRadu Pirea (NXP OSS) } 1333b050f2f1SRadu Pirea (NXP OSS) 1334b050f2f1SRadu Pirea (NXP OSS) *finished = true; 13356c0c85daSRadu Pirea (NXP OSS) cable_test_result = nxp_c45_read_reg_field(phydev, 13366c0c85daSRadu Pirea (NXP OSS) ®map->cable_test_result); 1337b050f2f1SRadu Pirea (NXP OSS) 1338b050f2f1SRadu Pirea (NXP OSS) switch (cable_test_result) { 1339b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OK: 1340b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1341b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OK); 1342b050f2f1SRadu Pirea (NXP OSS) break; 1343b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_SHORTED: 1344b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1345b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT); 1346b050f2f1SRadu Pirea (NXP OSS) break; 1347b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OPEN: 1348b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1349b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OPEN); 1350b050f2f1SRadu Pirea (NXP OSS) break; 1351b050f2f1SRadu Pirea (NXP OSS) default: 1352b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1353b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC); 1354b050f2f1SRadu Pirea (NXP OSS) } 1355b050f2f1SRadu Pirea (NXP OSS) 13566c0c85daSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, 1357b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE); 1358c552c110SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1359c552c110SRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE); 1360b050f2f1SRadu Pirea (NXP OSS) 1361b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 1362b050f2f1SRadu Pirea (NXP OSS) } 1363b050f2f1SRadu Pirea (NXP OSS) 1364b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev) 1365b050f2f1SRadu Pirea (NXP OSS) { 1366b050f2f1SRadu Pirea (NXP OSS) int reg; 1367b050f2f1SRadu Pirea (NXP OSS) 1368b050f2f1SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY); 1369b050f2f1SRadu Pirea (NXP OSS) if (!(reg & SQI_VALID)) 1370b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1371b050f2f1SRadu Pirea (NXP OSS) 1372b050f2f1SRadu Pirea (NXP OSS) reg &= SQI_MASK; 1373b050f2f1SRadu Pirea (NXP OSS) 1374b050f2f1SRadu Pirea (NXP OSS) return reg; 1375b050f2f1SRadu Pirea (NXP OSS) } 1376b050f2f1SRadu Pirea (NXP OSS) 1377*68c6af72SRadu Pirea (NXP OSS) static void tja1120_link_change_notify(struct phy_device *phydev) 1378*68c6af72SRadu Pirea (NXP OSS) { 1379*68c6af72SRadu Pirea (NXP OSS) /* Bug workaround for TJA1120 enegineering samples: fix egress 1380*68c6af72SRadu Pirea (NXP OSS) * timestamps lost after link recovery. 1381*68c6af72SRadu Pirea (NXP OSS) */ 1382*68c6af72SRadu Pirea (NXP OSS) if (phydev->state == PHY_NOLINK) { 1383*68c6af72SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1384*68c6af72SRadu Pirea (NXP OSS) TJA1120_EPHY_RESETS, EPHY_PCS_RESET); 1385*68c6af72SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1386*68c6af72SRadu Pirea (NXP OSS) TJA1120_EPHY_RESETS, EPHY_PCS_RESET); 1387*68c6af72SRadu Pirea (NXP OSS) } 1388*68c6af72SRadu Pirea (NXP OSS) } 1389*68c6af72SRadu Pirea (NXP OSS) 1390b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev) 1391b050f2f1SRadu Pirea (NXP OSS) { 1392b050f2f1SRadu Pirea (NXP OSS) return MAX_SQI; 1393b050f2f1SRadu Pirea (NXP OSS) } 1394b050f2f1SRadu Pirea (NXP OSS) 1395b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay) 1396b050f2f1SRadu Pirea (NXP OSS) { 1397b050f2f1SRadu Pirea (NXP OSS) if (delay < MIN_ID_PS) { 1398b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS); 1399b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1400b050f2f1SRadu Pirea (NXP OSS) } 1401b050f2f1SRadu Pirea (NXP OSS) 1402b050f2f1SRadu Pirea (NXP OSS) if (delay > MAX_ID_PS) { 1403b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS); 1404b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1405b050f2f1SRadu Pirea (NXP OSS) } 1406b050f2f1SRadu Pirea (NXP OSS) 1407b050f2f1SRadu Pirea (NXP OSS) return 0; 1408b050f2f1SRadu Pirea (NXP OSS) } 1409b050f2f1SRadu Pirea (NXP OSS) 14106c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_counters_enable(struct phy_device *phydev) 14116c0c85daSRadu Pirea (NXP OSS) { 14126c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 14136c0c85daSRadu Pirea (NXP OSS) 14146c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER, 14156c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 14166c0c85daSRadu Pirea (NXP OSS) 14176c0c85daSRadu Pirea (NXP OSS) data->counters_enable(phydev); 14186c0c85daSRadu Pirea (NXP OSS) } 14196c0c85daSRadu Pirea (NXP OSS) 14206c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_ptp_init(struct phy_device *phydev) 14216c0c85daSRadu Pirea (NXP OSS) { 14226c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 14236c0c85daSRadu Pirea (NXP OSS) 14246c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 14256c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_ptp_clk_period, 14266c0c85daSRadu Pirea (NXP OSS) data->ptp_clk_period); 14276c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(phydev, &data->regmap->ltc_lock_ctrl); 14286c0c85daSRadu Pirea (NXP OSS) 14296c0c85daSRadu Pirea (NXP OSS) data->ptp_init(phydev); 14306c0c85daSRadu Pirea (NXP OSS) } 14316c0c85daSRadu Pirea (NXP OSS) 1432b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw) 1433b050f2f1SRadu Pirea (NXP OSS) { 1434b050f2f1SRadu Pirea (NXP OSS) /* The delay in degree phase is 73.8 + phase_offset_raw * 0.9. 1435b050f2f1SRadu Pirea (NXP OSS) * To avoid floating point operations we'll multiply by 10 1436b050f2f1SRadu Pirea (NXP OSS) * and get 1 decimal point precision. 1437b050f2f1SRadu Pirea (NXP OSS) */ 1438b050f2f1SRadu Pirea (NXP OSS) phase_offset_raw *= 10; 14396b3a6310SRadu Pirea (NXP OSS) phase_offset_raw -= 738; 1440b050f2f1SRadu Pirea (NXP OSS) return div_u64(phase_offset_raw, 9); 1441b050f2f1SRadu Pirea (NXP OSS) } 1442b050f2f1SRadu Pirea (NXP OSS) 1443b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev) 1444b050f2f1SRadu Pirea (NXP OSS) { 1445b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE); 1446b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE); 1447b050f2f1SRadu Pirea (NXP OSS) } 1448b050f2f1SRadu Pirea (NXP OSS) 1449b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev) 1450b050f2f1SRadu Pirea (NXP OSS) { 1451b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1452b050f2f1SRadu Pirea (NXP OSS) u64 tx_delay = priv->tx_delay; 1453b050f2f1SRadu Pirea (NXP OSS) u64 rx_delay = priv->rx_delay; 1454b050f2f1SRadu Pirea (NXP OSS) u64 degree; 1455b050f2f1SRadu Pirea (NXP OSS) 1456b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1457b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 1458b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(tx_delay, PS_PER_DEGREE); 1459b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 1460b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 1461b050f2f1SRadu Pirea (NXP OSS) } else { 1462b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 1463b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 1464b050f2f1SRadu Pirea (NXP OSS) } 1465b050f2f1SRadu Pirea (NXP OSS) 1466b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1467b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 1468b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(rx_delay, PS_PER_DEGREE); 1469b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 1470b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 1471b050f2f1SRadu Pirea (NXP OSS) } else { 1472b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 1473b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 1474b050f2f1SRadu Pirea (NXP OSS) } 1475b050f2f1SRadu Pirea (NXP OSS) } 1476b050f2f1SRadu Pirea (NXP OSS) 1477b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev) 1478b050f2f1SRadu Pirea (NXP OSS) { 1479b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1480b050f2f1SRadu Pirea (NXP OSS) int ret; 1481b050f2f1SRadu Pirea (NXP OSS) 1482b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1483b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 1484b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 1485b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps", 1486b050f2f1SRadu Pirea (NXP OSS) &priv->tx_delay); 1487b050f2f1SRadu Pirea (NXP OSS) if (ret) 1488b050f2f1SRadu Pirea (NXP OSS) priv->tx_delay = DEFAULT_ID_PS; 1489b050f2f1SRadu Pirea (NXP OSS) 1490b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->tx_delay); 1491b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1492b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 1493b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps invalid value\n"); 1494b050f2f1SRadu Pirea (NXP OSS) return ret; 1495b050f2f1SRadu Pirea (NXP OSS) } 1496b050f2f1SRadu Pirea (NXP OSS) } 1497b050f2f1SRadu Pirea (NXP OSS) 1498b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1499b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 1500b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 1501b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps", 1502b050f2f1SRadu Pirea (NXP OSS) &priv->rx_delay); 1503b050f2f1SRadu Pirea (NXP OSS) if (ret) 1504b050f2f1SRadu Pirea (NXP OSS) priv->rx_delay = DEFAULT_ID_PS; 1505b050f2f1SRadu Pirea (NXP OSS) 1506b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->rx_delay); 1507b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1508b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 1509b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps invalid value\n"); 1510b050f2f1SRadu Pirea (NXP OSS) return ret; 1511b050f2f1SRadu Pirea (NXP OSS) } 1512b050f2f1SRadu Pirea (NXP OSS) } 1513b050f2f1SRadu Pirea (NXP OSS) 1514b050f2f1SRadu Pirea (NXP OSS) return 0; 1515b050f2f1SRadu Pirea (NXP OSS) } 1516b050f2f1SRadu Pirea (NXP OSS) 1517b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev) 1518b050f2f1SRadu Pirea (NXP OSS) { 1519b050f2f1SRadu Pirea (NXP OSS) int ret; 1520b050f2f1SRadu Pirea (NXP OSS) 1521b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES); 1522b050f2f1SRadu Pirea (NXP OSS) phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret); 1523b050f2f1SRadu Pirea (NXP OSS) 1524b050f2f1SRadu Pirea (NXP OSS) switch (phydev->interface) { 1525b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII: 1526b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ABILITY)) { 1527b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii mode not supported\n"); 1528b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1529b050f2f1SRadu Pirea (NXP OSS) } 1530b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1531b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 1532b050f2f1SRadu Pirea (NXP OSS) nxp_c45_disable_delays(phydev); 1533b050f2f1SRadu Pirea (NXP OSS) break; 1534b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_ID: 1535b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_TXID: 1536b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_RXID: 1537b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ID_ABILITY)) { 1538b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n"); 1539b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1540b050f2f1SRadu Pirea (NXP OSS) } 1541b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1542b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 1543b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_get_delays(phydev); 1544b050f2f1SRadu Pirea (NXP OSS) if (ret) 1545b050f2f1SRadu Pirea (NXP OSS) return ret; 1546b050f2f1SRadu Pirea (NXP OSS) 1547b050f2f1SRadu Pirea (NXP OSS) nxp_c45_set_delays(phydev); 1548b050f2f1SRadu Pirea (NXP OSS) break; 1549b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_MII: 1550b050f2f1SRadu Pirea (NXP OSS) if (!(ret & MII_ABILITY)) { 1551b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "mii mode not supported\n"); 1552b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1553b050f2f1SRadu Pirea (NXP OSS) } 1554b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1555b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII); 1556b050f2f1SRadu Pirea (NXP OSS) break; 1557b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_REVMII: 1558b050f2f1SRadu Pirea (NXP OSS) if (!(ret & REVMII_ABILITY)) { 1559b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rev-mii mode not supported\n"); 1560b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1561b050f2f1SRadu Pirea (NXP OSS) } 1562b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1563b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII | MII_BASIC_CONFIG_REV); 1564b050f2f1SRadu Pirea (NXP OSS) break; 1565b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RMII: 1566b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RMII_ABILITY)) { 1567b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rmii mode not supported\n"); 1568b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1569b050f2f1SRadu Pirea (NXP OSS) } 1570b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1571b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RMII); 1572b050f2f1SRadu Pirea (NXP OSS) break; 1573b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_SGMII: 1574b050f2f1SRadu Pirea (NXP OSS) if (!(ret & SGMII_ABILITY)) { 1575b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "sgmii mode not supported\n"); 1576b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1577b050f2f1SRadu Pirea (NXP OSS) } 1578b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1579b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_SGMII); 1580b050f2f1SRadu Pirea (NXP OSS) break; 1581b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_INTERNAL: 1582b050f2f1SRadu Pirea (NXP OSS) break; 1583b050f2f1SRadu Pirea (NXP OSS) default: 1584b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1585b050f2f1SRadu Pirea (NXP OSS) } 1586b050f2f1SRadu Pirea (NXP OSS) 1587b050f2f1SRadu Pirea (NXP OSS) return 0; 1588b050f2f1SRadu Pirea (NXP OSS) } 1589b050f2f1SRadu Pirea (NXP OSS) 1590b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev) 1591b050f2f1SRadu Pirea (NXP OSS) { 1592b050f2f1SRadu Pirea (NXP OSS) int ret; 1593b050f2f1SRadu Pirea (NXP OSS) 1594b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_config_enable(phydev); 1595b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1596b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "Failed to enable config\n"); 1597b050f2f1SRadu Pirea (NXP OSS) return ret; 1598b050f2f1SRadu Pirea (NXP OSS) } 1599b050f2f1SRadu Pirea (NXP OSS) 16000b5f0f29SVladimir Oltean /* Bug workaround for SJA1110 rev B: enable write access 16010b5f0f29SVladimir Oltean * to MDIO_MMD_PMAPMD 16020b5f0f29SVladimir Oltean */ 16030b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1); 16040b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2); 16050b5f0f29SVladimir Oltean 1606b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG, 1607b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_AUTO); 1608b050f2f1SRadu Pirea (NXP OSS) 1609b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_set_phy_mode(phydev); 1610b050f2f1SRadu Pirea (NXP OSS) if (ret) 1611b050f2f1SRadu Pirea (NXP OSS) return ret; 1612b050f2f1SRadu Pirea (NXP OSS) 1613b050f2f1SRadu Pirea (NXP OSS) phydev->autoneg = AUTONEG_DISABLE; 1614b050f2f1SRadu Pirea (NXP OSS) 16156c0c85daSRadu Pirea (NXP OSS) nxp_c45_counters_enable(phydev); 16166c0c85daSRadu Pirea (NXP OSS) nxp_c45_ptp_init(phydev); 1617514def5dSRadu Pirea (NXP OSS) 1618b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 1619b050f2f1SRadu Pirea (NXP OSS) } 1620b050f2f1SRadu Pirea (NXP OSS) 1621369da333SRadu Pirea (NXP OSS) static int nxp_c45_get_features(struct phy_device *phydev) 1622369da333SRadu Pirea (NXP OSS) { 1623369da333SRadu Pirea (NXP OSS) linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported); 1624369da333SRadu Pirea (NXP OSS) linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported); 1625369da333SRadu Pirea (NXP OSS) 1626369da333SRadu Pirea (NXP OSS) return genphy_c45_pma_read_abilities(phydev); 1627369da333SRadu Pirea (NXP OSS) } 1628369da333SRadu Pirea (NXP OSS) 1629b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev) 1630b050f2f1SRadu Pirea (NXP OSS) { 1631b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv; 1632514def5dSRadu Pirea (NXP OSS) int ptp_ability; 1633514def5dSRadu Pirea (NXP OSS) int ret = 0; 1634b050f2f1SRadu Pirea (NXP OSS) 1635b050f2f1SRadu Pirea (NXP OSS) priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 1636b050f2f1SRadu Pirea (NXP OSS) if (!priv) 1637b050f2f1SRadu Pirea (NXP OSS) return -ENOMEM; 1638b050f2f1SRadu Pirea (NXP OSS) 1639514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->tx_queue); 1640514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->rx_queue); 1641514def5dSRadu Pirea (NXP OSS) 1642514def5dSRadu Pirea (NXP OSS) priv->phydev = phydev; 1643514def5dSRadu Pirea (NXP OSS) 1644b050f2f1SRadu Pirea (NXP OSS) phydev->priv = priv; 1645b050f2f1SRadu Pirea (NXP OSS) 1646514def5dSRadu Pirea (NXP OSS) mutex_init(&priv->ptp_lock); 1647514def5dSRadu Pirea (NXP OSS) 1648514def5dSRadu Pirea (NXP OSS) ptp_ability = phy_read_mmd(phydev, MDIO_MMD_VEND1, 1649514def5dSRadu Pirea (NXP OSS) VEND1_PORT_ABILITIES); 1650514def5dSRadu Pirea (NXP OSS) ptp_ability = !!(ptp_ability & PTP_ABILITY); 1651514def5dSRadu Pirea (NXP OSS) if (!ptp_ability) { 1652565c6d8cSVladimir Oltean phydev_dbg(phydev, "the phy does not support PTP"); 1653514def5dSRadu Pirea (NXP OSS) goto no_ptp_support; 1654514def5dSRadu Pirea (NXP OSS) } 1655514def5dSRadu Pirea (NXP OSS) 1656514def5dSRadu Pirea (NXP OSS) if (IS_ENABLED(CONFIG_PTP_1588_CLOCK) && 1657514def5dSRadu Pirea (NXP OSS) IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) { 1658514def5dSRadu Pirea (NXP OSS) priv->mii_ts.rxtstamp = nxp_c45_rxtstamp; 1659514def5dSRadu Pirea (NXP OSS) priv->mii_ts.txtstamp = nxp_c45_txtstamp; 1660514def5dSRadu Pirea (NXP OSS) priv->mii_ts.hwtstamp = nxp_c45_hwtstamp; 1661514def5dSRadu Pirea (NXP OSS) priv->mii_ts.ts_info = nxp_c45_ts_info; 1662514def5dSRadu Pirea (NXP OSS) phydev->mii_ts = &priv->mii_ts; 1663514def5dSRadu Pirea (NXP OSS) ret = nxp_c45_init_ptp_clock(priv); 1664514def5dSRadu Pirea (NXP OSS) } else { 1665514def5dSRadu Pirea (NXP OSS) phydev_dbg(phydev, "PTP support not enabled even if the phy supports it"); 1666514def5dSRadu Pirea (NXP OSS) } 1667514def5dSRadu Pirea (NXP OSS) 1668514def5dSRadu Pirea (NXP OSS) no_ptp_support: 1669514def5dSRadu Pirea (NXP OSS) 1670514def5dSRadu Pirea (NXP OSS) return ret; 1671b050f2f1SRadu Pirea (NXP OSS) } 1672b050f2f1SRadu Pirea (NXP OSS) 1673a4506722SRadu Pirea (OSS) static void nxp_c45_remove(struct phy_device *phydev) 1674a4506722SRadu Pirea (OSS) { 1675a4506722SRadu Pirea (OSS) struct nxp_c45_phy *priv = phydev->priv; 1676a4506722SRadu Pirea (OSS) 1677a4506722SRadu Pirea (OSS) if (priv->ptp_clock) 1678a4506722SRadu Pirea (OSS) ptp_clock_unregister(priv->ptp_clock); 1679a4506722SRadu Pirea (OSS) 1680a4506722SRadu Pirea (OSS) skb_queue_purge(&priv->tx_queue); 1681a4506722SRadu Pirea (OSS) skb_queue_purge(&priv->rx_queue); 1682a4506722SRadu Pirea (OSS) } 1683a4506722SRadu Pirea (OSS) 16846c0c85daSRadu Pirea (NXP OSS) static void tja1103_counters_enable(struct phy_device *phydev) 16856c0c85daSRadu Pirea (NXP OSS) { 16866c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT, 16876c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 16886c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT, 16896c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 16906c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH, 16916c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 16926c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH, 16936c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 16946c0c85daSRadu Pirea (NXP OSS) } 16956c0c85daSRadu Pirea (NXP OSS) 16966c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_init(struct phy_device *phydev) 16976c0c85daSRadu Pirea (NXP OSS) { 16986c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL, 16996c0c85daSRadu Pirea (NXP OSS) TJA1103_RX_TS_INSRT_MODE2); 17006c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES, 17016c0c85daSRadu Pirea (NXP OSS) PTP_ENABLE); 17026c0c85daSRadu Pirea (NXP OSS) } 17036c0c85daSRadu Pirea (NXP OSS) 17046c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_enable(struct phy_device *phydev, bool enable) 17056c0c85daSRadu Pirea (NXP OSS) { 17066c0c85daSRadu Pirea (NXP OSS) if (enable) 17076c0c85daSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 17086c0c85daSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL, 17096c0c85daSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS); 17106c0c85daSRadu Pirea (NXP OSS) else 17116c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 17126c0c85daSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL, 17136c0c85daSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS); 17146c0c85daSRadu Pirea (NXP OSS) } 17156c0c85daSRadu Pirea (NXP OSS) 1716425c8348SRadu Pirea (NXP OSS) static void tja1103_nmi_handler(struct phy_device *phydev, 1717425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status) 1718425c8348SRadu Pirea (NXP OSS) { 1719425c8348SRadu Pirea (NXP OSS) int ret; 1720425c8348SRadu Pirea (NXP OSS) 1721425c8348SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, 1722425c8348SRadu Pirea (NXP OSS) VEND1_ALWAYS_ACCESSIBLE); 1723425c8348SRadu Pirea (NXP OSS) if (ret & FUSA_PASS) { 1724425c8348SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 1725425c8348SRadu Pirea (NXP OSS) VEND1_ALWAYS_ACCESSIBLE, 1726425c8348SRadu Pirea (NXP OSS) FUSA_PASS); 1727425c8348SRadu Pirea (NXP OSS) *irq_status = IRQ_HANDLED; 1728425c8348SRadu Pirea (NXP OSS) } 1729425c8348SRadu Pirea (NXP OSS) } 1730425c8348SRadu Pirea (NXP OSS) 17316c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1103_regmap = { 17326c0c85daSRadu Pirea (NXP OSS) .vend1_ptp_clk_period = 0x1104, 17336c0c85daSRadu Pirea (NXP OSS) .vend1_event_msg_filt = 0x1148, 17346c0c85daSRadu Pirea (NXP OSS) .pps_enable = 17356c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 3, 1), 17366c0c85daSRadu Pirea (NXP OSS) .pps_polarity = 17376c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 2, 1), 17386c0c85daSRadu Pirea (NXP OSS) .ltc_lock_ctrl = 17396c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1115, MDIO_MMD_VEND1, 0, 1), 17406c0c85daSRadu Pirea (NXP OSS) .ltc_read = 17416c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 2, 1), 17426c0c85daSRadu Pirea (NXP OSS) .ltc_write = 17436c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 0, 1), 17446c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_0 = 0x1106, 17456c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_1 = 0x1107, 17466c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_0 = 0x1108, 17476c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_1 = 0x1109, 17486c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_0 = 0x110A, 17496c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_1 = 0x110B, 17506c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_0 = 0x110C, 17516c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_1 = 0x110D, 17526c0c85daSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_0 = 0x110F, 17536c0c85daSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_1 = 0x1110, 17546c0c85daSRadu Pirea (NXP OSS) .irq_egr_ts_en = 17556c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1131, MDIO_MMD_VEND1, 0, 1), 17566c0c85daSRadu Pirea (NXP OSS) .irq_egr_ts_status = 17576c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1132, MDIO_MMD_VEND1, 0, 1), 17586c0c85daSRadu Pirea (NXP OSS) .domain_number = 17596c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 0, 8), 17606c0c85daSRadu Pirea (NXP OSS) .msg_type = 17616c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 8, 4), 17626c0c85daSRadu Pirea (NXP OSS) .sequence_id = 17636c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114F, MDIO_MMD_VEND1, 0, 16), 17646c0c85daSRadu Pirea (NXP OSS) .sec_1_0 = 17656c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 14, 2), 17666c0c85daSRadu Pirea (NXP OSS) .sec_4_2 = 17676c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 12, 3), 17686c0c85daSRadu Pirea (NXP OSS) .nsec_15_0 = 17696c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1150, MDIO_MMD_VEND1, 0, 16), 17706c0c85daSRadu Pirea (NXP OSS) .nsec_29_16 = 17716c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 0, 14), 17726c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_0 = 0x1121, 17736c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_1 = 0x1122, 17746c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_2 = 0x1123, 17756c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_3 = 0x1124, 17766c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_ctrl = 0x1126, 17776c0c85daSRadu Pirea (NXP OSS) .cable_test = 0x8330, 17786c0c85daSRadu Pirea (NXP OSS) .cable_test_valid = 17796c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 13, 1), 17806c0c85daSRadu Pirea (NXP OSS) .cable_test_result = 17816c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 0, 3), 17826c0c85daSRadu Pirea (NXP OSS) }; 17836c0c85daSRadu Pirea (NXP OSS) 17846c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1103_phy_data = { 17856c0c85daSRadu Pirea (NXP OSS) .regmap = &tja1103_regmap, 17866c0c85daSRadu Pirea (NXP OSS) .stats = tja1103_hw_stats, 17876c0c85daSRadu Pirea (NXP OSS) .n_stats = ARRAY_SIZE(tja1103_hw_stats), 17886c0c85daSRadu Pirea (NXP OSS) .ptp_clk_period = PTP_CLK_PERIOD_100BT1, 1789b0b2247dSRadu Pirea (NXP OSS) .ext_ts_both_edges = false, 1790bdb4c5b8SRadu Pirea (NXP OSS) .ack_ptp_irq = false, 17916c0c85daSRadu Pirea (NXP OSS) .counters_enable = tja1103_counters_enable, 1792bdb4c5b8SRadu Pirea (NXP OSS) .get_egressts = nxp_c45_get_hwtxts, 179308e6547cSRadu Pirea (NXP OSS) .get_extts = nxp_c45_get_extts, 17946c0c85daSRadu Pirea (NXP OSS) .ptp_init = tja1103_ptp_init, 17956c0c85daSRadu Pirea (NXP OSS) .ptp_enable = tja1103_ptp_enable, 1796425c8348SRadu Pirea (NXP OSS) .nmi_handler = tja1103_nmi_handler, 17976c0c85daSRadu Pirea (NXP OSS) }; 17986c0c85daSRadu Pirea (NXP OSS) 1799f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_counters_enable(struct phy_device *phydev) 1800f1fe5dffSRadu Pirea (NXP OSS) { 1801f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_SYMBOL_ERROR_CNT_XTD, 1802f1fe5dffSRadu Pirea (NXP OSS) EXTENDED_CNT_EN); 1803f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_STATUS, 1804f1fe5dffSRadu Pirea (NXP OSS) MONITOR_RESET); 1805f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_CONFIG, 1806f1fe5dffSRadu Pirea (NXP OSS) ALL_FRAMES_CNT_EN | LOST_FRAMES_CNT_EN); 1807f1fe5dffSRadu Pirea (NXP OSS) } 1808f1fe5dffSRadu Pirea (NXP OSS) 1809f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_init(struct phy_device *phydev) 1810f1fe5dffSRadu Pirea (NXP OSS) { 1811f1fe5dffSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_RX_TS_INSRT_CTRL, 1812f1fe5dffSRadu Pirea (NXP OSS) TJA1120_RX_TS_INSRT_EN | TJA1120_TS_INSRT_MODE); 1813f1fe5dffSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_VEND1_EXT_TS_MODE, 1814f1fe5dffSRadu Pirea (NXP OSS) TJA1120_TS_INSRT_MODE); 1815f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONFIG, 1816f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1817f1fe5dffSRadu Pirea (NXP OSS) } 1818f1fe5dffSRadu Pirea (NXP OSS) 1819f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_enable(struct phy_device *phydev, bool enable) 1820f1fe5dffSRadu Pirea (NXP OSS) { 1821f1fe5dffSRadu Pirea (NXP OSS) if (enable) 1822f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1823f1fe5dffSRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, 1824f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1825f1fe5dffSRadu Pirea (NXP OSS) else 1826f1fe5dffSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1827f1fe5dffSRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, 1828f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1829f1fe5dffSRadu Pirea (NXP OSS) } 1830f1fe5dffSRadu Pirea (NXP OSS) 1831425c8348SRadu Pirea (NXP OSS) static void tja1120_nmi_handler(struct phy_device *phydev, 1832425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status) 1833425c8348SRadu Pirea (NXP OSS) { 1834425c8348SRadu Pirea (NXP OSS) int ret; 1835425c8348SRadu Pirea (NXP OSS) 1836425c8348SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, 1837425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_STATUS); 1838425c8348SRadu Pirea (NXP OSS) if (ret & TJA1120_DEV_BOOT_DONE) { 1839425c8348SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 1840425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_ACK, 1841425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE); 1842425c8348SRadu Pirea (NXP OSS) *irq_status = IRQ_HANDLED; 1843425c8348SRadu Pirea (NXP OSS) } 1844425c8348SRadu Pirea (NXP OSS) } 1845425c8348SRadu Pirea (NXP OSS) 1846f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1120_regmap = { 1847f1fe5dffSRadu Pirea (NXP OSS) .vend1_ptp_clk_period = 0x1020, 1848f1fe5dffSRadu Pirea (NXP OSS) .vend1_event_msg_filt = 0x9010, 1849f1fe5dffSRadu Pirea (NXP OSS) .pps_enable = 1850f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 4, 1), 1851f1fe5dffSRadu Pirea (NXP OSS) .pps_polarity = 1852f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 5, 1), 1853f1fe5dffSRadu Pirea (NXP OSS) .ltc_lock_ctrl = 1854f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 2, 1), 1855f1fe5dffSRadu Pirea (NXP OSS) .ltc_read = 1856f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 1, 1), 1857f1fe5dffSRadu Pirea (NXP OSS) .ltc_write = 1858f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 2, 1), 1859f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_0 = 0x1040, 1860f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_1 = 0x1041, 1861f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_0 = 0x1042, 1862f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_1 = 0x1043, 1863f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_0 = 0x1048, 1864f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_1 = 0x1049, 1865f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_0 = 0x104A, 1866f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_1 = 0x104B, 1867f1fe5dffSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_0 = 0x1030, 1868f1fe5dffSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_1 = 0x1031, 1869f1fe5dffSRadu Pirea (NXP OSS) .irq_egr_ts_en = 1870f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x900A, MDIO_MMD_VEND1, 1, 1), 1871f1fe5dffSRadu Pirea (NXP OSS) .irq_egr_ts_status = 1872f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x900C, MDIO_MMD_VEND1, 1, 1), 1873f1fe5dffSRadu Pirea (NXP OSS) .domain_number = 1874f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 8, 8), 1875f1fe5dffSRadu Pirea (NXP OSS) .msg_type = 1876f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 4, 4), 1877f1fe5dffSRadu Pirea (NXP OSS) .sequence_id = 1878f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9062, MDIO_MMD_VEND1, 0, 16), 1879f1fe5dffSRadu Pirea (NXP OSS) .sec_1_0 = 1880f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 0, 2), 1881f1fe5dffSRadu Pirea (NXP OSS) .sec_4_2 = 1882f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 2, 3), 1883f1fe5dffSRadu Pirea (NXP OSS) .nsec_15_0 = 1884f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9063, MDIO_MMD_VEND1, 0, 16), 1885f1fe5dffSRadu Pirea (NXP OSS) .nsec_29_16 = 1886f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9064, MDIO_MMD_VEND1, 0, 14), 1887f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_0 = 0x1071, 1888f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_1 = 0x1072, 1889f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_2 = 0x1073, 1890f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_3 = 0x1074, 1891f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_ctrl = 0x1075, 1892f1fe5dffSRadu Pirea (NXP OSS) .cable_test = 0x8360, 1893f1fe5dffSRadu Pirea (NXP OSS) .cable_test_valid = 1894f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 15, 1), 1895f1fe5dffSRadu Pirea (NXP OSS) .cable_test_result = 1896f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 0, 3), 1897f1fe5dffSRadu Pirea (NXP OSS) }; 1898f1fe5dffSRadu Pirea (NXP OSS) 1899f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1120_phy_data = { 1900f1fe5dffSRadu Pirea (NXP OSS) .regmap = &tja1120_regmap, 1901f1fe5dffSRadu Pirea (NXP OSS) .stats = tja1120_hw_stats, 1902f1fe5dffSRadu Pirea (NXP OSS) .n_stats = ARRAY_SIZE(tja1120_hw_stats), 1903f1fe5dffSRadu Pirea (NXP OSS) .ptp_clk_period = PTP_CLK_PERIOD_1000BT1, 1904b0b2247dSRadu Pirea (NXP OSS) .ext_ts_both_edges = true, 1905bdb4c5b8SRadu Pirea (NXP OSS) .ack_ptp_irq = true, 1906f1fe5dffSRadu Pirea (NXP OSS) .counters_enable = tja1120_counters_enable, 1907bdb4c5b8SRadu Pirea (NXP OSS) .get_egressts = tja1120_get_hwtxts, 190808e6547cSRadu Pirea (NXP OSS) .get_extts = tja1120_get_extts, 1909f1fe5dffSRadu Pirea (NXP OSS) .ptp_init = tja1120_ptp_init, 1910f1fe5dffSRadu Pirea (NXP OSS) .ptp_enable = tja1120_ptp_enable, 1911425c8348SRadu Pirea (NXP OSS) .nmi_handler = tja1120_nmi_handler, 1912f1fe5dffSRadu Pirea (NXP OSS) }; 1913f1fe5dffSRadu Pirea (NXP OSS) 1914b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = { 1915b050f2f1SRadu Pirea (NXP OSS) { 1916b050f2f1SRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), 1917b050f2f1SRadu Pirea (NXP OSS) .name = "NXP C45 TJA1103", 1918369da333SRadu Pirea (NXP OSS) .get_features = nxp_c45_get_features, 19196c0c85daSRadu Pirea (NXP OSS) .driver_data = &tja1103_phy_data, 1920b050f2f1SRadu Pirea (NXP OSS) .probe = nxp_c45_probe, 1921b050f2f1SRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset, 1922ac0687e8SRadu Pirea (NXP OSS) .config_aneg = genphy_c45_config_aneg, 1923b050f2f1SRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init, 1924425c8348SRadu Pirea (NXP OSS) .config_intr = tja1103_config_intr, 1925b2f0ca00SRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt, 1926ac0687e8SRadu Pirea (NXP OSS) .read_status = genphy_c45_read_status, 1927b050f2f1SRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend, 1928b050f2f1SRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume, 1929b050f2f1SRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count, 1930b050f2f1SRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings, 1931b050f2f1SRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats, 1932b050f2f1SRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start, 1933b050f2f1SRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status, 1934b050f2f1SRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback, 1935b050f2f1SRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi, 1936b050f2f1SRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max, 1937a4506722SRadu Pirea (OSS) .remove = nxp_c45_remove, 1938b050f2f1SRadu Pirea (NXP OSS) }, 1939f1fe5dffSRadu Pirea (NXP OSS) { 1940f1fe5dffSRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120), 1941f1fe5dffSRadu Pirea (NXP OSS) .name = "NXP C45 TJA1120", 1942f1fe5dffSRadu Pirea (NXP OSS) .get_features = nxp_c45_get_features, 1943f1fe5dffSRadu Pirea (NXP OSS) .driver_data = &tja1120_phy_data, 1944f1fe5dffSRadu Pirea (NXP OSS) .probe = nxp_c45_probe, 1945f1fe5dffSRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset, 1946f1fe5dffSRadu Pirea (NXP OSS) .config_aneg = genphy_c45_config_aneg, 1947f1fe5dffSRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init, 1948425c8348SRadu Pirea (NXP OSS) .config_intr = tja1120_config_intr, 1949f1fe5dffSRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt, 1950f1fe5dffSRadu Pirea (NXP OSS) .read_status = genphy_c45_read_status, 1951*68c6af72SRadu Pirea (NXP OSS) .link_change_notify = tja1120_link_change_notify, 1952f1fe5dffSRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend, 1953f1fe5dffSRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume, 1954f1fe5dffSRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count, 1955f1fe5dffSRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings, 1956f1fe5dffSRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats, 1957f1fe5dffSRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start, 1958f1fe5dffSRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status, 1959f1fe5dffSRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback, 1960f1fe5dffSRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi, 1961f1fe5dffSRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max, 1962f1fe5dffSRadu Pirea (NXP OSS) .remove = nxp_c45_remove, 1963f1fe5dffSRadu Pirea (NXP OSS) }, 1964b050f2f1SRadu Pirea (NXP OSS) }; 1965b050f2f1SRadu Pirea (NXP OSS) 1966b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver); 1967b050f2f1SRadu Pirea (NXP OSS) 1968b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = { 1969b050f2f1SRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) }, 1970f1fe5dffSRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120) }, 1971b050f2f1SRadu Pirea (NXP OSS) { /*sentinel*/ }, 1972b050f2f1SRadu Pirea (NXP OSS) }; 1973b050f2f1SRadu Pirea (NXP OSS) 1974b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl); 1975b050f2f1SRadu Pirea (NXP OSS) 1976b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>"); 1977b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver"); 1978b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2"); 1979