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) 37bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_EGRESS_TS_DATA_S 0x9060 38bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_EGRESS_TS_END 0x9067 39bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_TS_VALID BIT(0) 40bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_MORE_TS BIT(15) 41bdb4c5b8SRadu Pirea (NXP OSS) 42b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_ACK 0x80A0 43b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_EN 0x80A1 44b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_STATUS 0x80A2 45b2f0ca00SRadu Pirea (NXP OSS) #define PHY_IRQ_LINK_EVENT BIT(1) 46b2f0ca00SRadu Pirea (NXP OSS) 47425c8348SRadu Pirea (NXP OSS) #define VEND1_ALWAYS_ACCESSIBLE 0x801F 48425c8348SRadu Pirea (NXP OSS) #define FUSA_PASS BIT(4) 49425c8348SRadu Pirea (NXP OSS) 50b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONTROL 0x8100 51b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_EN BIT(14) 52b050f2f1SRadu Pirea (NXP OSS) #define PHY_START_OP BIT(0) 53b050f2f1SRadu Pirea (NXP OSS) 54b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONFIG 0x8108 55b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_AUTO BIT(0) 56b050f2f1SRadu Pirea (NXP OSS) 57b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SIGNAL_QUALITY 0x8320 58b050f2f1SRadu Pirea (NXP OSS) #define SQI_VALID BIT(14) 59b050f2f1SRadu Pirea (NXP OSS) #define SQI_MASK GENMASK(2, 0) 60b050f2f1SRadu Pirea (NXP OSS) #define MAX_SQI SQI_MASK 61b050f2f1SRadu Pirea (NXP OSS) 62b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_ENABLE BIT(15) 63b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_START BIT(14) 64b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OK 0x00 65b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_SHORTED 0x01 66b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OPEN 0x02 67b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_UNKNOWN 0x07 68b050f2f1SRadu Pirea (NXP OSS) 69b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_CONTROL 0x8040 70b050f2f1SRadu Pirea (NXP OSS) #define PORT_CONTROL_EN BIT(14) 71b050f2f1SRadu Pirea (NXP OSS) 72514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_ABILITIES 0x8046 73514def5dSRadu Pirea (NXP OSS) #define PTP_ABILITY BIT(3) 74514def5dSRadu Pirea (NXP OSS) 75bdb4c5b8SRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_IRQ_EN 0x807A 76bdb4c5b8SRadu Pirea (NXP OSS) #define PTP_IRQS BIT(3) 77bdb4c5b8SRadu Pirea (NXP OSS) 78bdb4c5b8SRadu Pirea (NXP OSS) #define VEND1_PTP_IRQ_ACK 0x9008 79bdb4c5b8SRadu Pirea (NXP OSS) #define EGR_TS_IRQ BIT(1) 80bdb4c5b8SRadu Pirea (NXP OSS) 81b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_INFRA_CONTROL 0xAC00 82b050f2f1SRadu Pirea (NXP OSS) #define PORT_INFRA_CONTROL_EN BIT(14) 83b050f2f1SRadu Pirea (NXP OSS) 84b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RXID 0xAFCC 85b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TXID 0xAFCD 86b050f2f1SRadu Pirea (NXP OSS) #define ID_ENABLE BIT(15) 87b050f2f1SRadu Pirea (NXP OSS) 88b050f2f1SRadu Pirea (NXP OSS) #define VEND1_ABILITIES 0xAFC4 89b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ID_ABILITY BIT(15) 90b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ABILITY BIT(14) 91b050f2f1SRadu Pirea (NXP OSS) #define RMII_ABILITY BIT(10) 92b050f2f1SRadu Pirea (NXP OSS) #define REVMII_ABILITY BIT(9) 93b050f2f1SRadu Pirea (NXP OSS) #define MII_ABILITY BIT(8) 94b050f2f1SRadu Pirea (NXP OSS) #define SGMII_ABILITY BIT(0) 95b050f2f1SRadu Pirea (NXP OSS) 96b050f2f1SRadu Pirea (NXP OSS) #define VEND1_MII_BASIC_CONFIG 0xAFC6 978ba57205SRadu Pirea (OSS) #define MII_BASIC_CONFIG_REV BIT(4) 98b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_SGMII 0x9 99b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RGMII 0x7 100b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RMII 0x5 101b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_MII 0x4 102b050f2f1SRadu Pirea (NXP OSS) 103f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_CNT_XTD 0x8351 104f1fe5dffSRadu Pirea (NXP OSS) #define EXTENDED_CNT_EN BIT(15) 105f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_STATUS 0xAC80 106f1fe5dffSRadu Pirea (NXP OSS) #define MONITOR_RESET BIT(15) 107f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_CONFIG 0xAC86 108f1fe5dffSRadu Pirea (NXP OSS) #define LOST_FRAMES_CNT_EN BIT(9) 109f1fe5dffSRadu Pirea (NXP OSS) #define ALL_FRAMES_CNT_EN BIT(8) 110f1fe5dffSRadu Pirea (NXP OSS) 111b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_COUNTER 0x8350 112b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_DROP_COUNTER 0x8352 113b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_LOSSES_AND_FAILURES 0x8353 114b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_PREAMBLE_COUNT 0xAFCE 115b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_PREAMBLE_COUNT 0xAFCF 116b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_IPG_LENGTH 0xAFD0 117b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_IPG_LENGTH 0xAFD1 118b050f2f1SRadu Pirea (NXP OSS) #define COUNTER_EN BIT(15) 119b050f2f1SRadu Pirea (NXP OSS) 1207a71c8aaSRadu Pirea (NXP OSS) #define VEND1_PTP_CONFIG 0x1102 1217a71c8aaSRadu Pirea (NXP OSS) #define EXT_TRG_EDGE BIT(1) 1227a71c8aaSRadu Pirea (NXP OSS) 123b0b2247dSRadu Pirea (NXP OSS) #define TJA1120_SYNC_TRIG_FILTER 0x1010 124b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_RISE_TS BIT(3) 125b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_FALLING_TS BIT(2) 126b0b2247dSRadu Pirea (NXP OSS) 127514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_LD BIT(15) 128514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_DIR BIT(14) 129514def5dSRadu Pirea (NXP OSS) 130514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_TS_INSRT_CTRL 0x114D 1316c0c85daSRadu Pirea (NXP OSS) #define TJA1103_RX_TS_INSRT_MODE2 0x02 132514def5dSRadu Pirea (NXP OSS) 133f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_CTRL 0x9012 134f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_EN BIT(15) 135f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_TS_INSRT_MODE BIT(4) 136f1fe5dffSRadu Pirea (NXP OSS) 137514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_0 0x114E 138514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_CTRL 0x1154 139514def5dSRadu Pirea (NXP OSS) 140514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_TS_VALID BIT(15) 141514def5dSRadu Pirea (NXP OSS) 142514def5dSRadu Pirea (NXP OSS) #define RING_DONE BIT(0) 143514def5dSRadu Pirea (NXP OSS) 144514def5dSRadu Pirea (NXP OSS) #define TS_SEC_MASK GENMASK(1, 0) 145514def5dSRadu Pirea (NXP OSS) 146514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_ENABLES 0x8048 147514def5dSRadu Pirea (NXP OSS) #define PTP_ENABLE BIT(3) 148*c552c110SRadu Pirea (NXP OSS) #define PHY_TEST_ENABLE BIT(0) 149514def5dSRadu Pirea (NXP OSS) 150514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_PTP_CONTROL 0x9000 151514def5dSRadu Pirea (NXP OSS) #define PORT_PTP_CONTROL_BYPASS BIT(11) 152514def5dSRadu Pirea (NXP OSS) 153514def5dSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_100BT1 15ULL 154f1fe5dffSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_1000BT1 8ULL 155514def5dSRadu Pirea (NXP OSS) 156514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_ALL 0x0F 157514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_NONE 0x00 158514def5dSRadu Pirea (NXP OSS) 1597a71c8aaSRadu Pirea (NXP OSS) #define VEND1_GPIO_FUNC_CONFIG_BASE 0x2C40 1607a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_EN BIT(15) 1617a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_PTP BIT(6) 1627a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PTP_TRIGGER 0x01 1637a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PPS_OUT 0x12 1647a71c8aaSRadu Pirea (NXP OSS) #define GPIO_DISABLE 0 1657a71c8aaSRadu Pirea (NXP OSS) #define GPIO_PPS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \ 1667a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PPS_OUT) 1677a71c8aaSRadu Pirea (NXP OSS) #define GPIO_EXTTS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \ 1687a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PTP_TRIGGER) 1697a71c8aaSRadu Pirea (NXP OSS) 170b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS 8000U 171b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE div_u64(RGMII_PERIOD_PS, 360) 172b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS 1644U 173b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS 2260U 174b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS 2000U 175b050f2f1SRadu Pirea (NXP OSS) 1766c0c85daSRadu Pirea (NXP OSS) #define PPM_TO_SUBNS_INC(ppb, ptp_clk_period) div_u64(GENMASK_ULL(31, 0) * \ 1776c0c85daSRadu Pirea (NXP OSS) (ppb) * (ptp_clk_period), NSEC_PER_SEC) 178514def5dSRadu Pirea (NXP OSS) 179514def5dSRadu Pirea (NXP OSS) #define NXP_C45_SKB_CB(skb) ((struct nxp_c45_skb_cb *)(skb)->cb) 180514def5dSRadu Pirea (NXP OSS) 181bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_phy; 182bdb4c5b8SRadu Pirea (NXP OSS) 183514def5dSRadu Pirea (NXP OSS) struct nxp_c45_skb_cb { 184514def5dSRadu Pirea (NXP OSS) struct ptp_header *header; 185514def5dSRadu Pirea (NXP OSS) unsigned int type; 186514def5dSRadu Pirea (NXP OSS) }; 187514def5dSRadu Pirea (NXP OSS) 1886c0c85daSRadu Pirea (NXP OSS) #define NXP_C45_REG_FIELD(_reg, _devad, _offset, _size) \ 1896c0c85daSRadu Pirea (NXP OSS) ((struct nxp_c45_reg_field) { \ 1906c0c85daSRadu Pirea (NXP OSS) .reg = _reg, \ 1916c0c85daSRadu Pirea (NXP OSS) .devad = _devad, \ 1926c0c85daSRadu Pirea (NXP OSS) .offset = _offset, \ 1936c0c85daSRadu Pirea (NXP OSS) .size = _size, \ 1946c0c85daSRadu Pirea (NXP OSS) }) 1956c0c85daSRadu Pirea (NXP OSS) 1966c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field { 1976c0c85daSRadu Pirea (NXP OSS) u16 reg; 1986c0c85daSRadu Pirea (NXP OSS) u8 devad; 1996c0c85daSRadu Pirea (NXP OSS) u8 offset; 2006c0c85daSRadu Pirea (NXP OSS) u8 size; 2016c0c85daSRadu Pirea (NXP OSS) }; 2026c0c85daSRadu Pirea (NXP OSS) 203514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts { 204514def5dSRadu Pirea (NXP OSS) u32 nsec; 205514def5dSRadu Pirea (NXP OSS) u32 sec; 206514def5dSRadu Pirea (NXP OSS) u8 domain_number; 207514def5dSRadu Pirea (NXP OSS) u16 sequence_id; 208514def5dSRadu Pirea (NXP OSS) u8 msg_type; 209514def5dSRadu Pirea (NXP OSS) }; 210514def5dSRadu Pirea (NXP OSS) 2116c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap { 2126c0c85daSRadu Pirea (NXP OSS) /* PTP config regs. */ 2136c0c85daSRadu Pirea (NXP OSS) u16 vend1_ptp_clk_period; 2146c0c85daSRadu Pirea (NXP OSS) u16 vend1_event_msg_filt; 2156c0c85daSRadu Pirea (NXP OSS) 2166c0c85daSRadu Pirea (NXP OSS) /* LTC bits and regs. */ 2176c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_read; 2186c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_write; 2196c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_lock_ctrl; 2206c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_nsec_0; 2216c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_nsec_1; 2226c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_sec_0; 2236c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_sec_1; 2246c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_nsec_0; 2256c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_nsec_1; 2266c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_sec_0; 2276c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_sec_1; 2286c0c85daSRadu Pirea (NXP OSS) u16 vend1_rate_adj_subns_0; 2296c0c85daSRadu Pirea (NXP OSS) u16 vend1_rate_adj_subns_1; 2306c0c85daSRadu Pirea (NXP OSS) 2316c0c85daSRadu Pirea (NXP OSS) /* External trigger reg fields. */ 2326c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field irq_egr_ts_en; 2336c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field irq_egr_ts_status; 2346c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field domain_number; 2356c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field msg_type; 2366c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sequence_id; 2376c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sec_1_0; 2386c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sec_4_2; 2396c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field nsec_15_0; 2406c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field nsec_29_16; 2416c0c85daSRadu Pirea (NXP OSS) 2426c0c85daSRadu Pirea (NXP OSS) /* PPS and EXT Trigger bits and regs. */ 2436c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field pps_enable; 2446c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field pps_polarity; 2456c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_0; 2466c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_1; 2476c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_2; 2486c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_3; 2496c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_ctrl; 2506c0c85daSRadu Pirea (NXP OSS) 2516c0c85daSRadu Pirea (NXP OSS) /* Cable test reg fields. */ 2526c0c85daSRadu Pirea (NXP OSS) u16 cable_test; 2536c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field cable_test_valid; 2546c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field cable_test_result; 2556c0c85daSRadu Pirea (NXP OSS) }; 2566c0c85daSRadu Pirea (NXP OSS) 2576c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_stats { 2586c0c85daSRadu Pirea (NXP OSS) const char *name; 2596c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field counter; 2606c0c85daSRadu Pirea (NXP OSS) }; 2616c0c85daSRadu Pirea (NXP OSS) 2626c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data { 2636c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap; 2646c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_stats *stats; 2656c0c85daSRadu Pirea (NXP OSS) int n_stats; 2666c0c85daSRadu Pirea (NXP OSS) u8 ptp_clk_period; 267b0b2247dSRadu Pirea (NXP OSS) bool ext_ts_both_edges; 268bdb4c5b8SRadu Pirea (NXP OSS) bool ack_ptp_irq; 2696c0c85daSRadu Pirea (NXP OSS) void (*counters_enable)(struct phy_device *phydev); 270bdb4c5b8SRadu Pirea (NXP OSS) bool (*get_egressts)(struct nxp_c45_phy *priv, 271bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts); 2726c0c85daSRadu Pirea (NXP OSS) void (*ptp_init)(struct phy_device *phydev); 2736c0c85daSRadu Pirea (NXP OSS) void (*ptp_enable)(struct phy_device *phydev, bool enable); 274425c8348SRadu Pirea (NXP OSS) void (*nmi_handler)(struct phy_device *phydev, 275425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status); 2766c0c85daSRadu Pirea (NXP OSS) }; 2776c0c85daSRadu Pirea (NXP OSS) 278b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy { 2796c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data; 280514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev; 281514def5dSRadu Pirea (NXP OSS) struct mii_timestamper mii_ts; 282514def5dSRadu Pirea (NXP OSS) struct ptp_clock *ptp_clock; 283514def5dSRadu Pirea (NXP OSS) struct ptp_clock_info caps; 284514def5dSRadu Pirea (NXP OSS) struct sk_buff_head tx_queue; 285514def5dSRadu Pirea (NXP OSS) struct sk_buff_head rx_queue; 286514def5dSRadu Pirea (NXP OSS) /* used to access the PTP registers atomic */ 287514def5dSRadu Pirea (NXP OSS) struct mutex ptp_lock; 288514def5dSRadu Pirea (NXP OSS) int hwts_tx; 289514def5dSRadu Pirea (NXP OSS) int hwts_rx; 290b050f2f1SRadu Pirea (NXP OSS) u32 tx_delay; 291b050f2f1SRadu Pirea (NXP OSS) u32 rx_delay; 2927a71c8aaSRadu Pirea (NXP OSS) struct timespec64 extts_ts; 2937a71c8aaSRadu Pirea (NXP OSS) int extts_index; 2947a71c8aaSRadu Pirea (NXP OSS) bool extts; 295b050f2f1SRadu Pirea (NXP OSS) }; 296b050f2f1SRadu Pirea (NXP OSS) 2976c0c85daSRadu Pirea (NXP OSS) static const 2986c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data *nxp_c45_get_data(struct phy_device *phydev) 2996c0c85daSRadu Pirea (NXP OSS) { 3006c0c85daSRadu Pirea (NXP OSS) return phydev->drv->driver_data; 3016c0c85daSRadu Pirea (NXP OSS) } 3026c0c85daSRadu Pirea (NXP OSS) 3036c0c85daSRadu Pirea (NXP OSS) static const 3046c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap *nxp_c45_get_regmap(struct phy_device *phydev) 3056c0c85daSRadu Pirea (NXP OSS) { 3066c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 3076c0c85daSRadu Pirea (NXP OSS) 3086c0c85daSRadu Pirea (NXP OSS) return phy_data->regmap; 3096c0c85daSRadu Pirea (NXP OSS) } 3106c0c85daSRadu Pirea (NXP OSS) 3116c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_read_reg_field(struct phy_device *phydev, 3126c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 3136c0c85daSRadu Pirea (NXP OSS) { 314b050f2f1SRadu Pirea (NXP OSS) u16 mask; 3156c0c85daSRadu Pirea (NXP OSS) int ret; 3166c0c85daSRadu Pirea (NXP OSS) 3176c0c85daSRadu Pirea (NXP OSS) if (reg_field->size == 0) { 3186c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to read a reg field of size 0.\n"); 3196c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3206c0c85daSRadu Pirea (NXP OSS) } 3216c0c85daSRadu Pirea (NXP OSS) 3226c0c85daSRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, reg_field->devad, reg_field->reg); 3236c0c85daSRadu Pirea (NXP OSS) if (ret < 0) 3246c0c85daSRadu Pirea (NXP OSS) return ret; 3256c0c85daSRadu Pirea (NXP OSS) 3266c0c85daSRadu Pirea (NXP OSS) mask = reg_field->size == 1 ? BIT(reg_field->offset) : 3276c0c85daSRadu Pirea (NXP OSS) GENMASK(reg_field->offset + reg_field->size - 1, 3286c0c85daSRadu Pirea (NXP OSS) reg_field->offset); 3296c0c85daSRadu Pirea (NXP OSS) ret &= mask; 3306c0c85daSRadu Pirea (NXP OSS) ret >>= reg_field->offset; 3316c0c85daSRadu Pirea (NXP OSS) 3326c0c85daSRadu Pirea (NXP OSS) return ret; 3336c0c85daSRadu Pirea (NXP OSS) } 3346c0c85daSRadu Pirea (NXP OSS) 3356c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_write_reg_field(struct phy_device *phydev, 3366c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field, 3376c0c85daSRadu Pirea (NXP OSS) u16 val) 3386c0c85daSRadu Pirea (NXP OSS) { 3396c0c85daSRadu Pirea (NXP OSS) u16 mask; 3406c0c85daSRadu Pirea (NXP OSS) u16 set; 3416c0c85daSRadu Pirea (NXP OSS) 3426c0c85daSRadu Pirea (NXP OSS) if (reg_field->size == 0) { 3436c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to write a reg field of size 0.\n"); 3446c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3456c0c85daSRadu Pirea (NXP OSS) } 3466c0c85daSRadu Pirea (NXP OSS) 3476c0c85daSRadu Pirea (NXP OSS) mask = reg_field->size == 1 ? BIT(reg_field->offset) : 3486c0c85daSRadu Pirea (NXP OSS) GENMASK(reg_field->offset + reg_field->size - 1, 3496c0c85daSRadu Pirea (NXP OSS) reg_field->offset); 3506c0c85daSRadu Pirea (NXP OSS) set = val << reg_field->offset; 3516c0c85daSRadu Pirea (NXP OSS) 3526c0c85daSRadu Pirea (NXP OSS) return phy_modify_mmd_changed(phydev, reg_field->devad, 3536c0c85daSRadu Pirea (NXP OSS) reg_field->reg, mask, set); 3546c0c85daSRadu Pirea (NXP OSS) } 3556c0c85daSRadu Pirea (NXP OSS) 3566c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_set_reg_field(struct phy_device *phydev, 3576c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 3586c0c85daSRadu Pirea (NXP OSS) { 3596c0c85daSRadu Pirea (NXP OSS) if (reg_field->size != 1) { 3606c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to set a reg field of size different than 1.\n"); 3616c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3626c0c85daSRadu Pirea (NXP OSS) } 3636c0c85daSRadu Pirea (NXP OSS) 3646c0c85daSRadu Pirea (NXP OSS) return nxp_c45_write_reg_field(phydev, reg_field, 1); 3656c0c85daSRadu Pirea (NXP OSS) } 3666c0c85daSRadu Pirea (NXP OSS) 3676c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_clear_reg_field(struct phy_device *phydev, 3686c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 3696c0c85daSRadu Pirea (NXP OSS) { 3706c0c85daSRadu Pirea (NXP OSS) if (reg_field->size != 1) { 3716c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to set a reg field of size different than 1.\n"); 3726c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3736c0c85daSRadu Pirea (NXP OSS) } 3746c0c85daSRadu Pirea (NXP OSS) 3756c0c85daSRadu Pirea (NXP OSS) return nxp_c45_write_reg_field(phydev, reg_field, 0); 3766c0c85daSRadu Pirea (NXP OSS) } 377b050f2f1SRadu Pirea (NXP OSS) 378514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_poll_txts(struct phy_device *phydev) 379514def5dSRadu Pirea (NXP OSS) { 380514def5dSRadu Pirea (NXP OSS) return phydev->irq <= 0; 381514def5dSRadu Pirea (NXP OSS) } 382514def5dSRadu Pirea (NXP OSS) 383514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, 384514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts, 385514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts) 386514def5dSRadu Pirea (NXP OSS) { 387514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 3886c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 389514def5dSRadu Pirea (NXP OSS) 3906c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->ltc_read); 391514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3926c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_nsec_0); 393514def5dSRadu Pirea (NXP OSS) ts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3946c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_nsec_1) << 16; 395514def5dSRadu Pirea (NXP OSS) ts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3966c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_sec_0); 397514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3986c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_sec_1) << 16; 399514def5dSRadu Pirea (NXP OSS) 400514def5dSRadu Pirea (NXP OSS) return 0; 401514def5dSRadu Pirea (NXP OSS) } 402514def5dSRadu Pirea (NXP OSS) 403514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, 404514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts, 405514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts) 406514def5dSRadu Pirea (NXP OSS) { 407514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 408514def5dSRadu Pirea (NXP OSS) 409514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 410514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, ts, sts); 411514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 412514def5dSRadu Pirea (NXP OSS) 413514def5dSRadu Pirea (NXP OSS) return 0; 414514def5dSRadu Pirea (NXP OSS) } 415514def5dSRadu Pirea (NXP OSS) 416514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, 417514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts) 418514def5dSRadu Pirea (NXP OSS) { 419514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 4206c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 421514def5dSRadu Pirea (NXP OSS) 4226c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_0, 423514def5dSRadu Pirea (NXP OSS) ts->tv_nsec); 4246c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_1, 425514def5dSRadu Pirea (NXP OSS) ts->tv_nsec >> 16); 4266c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_0, 427514def5dSRadu Pirea (NXP OSS) ts->tv_sec); 4286c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_1, 429514def5dSRadu Pirea (NXP OSS) ts->tv_sec >> 16); 4306c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->ltc_write); 431514def5dSRadu Pirea (NXP OSS) 432514def5dSRadu Pirea (NXP OSS) return 0; 433514def5dSRadu Pirea (NXP OSS) } 434514def5dSRadu Pirea (NXP OSS) 435514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, 436514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts) 437514def5dSRadu Pirea (NXP OSS) { 438514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 439514def5dSRadu Pirea (NXP OSS) 440514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 441514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, ts); 442514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 443514def5dSRadu Pirea (NXP OSS) 444514def5dSRadu Pirea (NXP OSS) return 0; 445514def5dSRadu Pirea (NXP OSS) } 446514def5dSRadu Pirea (NXP OSS) 447514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 448514def5dSRadu Pirea (NXP OSS) { 449514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 4506c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); 4516c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = data->regmap; 452514def5dSRadu Pirea (NXP OSS) s32 ppb = scaled_ppm_to_ppb(scaled_ppm); 453514def5dSRadu Pirea (NXP OSS) u64 subns_inc_val; 454514def5dSRadu Pirea (NXP OSS) bool inc; 455514def5dSRadu Pirea (NXP OSS) 456514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 457514def5dSRadu Pirea (NXP OSS) inc = ppb >= 0; 458514def5dSRadu Pirea (NXP OSS) ppb = abs(ppb); 459514def5dSRadu Pirea (NXP OSS) 4606c0c85daSRadu Pirea (NXP OSS) subns_inc_val = PPM_TO_SUBNS_INC(ppb, data->ptp_clk_period); 461514def5dSRadu Pirea (NXP OSS) 4626c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 4636c0c85daSRadu Pirea (NXP OSS) regmap->vend1_rate_adj_subns_0, 464514def5dSRadu Pirea (NXP OSS) subns_inc_val); 465514def5dSRadu Pirea (NXP OSS) subns_inc_val >>= 16; 466514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_LD; 467514def5dSRadu Pirea (NXP OSS) if (inc) 468514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_DIR; 469514def5dSRadu Pirea (NXP OSS) 4706c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 4716c0c85daSRadu Pirea (NXP OSS) regmap->vend1_rate_adj_subns_1, 472514def5dSRadu Pirea (NXP OSS) subns_inc_val); 473514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 474514def5dSRadu Pirea (NXP OSS) 475514def5dSRadu Pirea (NXP OSS) return 0; 476514def5dSRadu Pirea (NXP OSS) } 477514def5dSRadu Pirea (NXP OSS) 478514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) 479514def5dSRadu Pirea (NXP OSS) { 480514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 481514def5dSRadu Pirea (NXP OSS) struct timespec64 now, then; 482514def5dSRadu Pirea (NXP OSS) 483514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 484514def5dSRadu Pirea (NXP OSS) then = ns_to_timespec64(delta); 485514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, &now, NULL); 486514def5dSRadu Pirea (NXP OSS) now = timespec64_add(now, then); 487514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, &now); 488514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 489514def5dSRadu Pirea (NXP OSS) 490514def5dSRadu Pirea (NXP OSS) return 0; 491514def5dSRadu Pirea (NXP OSS) } 492514def5dSRadu Pirea (NXP OSS) 493514def5dSRadu Pirea (NXP OSS) static void nxp_c45_reconstruct_ts(struct timespec64 *ts, 494514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 495514def5dSRadu Pirea (NXP OSS) { 496514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = hwts->nsec; 497514def5dSRadu Pirea (NXP OSS) if ((ts->tv_sec & TS_SEC_MASK) < (hwts->sec & TS_SEC_MASK)) 498661fef56SVladimir Oltean ts->tv_sec -= TS_SEC_MASK + 1; 499514def5dSRadu Pirea (NXP OSS) ts->tv_sec &= ~TS_SEC_MASK; 500514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= hwts->sec & TS_SEC_MASK; 501514def5dSRadu Pirea (NXP OSS) } 502514def5dSRadu Pirea (NXP OSS) 503514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_match_ts(struct ptp_header *header, 504514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts, 505514def5dSRadu Pirea (NXP OSS) unsigned int type) 506514def5dSRadu Pirea (NXP OSS) { 507514def5dSRadu Pirea (NXP OSS) return ntohs(header->sequence_id) == hwts->sequence_id && 508514def5dSRadu Pirea (NXP OSS) ptp_get_msgtype(header, type) == hwts->msg_type && 509514def5dSRadu Pirea (NXP OSS) header->domain_number == hwts->domain_number; 510514def5dSRadu Pirea (NXP OSS) } 511514def5dSRadu Pirea (NXP OSS) 5127a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_get_extts(struct nxp_c45_phy *priv, 5137a71c8aaSRadu Pirea (NXP OSS) struct timespec64 *extts) 5147a71c8aaSRadu Pirea (NXP OSS) { 5156c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 5166c0c85daSRadu Pirea (NXP OSS) 5177a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 5186c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_0); 5197a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 5206c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_1) << 16; 5217a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 5226c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_2); 5237a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 5246c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_3) << 16; 5256c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 5266c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_ctrl, RING_DONE); 5277a71c8aaSRadu Pirea (NXP OSS) } 5287a71c8aaSRadu Pirea (NXP OSS) 529bdb4c5b8SRadu Pirea (NXP OSS) static void nxp_c45_read_egress_ts(struct nxp_c45_phy *priv, 530514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 531514def5dSRadu Pirea (NXP OSS) { 5326c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 5336c0c85daSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 534514def5dSRadu Pirea (NXP OSS) 5356c0c85daSRadu Pirea (NXP OSS) hwts->domain_number = 5366c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->domain_number); 5376c0c85daSRadu Pirea (NXP OSS) hwts->msg_type = 5386c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->msg_type); 5396c0c85daSRadu Pirea (NXP OSS) hwts->sequence_id = 5406c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->sequence_id); 5416c0c85daSRadu Pirea (NXP OSS) hwts->nsec = 5426c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->nsec_15_0); 5436c0c85daSRadu Pirea (NXP OSS) hwts->nsec |= 5446c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->nsec_29_16) << 16; 5456c0c85daSRadu Pirea (NXP OSS) hwts->sec = nxp_c45_read_reg_field(phydev, ®map->sec_1_0); 5466c0c85daSRadu Pirea (NXP OSS) hwts->sec |= nxp_c45_read_reg_field(phydev, ®map->sec_4_2) << 2; 547bdb4c5b8SRadu Pirea (NXP OSS) } 548514def5dSRadu Pirea (NXP OSS) 549bdb4c5b8SRadu Pirea (NXP OSS) static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, 550bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 551bdb4c5b8SRadu Pirea (NXP OSS) { 552bdb4c5b8SRadu Pirea (NXP OSS) bool valid; 553bdb4c5b8SRadu Pirea (NXP OSS) u16 reg; 554bdb4c5b8SRadu Pirea (NXP OSS) 555bdb4c5b8SRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 556bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL, 557bdb4c5b8SRadu Pirea (NXP OSS) RING_DONE); 558bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0); 559bdb4c5b8SRadu Pirea (NXP OSS) valid = !!(reg & RING_DATA_0_TS_VALID); 560bdb4c5b8SRadu Pirea (NXP OSS) if (!valid) 561bdb4c5b8SRadu Pirea (NXP OSS) goto nxp_c45_get_hwtxts_out; 562bdb4c5b8SRadu Pirea (NXP OSS) 563bdb4c5b8SRadu Pirea (NXP OSS) nxp_c45_read_egress_ts(priv, hwts); 564514def5dSRadu Pirea (NXP OSS) nxp_c45_get_hwtxts_out: 565514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 566514def5dSRadu Pirea (NXP OSS) return valid; 567514def5dSRadu Pirea (NXP OSS) } 568514def5dSRadu Pirea (NXP OSS) 569bdb4c5b8SRadu Pirea (NXP OSS) static bool tja1120_egress_ts_is_valid(struct phy_device *phydev) 570bdb4c5b8SRadu Pirea (NXP OSS) { 571bdb4c5b8SRadu Pirea (NXP OSS) bool valid; 572bdb4c5b8SRadu Pirea (NXP OSS) u16 reg; 573bdb4c5b8SRadu Pirea (NXP OSS) 574bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S); 575bdb4c5b8SRadu Pirea (NXP OSS) valid = !!(reg & TJA1120_TS_VALID); 576bdb4c5b8SRadu Pirea (NXP OSS) 577bdb4c5b8SRadu Pirea (NXP OSS) return valid; 578bdb4c5b8SRadu Pirea (NXP OSS) } 579bdb4c5b8SRadu Pirea (NXP OSS) 580bdb4c5b8SRadu Pirea (NXP OSS) static bool tja1120_get_hwtxts(struct nxp_c45_phy *priv, 581bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 582bdb4c5b8SRadu Pirea (NXP OSS) { 583bdb4c5b8SRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 584bdb4c5b8SRadu Pirea (NXP OSS) bool more_ts; 585bdb4c5b8SRadu Pirea (NXP OSS) bool valid; 586bdb4c5b8SRadu Pirea (NXP OSS) u16 reg; 587bdb4c5b8SRadu Pirea (NXP OSS) 588bdb4c5b8SRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 589bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_END); 590bdb4c5b8SRadu Pirea (NXP OSS) more_ts = !!(reg & TJA1120_MORE_TS); 591bdb4c5b8SRadu Pirea (NXP OSS) valid = tja1120_egress_ts_is_valid(phydev); 592bdb4c5b8SRadu Pirea (NXP OSS) if (!valid) { 593bdb4c5b8SRadu Pirea (NXP OSS) if (!more_ts) 594bdb4c5b8SRadu Pirea (NXP OSS) goto tja1120_get_hwtxts_out; 595bdb4c5b8SRadu Pirea (NXP OSS) 596bdb4c5b8SRadu Pirea (NXP OSS) /* Bug workaround for TJA1120 engineering samples: move the 597bdb4c5b8SRadu Pirea (NXP OSS) * new timestamp from the FIFO to the buffer. 598bdb4c5b8SRadu Pirea (NXP OSS) */ 599bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 600bdb4c5b8SRadu Pirea (NXP OSS) TJA1120_EGRESS_TS_END, TJA1120_TS_VALID); 601bdb4c5b8SRadu Pirea (NXP OSS) valid = tja1120_egress_ts_is_valid(phydev); 602bdb4c5b8SRadu Pirea (NXP OSS) if (!valid) 603bdb4c5b8SRadu Pirea (NXP OSS) goto tja1120_get_hwtxts_out; 604bdb4c5b8SRadu Pirea (NXP OSS) } 605bdb4c5b8SRadu Pirea (NXP OSS) nxp_c45_read_egress_ts(priv, hwts); 606bdb4c5b8SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S, 607bdb4c5b8SRadu Pirea (NXP OSS) TJA1120_TS_VALID); 608bdb4c5b8SRadu Pirea (NXP OSS) tja1120_get_hwtxts_out: 609bdb4c5b8SRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 610bdb4c5b8SRadu Pirea (NXP OSS) return valid; 611bdb4c5b8SRadu Pirea (NXP OSS) } 612bdb4c5b8SRadu Pirea (NXP OSS) 613514def5dSRadu Pirea (NXP OSS) static void nxp_c45_process_txts(struct nxp_c45_phy *priv, 614514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *txts) 615514def5dSRadu Pirea (NXP OSS) { 616514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, *tmp, *skb_match = NULL; 617514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps shhwtstamps; 618514def5dSRadu Pirea (NXP OSS) struct timespec64 ts; 619514def5dSRadu Pirea (NXP OSS) unsigned long flags; 620514def5dSRadu Pirea (NXP OSS) bool ts_match; 621514def5dSRadu Pirea (NXP OSS) s64 ts_ns; 622514def5dSRadu Pirea (NXP OSS) 623514def5dSRadu Pirea (NXP OSS) spin_lock_irqsave(&priv->tx_queue.lock, flags); 624514def5dSRadu Pirea (NXP OSS) skb_queue_walk_safe(&priv->tx_queue, skb, tmp) { 625514def5dSRadu Pirea (NXP OSS) ts_match = nxp_c45_match_ts(NXP_C45_SKB_CB(skb)->header, txts, 626514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type); 627514def5dSRadu Pirea (NXP OSS) if (!ts_match) 628514def5dSRadu Pirea (NXP OSS) continue; 629514def5dSRadu Pirea (NXP OSS) skb_match = skb; 630514def5dSRadu Pirea (NXP OSS) __skb_unlink(skb, &priv->tx_queue); 631514def5dSRadu Pirea (NXP OSS) break; 632514def5dSRadu Pirea (NXP OSS) } 633514def5dSRadu Pirea (NXP OSS) spin_unlock_irqrestore(&priv->tx_queue.lock, flags); 634514def5dSRadu Pirea (NXP OSS) 635514def5dSRadu Pirea (NXP OSS) if (skb_match) { 636514def5dSRadu Pirea (NXP OSS) nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL); 637514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, txts); 638514def5dSRadu Pirea (NXP OSS) memset(&shhwtstamps, 0, sizeof(shhwtstamps)); 639514def5dSRadu Pirea (NXP OSS) ts_ns = timespec64_to_ns(&ts); 640514def5dSRadu Pirea (NXP OSS) shhwtstamps.hwtstamp = ns_to_ktime(ts_ns); 641514def5dSRadu Pirea (NXP OSS) skb_complete_tx_timestamp(skb_match, &shhwtstamps); 642514def5dSRadu Pirea (NXP OSS) } else { 643514def5dSRadu Pirea (NXP OSS) phydev_warn(priv->phydev, 644514def5dSRadu Pirea (NXP OSS) "the tx timestamp doesn't match with any skb\n"); 645514def5dSRadu Pirea (NXP OSS) } 646514def5dSRadu Pirea (NXP OSS) } 647514def5dSRadu Pirea (NXP OSS) 648514def5dSRadu Pirea (NXP OSS) static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp) 649514def5dSRadu Pirea (NXP OSS) { 650514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 651bdb4c5b8SRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); 652514def5dSRadu Pirea (NXP OSS) bool poll_txts = nxp_c45_poll_txts(priv->phydev); 653514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps *shhwtstamps_rx; 6547a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_event event; 655514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts; 656514def5dSRadu Pirea (NXP OSS) bool reschedule = false; 657514def5dSRadu Pirea (NXP OSS) struct timespec64 ts; 658514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb; 659514def5dSRadu Pirea (NXP OSS) bool txts_valid; 660514def5dSRadu Pirea (NXP OSS) u32 ts_raw; 661514def5dSRadu Pirea (NXP OSS) 662514def5dSRadu Pirea (NXP OSS) while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) { 663bdb4c5b8SRadu Pirea (NXP OSS) txts_valid = data->get_egressts(priv, &hwts); 664514def5dSRadu Pirea (NXP OSS) if (unlikely(!txts_valid)) { 665514def5dSRadu Pirea (NXP OSS) /* Still more skbs in the queue */ 666514def5dSRadu Pirea (NXP OSS) reschedule = true; 667514def5dSRadu Pirea (NXP OSS) break; 668514def5dSRadu Pirea (NXP OSS) } 669514def5dSRadu Pirea (NXP OSS) 670514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts); 671514def5dSRadu Pirea (NXP OSS) } 672514def5dSRadu Pirea (NXP OSS) 673514def5dSRadu Pirea (NXP OSS) while ((skb = skb_dequeue(&priv->rx_queue)) != NULL) { 674109258edSVladimir Oltean nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL); 675514def5dSRadu Pirea (NXP OSS) ts_raw = __be32_to_cpu(NXP_C45_SKB_CB(skb)->header->reserved2); 676514def5dSRadu Pirea (NXP OSS) hwts.sec = ts_raw >> 30; 677514def5dSRadu Pirea (NXP OSS) hwts.nsec = ts_raw & GENMASK(29, 0); 678514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, &hwts); 679514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx = skb_hwtstamps(skb); 680514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx->hwtstamp = ns_to_ktime(timespec64_to_ns(&ts)); 681514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header->reserved2 = 0; 682a3d73e15SSebastian Andrzej Siewior netif_rx(skb); 683514def5dSRadu Pirea (NXP OSS) } 684514def5dSRadu Pirea (NXP OSS) 6857a71c8aaSRadu Pirea (NXP OSS) if (priv->extts) { 6867a71c8aaSRadu Pirea (NXP OSS) nxp_c45_get_extts(priv, &ts); 6877a71c8aaSRadu Pirea (NXP OSS) if (timespec64_compare(&ts, &priv->extts_ts) != 0) { 6887a71c8aaSRadu Pirea (NXP OSS) priv->extts_ts = ts; 6897a71c8aaSRadu Pirea (NXP OSS) event.index = priv->extts_index; 6907a71c8aaSRadu Pirea (NXP OSS) event.type = PTP_CLOCK_EXTTS; 6917a71c8aaSRadu Pirea (NXP OSS) event.timestamp = ns_to_ktime(timespec64_to_ns(&ts)); 6927a71c8aaSRadu Pirea (NXP OSS) ptp_clock_event(priv->ptp_clock, &event); 6937a71c8aaSRadu Pirea (NXP OSS) } 6947a71c8aaSRadu Pirea (NXP OSS) reschedule = true; 6957a71c8aaSRadu Pirea (NXP OSS) } 6967a71c8aaSRadu Pirea (NXP OSS) 697514def5dSRadu Pirea (NXP OSS) return reschedule ? 1 : -1; 698514def5dSRadu Pirea (NXP OSS) } 699514def5dSRadu Pirea (NXP OSS) 7007a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_gpio_config(struct nxp_c45_phy *priv, 7017a71c8aaSRadu Pirea (NXP OSS) int pin, u16 pin_cfg) 7027a71c8aaSRadu Pirea (NXP OSS) { 7037a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 7047a71c8aaSRadu Pirea (NXP OSS) 7057a71c8aaSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 7067a71c8aaSRadu Pirea (NXP OSS) VEND1_GPIO_FUNC_CONFIG_BASE + pin, pin_cfg); 7077a71c8aaSRadu Pirea (NXP OSS) } 7087a71c8aaSRadu Pirea (NXP OSS) 7097a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_perout_enable(struct nxp_c45_phy *priv, 7107a71c8aaSRadu Pirea (NXP OSS) struct ptp_perout_request *perout, int on) 7117a71c8aaSRadu Pirea (NXP OSS) { 7126c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 7137a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 7147a71c8aaSRadu Pirea (NXP OSS) int pin; 7157a71c8aaSRadu Pirea (NXP OSS) 7167a71c8aaSRadu Pirea (NXP OSS) if (perout->flags & ~PTP_PEROUT_PHASE) 7177a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 7187a71c8aaSRadu Pirea (NXP OSS) 7197a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_PEROUT, perout->index); 7207a71c8aaSRadu Pirea (NXP OSS) if (pin < 0) 7217a71c8aaSRadu Pirea (NXP OSS) return pin; 7227a71c8aaSRadu Pirea (NXP OSS) 7237a71c8aaSRadu Pirea (NXP OSS) if (!on) { 7246c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 7256c0c85daSRadu Pirea (NXP OSS) ®map->pps_enable); 7266c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 7276c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 7287a71c8aaSRadu Pirea (NXP OSS) 7297a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); 7307a71c8aaSRadu Pirea (NXP OSS) 7317a71c8aaSRadu Pirea (NXP OSS) return 0; 7327a71c8aaSRadu Pirea (NXP OSS) } 7337a71c8aaSRadu Pirea (NXP OSS) 7347a71c8aaSRadu Pirea (NXP OSS) /* The PPS signal is fixed to 1 second and is always generated when the 7357a71c8aaSRadu Pirea (NXP OSS) * seconds counter is incremented. The start time is not configurable. 7367a71c8aaSRadu Pirea (NXP OSS) * If the clock is adjusted, the PPS signal is automatically readjusted. 7377a71c8aaSRadu Pirea (NXP OSS) */ 7387a71c8aaSRadu Pirea (NXP OSS) if (perout->period.sec != 1 || perout->period.nsec != 0) { 7397a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The period can be set only to 1 second."); 7407a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 7417a71c8aaSRadu Pirea (NXP OSS) } 7427a71c8aaSRadu Pirea (NXP OSS) 7437a71c8aaSRadu Pirea (NXP OSS) if (!(perout->flags & PTP_PEROUT_PHASE)) { 7447a71c8aaSRadu Pirea (NXP OSS) if (perout->start.sec != 0 || perout->start.nsec != 0) { 7457a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The start time is not configurable. Should be set to 0 seconds and 0 nanoseconds."); 7467a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 7477a71c8aaSRadu Pirea (NXP OSS) } 7487a71c8aaSRadu Pirea (NXP OSS) } else { 7497a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec != 0 && 7507a71c8aaSRadu Pirea (NXP OSS) perout->phase.nsec != (NSEC_PER_SEC >> 1)) { 7517a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The phase can be set only to 0 or 500000000 nanoseconds."); 7527a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 7537a71c8aaSRadu Pirea (NXP OSS) } 7547a71c8aaSRadu Pirea (NXP OSS) 7557a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec == 0) 7566c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 7576c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 7587a71c8aaSRadu Pirea (NXP OSS) else 7596c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, 7606c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 7617a71c8aaSRadu Pirea (NXP OSS) } 7627a71c8aaSRadu Pirea (NXP OSS) 7637a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_PPS_OUT_CFG); 7647a71c8aaSRadu Pirea (NXP OSS) 7656c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->pps_enable); 7667a71c8aaSRadu Pirea (NXP OSS) 7677a71c8aaSRadu Pirea (NXP OSS) return 0; 7687a71c8aaSRadu Pirea (NXP OSS) } 7697a71c8aaSRadu Pirea (NXP OSS) 770b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_or_falling(struct phy_device *phydev, 771b0b2247dSRadu Pirea (NXP OSS) struct ptp_extts_request *extts) 772b0b2247dSRadu Pirea (NXP OSS) { 773b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE) 774b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 775b0b2247dSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE); 776b0b2247dSRadu Pirea (NXP OSS) 777b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE) 778b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 779b0b2247dSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE); 780b0b2247dSRadu Pirea (NXP OSS) } 781b0b2247dSRadu Pirea (NXP OSS) 782b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_and_falling(struct phy_device *phydev, 783b0b2247dSRadu Pirea (NXP OSS) struct ptp_extts_request *extts) 784b0b2247dSRadu Pirea (NXP OSS) { 785b0b2247dSRadu Pirea (NXP OSS) /* PTP_EXTTS_REQUEST may have only the PTP_ENABLE_FEATURE flag set. In 786b0b2247dSRadu Pirea (NXP OSS) * this case external ts will be enabled on rising edge. 787b0b2247dSRadu Pirea (NXP OSS) */ 788b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE || 789b0b2247dSRadu Pirea (NXP OSS) extts->flags == PTP_ENABLE_FEATURE) 790b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 791b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 792b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_RISE_TS); 793b0b2247dSRadu Pirea (NXP OSS) else 794b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 795b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 796b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_RISE_TS); 797b0b2247dSRadu Pirea (NXP OSS) 798b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE) 799b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 800b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 801b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_FALLING_TS); 802b0b2247dSRadu Pirea (NXP OSS) else 803b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 804b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 805b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_FALLING_TS); 806b0b2247dSRadu Pirea (NXP OSS) } 807b0b2247dSRadu Pirea (NXP OSS) 8087a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_extts_enable(struct nxp_c45_phy *priv, 8097a71c8aaSRadu Pirea (NXP OSS) struct ptp_extts_request *extts, int on) 8107a71c8aaSRadu Pirea (NXP OSS) { 811b0b2247dSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); 8127a71c8aaSRadu Pirea (NXP OSS) int pin; 8137a71c8aaSRadu Pirea (NXP OSS) 8147a71c8aaSRadu Pirea (NXP OSS) if (extts->flags & ~(PTP_ENABLE_FEATURE | 8157a71c8aaSRadu Pirea (NXP OSS) PTP_RISING_EDGE | 8167a71c8aaSRadu Pirea (NXP OSS) PTP_FALLING_EDGE | 8177a71c8aaSRadu Pirea (NXP OSS) PTP_STRICT_FLAGS)) 8187a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 8197a71c8aaSRadu Pirea (NXP OSS) 8207a71c8aaSRadu Pirea (NXP OSS) /* Sampling on both edges is not supported */ 8217a71c8aaSRadu Pirea (NXP OSS) if ((extts->flags & PTP_RISING_EDGE) && 822b0b2247dSRadu Pirea (NXP OSS) (extts->flags & PTP_FALLING_EDGE) && 823b0b2247dSRadu Pirea (NXP OSS) !data->ext_ts_both_edges) 8247a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 8257a71c8aaSRadu Pirea (NXP OSS) 8267a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_EXTTS, extts->index); 8277a71c8aaSRadu Pirea (NXP OSS) if (pin < 0) 8287a71c8aaSRadu Pirea (NXP OSS) return pin; 8297a71c8aaSRadu Pirea (NXP OSS) 8307a71c8aaSRadu Pirea (NXP OSS) if (!on) { 8317a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); 8327a71c8aaSRadu Pirea (NXP OSS) priv->extts = false; 8337a71c8aaSRadu Pirea (NXP OSS) 8347a71c8aaSRadu Pirea (NXP OSS) return 0; 8357a71c8aaSRadu Pirea (NXP OSS) } 8367a71c8aaSRadu Pirea (NXP OSS) 837b0b2247dSRadu Pirea (NXP OSS) if (data->ext_ts_both_edges) 838b0b2247dSRadu Pirea (NXP OSS) nxp_c45_set_rising_and_falling(priv->phydev, extts); 839b0b2247dSRadu Pirea (NXP OSS) else 840b0b2247dSRadu Pirea (NXP OSS) nxp_c45_set_rising_or_falling(priv->phydev, extts); 8417a71c8aaSRadu Pirea (NXP OSS) 8427a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_EXTTS_OUT_CFG); 8437a71c8aaSRadu Pirea (NXP OSS) priv->extts = true; 8447a71c8aaSRadu Pirea (NXP OSS) priv->extts_index = extts->index; 8457a71c8aaSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 8467a71c8aaSRadu Pirea (NXP OSS) 8477a71c8aaSRadu Pirea (NXP OSS) return 0; 8487a71c8aaSRadu Pirea (NXP OSS) } 8497a71c8aaSRadu Pirea (NXP OSS) 8507a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_enable(struct ptp_clock_info *ptp, 8517a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_request *req, int on) 8527a71c8aaSRadu Pirea (NXP OSS) { 8537a71c8aaSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 8547a71c8aaSRadu Pirea (NXP OSS) 8557a71c8aaSRadu Pirea (NXP OSS) switch (req->type) { 8567a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_EXTTS: 8577a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_extts_enable(priv, &req->extts, on); 8587a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_PEROUT: 8597a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_perout_enable(priv, &req->perout, on); 8607a71c8aaSRadu Pirea (NXP OSS) default: 8617a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 8627a71c8aaSRadu Pirea (NXP OSS) } 8637a71c8aaSRadu Pirea (NXP OSS) } 8647a71c8aaSRadu Pirea (NXP OSS) 8657a71c8aaSRadu Pirea (NXP OSS) static struct ptp_pin_desc nxp_c45_ptp_pins[] = { 8667a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio0", 0, PTP_PF_NONE}, 8677a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio1", 1, PTP_PF_NONE}, 8687a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio2", 2, PTP_PF_NONE}, 8697a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio3", 3, PTP_PF_NONE}, 8707a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio4", 4, PTP_PF_NONE}, 8717a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio5", 5, PTP_PF_NONE}, 8727a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio6", 6, PTP_PF_NONE}, 8737a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio7", 7, PTP_PF_NONE}, 8747a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio8", 8, PTP_PF_NONE}, 8757a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio9", 9, PTP_PF_NONE}, 8767a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio10", 10, PTP_PF_NONE}, 8777a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio11", 11, PTP_PF_NONE}, 8787a71c8aaSRadu Pirea (NXP OSS) }; 8797a71c8aaSRadu Pirea (NXP OSS) 8807a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, 8817a71c8aaSRadu Pirea (NXP OSS) enum ptp_pin_function func, unsigned int chan) 8827a71c8aaSRadu Pirea (NXP OSS) { 8837a71c8aaSRadu Pirea (NXP OSS) if (pin >= ARRAY_SIZE(nxp_c45_ptp_pins)) 8847a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 8857a71c8aaSRadu Pirea (NXP OSS) 8867a71c8aaSRadu Pirea (NXP OSS) switch (func) { 8877a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_NONE: 8887a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_PEROUT: 8897a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_EXTTS: 8907a71c8aaSRadu Pirea (NXP OSS) break; 8917a71c8aaSRadu Pirea (NXP OSS) default: 8927a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 8937a71c8aaSRadu Pirea (NXP OSS) } 8947a71c8aaSRadu Pirea (NXP OSS) 8957a71c8aaSRadu Pirea (NXP OSS) return 0; 8967a71c8aaSRadu Pirea (NXP OSS) } 8977a71c8aaSRadu Pirea (NXP OSS) 898514def5dSRadu Pirea (NXP OSS) static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv) 899514def5dSRadu Pirea (NXP OSS) { 900514def5dSRadu Pirea (NXP OSS) priv->caps = (struct ptp_clock_info) { 901514def5dSRadu Pirea (NXP OSS) .owner = THIS_MODULE, 902514def5dSRadu Pirea (NXP OSS) .name = "NXP C45 PHC", 903514def5dSRadu Pirea (NXP OSS) .max_adj = 16666666, 904514def5dSRadu Pirea (NXP OSS) .adjfine = nxp_c45_ptp_adjfine, 905514def5dSRadu Pirea (NXP OSS) .adjtime = nxp_c45_ptp_adjtime, 906514def5dSRadu Pirea (NXP OSS) .gettimex64 = nxp_c45_ptp_gettimex64, 907514def5dSRadu Pirea (NXP OSS) .settime64 = nxp_c45_ptp_settime64, 9087a71c8aaSRadu Pirea (NXP OSS) .enable = nxp_c45_ptp_enable, 9097a71c8aaSRadu Pirea (NXP OSS) .verify = nxp_c45_ptp_verify_pin, 910514def5dSRadu Pirea (NXP OSS) .do_aux_work = nxp_c45_do_aux_work, 9117a71c8aaSRadu Pirea (NXP OSS) .pin_config = nxp_c45_ptp_pins, 9127a71c8aaSRadu Pirea (NXP OSS) .n_pins = ARRAY_SIZE(nxp_c45_ptp_pins), 9137a71c8aaSRadu Pirea (NXP OSS) .n_ext_ts = 1, 9147a71c8aaSRadu Pirea (NXP OSS) .n_per_out = 1, 915514def5dSRadu Pirea (NXP OSS) }; 916514def5dSRadu Pirea (NXP OSS) 917514def5dSRadu Pirea (NXP OSS) priv->ptp_clock = ptp_clock_register(&priv->caps, 918514def5dSRadu Pirea (NXP OSS) &priv->phydev->mdio.dev); 919514def5dSRadu Pirea (NXP OSS) 920514def5dSRadu Pirea (NXP OSS) if (IS_ERR(priv->ptp_clock)) 921514def5dSRadu Pirea (NXP OSS) return PTR_ERR(priv->ptp_clock); 922514def5dSRadu Pirea (NXP OSS) 923514def5dSRadu Pirea (NXP OSS) if (!priv->ptp_clock) 924514def5dSRadu Pirea (NXP OSS) return -ENOMEM; 925514def5dSRadu Pirea (NXP OSS) 926514def5dSRadu Pirea (NXP OSS) return 0; 927514def5dSRadu Pirea (NXP OSS) } 928514def5dSRadu Pirea (NXP OSS) 929514def5dSRadu Pirea (NXP OSS) static void nxp_c45_txtstamp(struct mii_timestamper *mii_ts, 930514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type) 931514def5dSRadu Pirea (NXP OSS) { 932514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 933514def5dSRadu Pirea (NXP OSS) mii_ts); 934514def5dSRadu Pirea (NXP OSS) 935514def5dSRadu Pirea (NXP OSS) switch (priv->hwts_tx) { 936514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_ON: 937514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type = type; 938514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = ptp_parse_header(skb, type); 939514def5dSRadu Pirea (NXP OSS) skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 940514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->tx_queue, skb); 941514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev)) 942514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 943514def5dSRadu Pirea (NXP OSS) break; 944514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_OFF: 945514def5dSRadu Pirea (NXP OSS) default: 946514def5dSRadu Pirea (NXP OSS) kfree_skb(skb); 947514def5dSRadu Pirea (NXP OSS) break; 948514def5dSRadu Pirea (NXP OSS) } 949514def5dSRadu Pirea (NXP OSS) } 950514def5dSRadu Pirea (NXP OSS) 951514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_rxtstamp(struct mii_timestamper *mii_ts, 952514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type) 953514def5dSRadu Pirea (NXP OSS) { 954514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 955514def5dSRadu Pirea (NXP OSS) mii_ts); 956514def5dSRadu Pirea (NXP OSS) struct ptp_header *header = ptp_parse_header(skb, type); 957514def5dSRadu Pirea (NXP OSS) 958514def5dSRadu Pirea (NXP OSS) if (!header) 959514def5dSRadu Pirea (NXP OSS) return false; 960514def5dSRadu Pirea (NXP OSS) 961514def5dSRadu Pirea (NXP OSS) if (!priv->hwts_rx) 962514def5dSRadu Pirea (NXP OSS) return false; 963514def5dSRadu Pirea (NXP OSS) 964514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = header; 965514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->rx_queue, skb); 966514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 967514def5dSRadu Pirea (NXP OSS) 968514def5dSRadu Pirea (NXP OSS) return true; 969514def5dSRadu Pirea (NXP OSS) } 970514def5dSRadu Pirea (NXP OSS) 971514def5dSRadu Pirea (NXP OSS) static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts, 972514def5dSRadu Pirea (NXP OSS) struct ifreq *ifreq) 973514def5dSRadu Pirea (NXP OSS) { 974514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 975514def5dSRadu Pirea (NXP OSS) mii_ts); 976514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 9776c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data; 978514def5dSRadu Pirea (NXP OSS) struct hwtstamp_config cfg; 979514def5dSRadu Pirea (NXP OSS) 980514def5dSRadu Pirea (NXP OSS) if (copy_from_user(&cfg, ifreq->ifr_data, sizeof(cfg))) 981514def5dSRadu Pirea (NXP OSS) return -EFAULT; 982514def5dSRadu Pirea (NXP OSS) 983514def5dSRadu Pirea (NXP OSS) if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ON) 984514def5dSRadu Pirea (NXP OSS) return -ERANGE; 985514def5dSRadu Pirea (NXP OSS) 9866c0c85daSRadu Pirea (NXP OSS) data = nxp_c45_get_data(phydev); 987514def5dSRadu Pirea (NXP OSS) priv->hwts_tx = cfg.tx_type; 988514def5dSRadu Pirea (NXP OSS) 989514def5dSRadu Pirea (NXP OSS) switch (cfg.rx_filter) { 990514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_NONE: 991514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 0; 992514def5dSRadu Pirea (NXP OSS) break; 993514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 994514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 995514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 996514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 1; 997514def5dSRadu Pirea (NXP OSS) cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; 998514def5dSRadu Pirea (NXP OSS) break; 999514def5dSRadu Pirea (NXP OSS) default: 1000514def5dSRadu Pirea (NXP OSS) return -ERANGE; 1001514def5dSRadu Pirea (NXP OSS) } 1002514def5dSRadu Pirea (NXP OSS) 1003514def5dSRadu Pirea (NXP OSS) if (priv->hwts_rx || priv->hwts_tx) { 10046c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 10056c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_event_msg_filt, 1006514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_ALL); 10076c0c85daSRadu Pirea (NXP OSS) data->ptp_enable(phydev, true); 1008514def5dSRadu Pirea (NXP OSS) } else { 10096c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 10106c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_event_msg_filt, 1011514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_NONE); 10126c0c85daSRadu Pirea (NXP OSS) data->ptp_enable(phydev, false); 1013514def5dSRadu Pirea (NXP OSS) } 1014514def5dSRadu Pirea (NXP OSS) 1015514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev)) 1016514def5dSRadu Pirea (NXP OSS) goto nxp_c45_no_ptp_irq; 1017514def5dSRadu Pirea (NXP OSS) 1018514def5dSRadu Pirea (NXP OSS) if (priv->hwts_tx) 10196c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(phydev, &data->regmap->irq_egr_ts_en); 1020514def5dSRadu Pirea (NXP OSS) else 10216c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(phydev, &data->regmap->irq_egr_ts_en); 1022514def5dSRadu Pirea (NXP OSS) 1023514def5dSRadu Pirea (NXP OSS) nxp_c45_no_ptp_irq: 1024514def5dSRadu Pirea (NXP OSS) return copy_to_user(ifreq->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 1025514def5dSRadu Pirea (NXP OSS) } 1026514def5dSRadu Pirea (NXP OSS) 1027514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ts_info(struct mii_timestamper *mii_ts, 1028514def5dSRadu Pirea (NXP OSS) struct ethtool_ts_info *ts_info) 1029514def5dSRadu Pirea (NXP OSS) { 1030514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 1031514def5dSRadu Pirea (NXP OSS) mii_ts); 1032514def5dSRadu Pirea (NXP OSS) 1033514def5dSRadu Pirea (NXP OSS) ts_info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | 1034514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RX_HARDWARE | 1035514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RAW_HARDWARE; 1036514def5dSRadu Pirea (NXP OSS) ts_info->phc_index = ptp_clock_index(priv->ptp_clock); 1037514def5dSRadu Pirea (NXP OSS) ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); 1038514def5dSRadu Pirea (NXP OSS) ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | 1039514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | 1040514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | 1041514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT); 1042514def5dSRadu Pirea (NXP OSS) 1043514def5dSRadu Pirea (NXP OSS) return 0; 1044514def5dSRadu Pirea (NXP OSS) } 1045514def5dSRadu Pirea (NXP OSS) 10466c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats common_hw_stats[] = { 10476c0c85daSRadu Pirea (NXP OSS) { "phy_link_status_drop_cnt", 10486c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 8, 6), }, 10496c0c85daSRadu Pirea (NXP OSS) { "phy_link_availability_drop_cnt", 10506c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 0, 6), }, 10516c0c85daSRadu Pirea (NXP OSS) { "phy_link_loss_cnt", 10526c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 10, 6), }, 10536c0c85daSRadu Pirea (NXP OSS) { "phy_link_failure_cnt", 10546c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 0, 10), }, 10556c0c85daSRadu Pirea (NXP OSS) { "phy_symbol_error_cnt", 10566c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8350, MDIO_MMD_VEND1, 0, 16) }, 10576c0c85daSRadu Pirea (NXP OSS) }; 10586c0c85daSRadu Pirea (NXP OSS) 10596c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1103_hw_stats[] = { 10606c0c85daSRadu Pirea (NXP OSS) { "rx_preamble_count", 10616c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFCE, MDIO_MMD_VEND1, 0, 6), }, 10626c0c85daSRadu Pirea (NXP OSS) { "tx_preamble_count", 10636c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFCF, MDIO_MMD_VEND1, 0, 6), }, 10646c0c85daSRadu Pirea (NXP OSS) { "rx_ipg_length", 10656c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFD0, MDIO_MMD_VEND1, 0, 9), }, 10666c0c85daSRadu Pirea (NXP OSS) { "tx_ipg_length", 10676c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFD1, MDIO_MMD_VEND1, 0, 9), }, 1068b050f2f1SRadu Pirea (NXP OSS) }; 1069b050f2f1SRadu Pirea (NXP OSS) 1070f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1120_hw_stats[] = { 1071f1fe5dffSRadu Pirea (NXP OSS) { "phy_symbol_error_cnt_ext", 1072f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8351, MDIO_MMD_VEND1, 0, 14) }, 1073f1fe5dffSRadu Pirea (NXP OSS) { "tx_frames_xtd", 1074f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA1, MDIO_MMD_VEND1, 0, 8), }, 1075f1fe5dffSRadu Pirea (NXP OSS) { "tx_frames", 1076f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA0, MDIO_MMD_VEND1, 0, 16), }, 1077f1fe5dffSRadu Pirea (NXP OSS) { "rx_frames_xtd", 1078f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA3, MDIO_MMD_VEND1, 0, 8), }, 1079f1fe5dffSRadu Pirea (NXP OSS) { "rx_frames", 1080f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA2, MDIO_MMD_VEND1, 0, 16), }, 1081f1fe5dffSRadu Pirea (NXP OSS) { "tx_lost_frames_xtd", 1082f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA5, MDIO_MMD_VEND1, 0, 8), }, 1083f1fe5dffSRadu Pirea (NXP OSS) { "tx_lost_frames", 1084f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA4, MDIO_MMD_VEND1, 0, 16), }, 1085f1fe5dffSRadu Pirea (NXP OSS) { "rx_lost_frames_xtd", 1086f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA7, MDIO_MMD_VEND1, 0, 8), }, 1087f1fe5dffSRadu Pirea (NXP OSS) { "rx_lost_frames", 1088f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA6, MDIO_MMD_VEND1, 0, 16), }, 1089f1fe5dffSRadu Pirea (NXP OSS) }; 1090f1fe5dffSRadu Pirea (NXP OSS) 1091b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev) 1092b050f2f1SRadu Pirea (NXP OSS) { 10936c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 10946c0c85daSRadu Pirea (NXP OSS) 10956c0c85daSRadu Pirea (NXP OSS) return ARRAY_SIZE(common_hw_stats) + (phy_data ? phy_data->n_stats : 0); 1096b050f2f1SRadu Pirea (NXP OSS) } 1097b050f2f1SRadu Pirea (NXP OSS) 1098b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data) 1099b050f2f1SRadu Pirea (NXP OSS) { 11006c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 11016c0c85daSRadu Pirea (NXP OSS) size_t count = nxp_c45_get_sset_count(phydev); 11026c0c85daSRadu Pirea (NXP OSS) size_t idx; 1103b050f2f1SRadu Pirea (NXP OSS) size_t i; 1104b050f2f1SRadu Pirea (NXP OSS) 11056c0c85daSRadu Pirea (NXP OSS) for (i = 0; i < count; i++) { 11066c0c85daSRadu Pirea (NXP OSS) if (i < ARRAY_SIZE(common_hw_stats)) { 11076c0c85daSRadu Pirea (NXP OSS) strscpy(data + i * ETH_GSTRING_LEN, 11086c0c85daSRadu Pirea (NXP OSS) common_hw_stats[i].name, ETH_GSTRING_LEN); 11096c0c85daSRadu Pirea (NXP OSS) continue; 11106c0c85daSRadu Pirea (NXP OSS) } 11116c0c85daSRadu Pirea (NXP OSS) idx = i - ARRAY_SIZE(common_hw_stats); 11126c0c85daSRadu Pirea (NXP OSS) strscpy(data + i * ETH_GSTRING_LEN, 11136c0c85daSRadu Pirea (NXP OSS) phy_data->stats[idx].name, ETH_GSTRING_LEN); 1114b050f2f1SRadu Pirea (NXP OSS) } 1115b050f2f1SRadu Pirea (NXP OSS) } 1116b050f2f1SRadu Pirea (NXP OSS) 1117b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev, 1118b050f2f1SRadu Pirea (NXP OSS) struct ethtool_stats *stats, u64 *data) 1119b050f2f1SRadu Pirea (NXP OSS) { 11206c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 11216c0c85daSRadu Pirea (NXP OSS) size_t count = nxp_c45_get_sset_count(phydev); 11226c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field; 11236c0c85daSRadu Pirea (NXP OSS) size_t idx; 1124b050f2f1SRadu Pirea (NXP OSS) size_t i; 1125b050f2f1SRadu Pirea (NXP OSS) int ret; 1126b050f2f1SRadu Pirea (NXP OSS) 11276c0c85daSRadu Pirea (NXP OSS) for (i = 0; i < count; i++) { 11286c0c85daSRadu Pirea (NXP OSS) if (i < ARRAY_SIZE(common_hw_stats)) { 11296c0c85daSRadu Pirea (NXP OSS) reg_field = &common_hw_stats[i].counter; 1130b050f2f1SRadu Pirea (NXP OSS) } else { 11316c0c85daSRadu Pirea (NXP OSS) idx = i - ARRAY_SIZE(common_hw_stats); 11326c0c85daSRadu Pirea (NXP OSS) reg_field = &phy_data->stats[idx].counter; 1133b050f2f1SRadu Pirea (NXP OSS) } 11346c0c85daSRadu Pirea (NXP OSS) 11356c0c85daSRadu Pirea (NXP OSS) ret = nxp_c45_read_reg_field(phydev, reg_field); 11366c0c85daSRadu Pirea (NXP OSS) if (ret < 0) 11376c0c85daSRadu Pirea (NXP OSS) data[i] = U64_MAX; 11386c0c85daSRadu Pirea (NXP OSS) else 11396c0c85daSRadu Pirea (NXP OSS) data[i] = ret; 1140b050f2f1SRadu Pirea (NXP OSS) } 1141b050f2f1SRadu Pirea (NXP OSS) } 1142b050f2f1SRadu Pirea (NXP OSS) 1143b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev) 1144b050f2f1SRadu Pirea (NXP OSS) { 1145b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 1146b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_GLOBAL_EN | 1147b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_ALL_EN); 1148b050f2f1SRadu Pirea (NXP OSS) usleep_range(400, 450); 1149b050f2f1SRadu Pirea (NXP OSS) 1150b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL, 1151b050f2f1SRadu Pirea (NXP OSS) PORT_CONTROL_EN); 1152b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 1153b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_EN); 1154b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL, 1155b050f2f1SRadu Pirea (NXP OSS) PORT_INFRA_CONTROL_EN); 1156b050f2f1SRadu Pirea (NXP OSS) 1157b050f2f1SRadu Pirea (NXP OSS) return 0; 1158b050f2f1SRadu Pirea (NXP OSS) } 1159b050f2f1SRadu Pirea (NXP OSS) 1160b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev) 1161b050f2f1SRadu Pirea (NXP OSS) { 1162b050f2f1SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 1163b050f2f1SRadu Pirea (NXP OSS) PHY_START_OP); 1164b050f2f1SRadu Pirea (NXP OSS) } 1165b050f2f1SRadu Pirea (NXP OSS) 1166b2f0ca00SRadu Pirea (NXP OSS) static int nxp_c45_config_intr(struct phy_device *phydev) 1167b2f0ca00SRadu Pirea (NXP OSS) { 1168b2f0ca00SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1169b2f0ca00SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1170b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 1171b2f0ca00SRadu Pirea (NXP OSS) else 1172b2f0ca00SRadu Pirea (NXP OSS) return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1173b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 1174b2f0ca00SRadu Pirea (NXP OSS) } 1175b2f0ca00SRadu Pirea (NXP OSS) 1176425c8348SRadu Pirea (NXP OSS) static int tja1103_config_intr(struct phy_device *phydev) 1177425c8348SRadu Pirea (NXP OSS) { 1178425c8348SRadu Pirea (NXP OSS) int ret; 1179425c8348SRadu Pirea (NXP OSS) 1180425c8348SRadu Pirea (NXP OSS) /* We can't disable the FUSA IRQ for TJA1103, but we can clean it up. */ 1181425c8348SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_ALWAYS_ACCESSIBLE, 1182425c8348SRadu Pirea (NXP OSS) FUSA_PASS); 1183425c8348SRadu Pirea (NXP OSS) if (ret) 1184425c8348SRadu Pirea (NXP OSS) return ret; 1185425c8348SRadu Pirea (NXP OSS) 1186425c8348SRadu Pirea (NXP OSS) return nxp_c45_config_intr(phydev); 1187425c8348SRadu Pirea (NXP OSS) } 1188425c8348SRadu Pirea (NXP OSS) 1189425c8348SRadu Pirea (NXP OSS) static int tja1120_config_intr(struct phy_device *phydev) 1190425c8348SRadu Pirea (NXP OSS) { 1191425c8348SRadu Pirea (NXP OSS) int ret; 1192425c8348SRadu Pirea (NXP OSS) 1193425c8348SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1194425c8348SRadu Pirea (NXP OSS) ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1195425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_EN, 1196425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE); 1197425c8348SRadu Pirea (NXP OSS) else 1198425c8348SRadu Pirea (NXP OSS) ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1199425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_EN, 1200425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE); 1201425c8348SRadu Pirea (NXP OSS) if (ret) 1202425c8348SRadu Pirea (NXP OSS) return ret; 1203425c8348SRadu Pirea (NXP OSS) 1204425c8348SRadu Pirea (NXP OSS) return nxp_c45_config_intr(phydev); 1205425c8348SRadu Pirea (NXP OSS) } 1206425c8348SRadu Pirea (NXP OSS) 1207b2f0ca00SRadu Pirea (NXP OSS) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) 1208b2f0ca00SRadu Pirea (NXP OSS) { 12096c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 1210514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1211b2f0ca00SRadu Pirea (NXP OSS) irqreturn_t ret = IRQ_NONE; 1212514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts; 1213b2f0ca00SRadu Pirea (NXP OSS) int irq; 1214b2f0ca00SRadu Pirea (NXP OSS) 1215b2f0ca00SRadu Pirea (NXP OSS) irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS); 1216b2f0ca00SRadu Pirea (NXP OSS) if (irq & PHY_IRQ_LINK_EVENT) { 1217b2f0ca00SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK, 1218b2f0ca00SRadu Pirea (NXP OSS) PHY_IRQ_LINK_EVENT); 1219b2f0ca00SRadu Pirea (NXP OSS) phy_trigger_machine(phydev); 1220b2f0ca00SRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 1221b2f0ca00SRadu Pirea (NXP OSS) } 1222b2f0ca00SRadu Pirea (NXP OSS) 12236c0c85daSRadu Pirea (NXP OSS) irq = nxp_c45_read_reg_field(phydev, &data->regmap->irq_egr_ts_status); 12246c0c85daSRadu Pirea (NXP OSS) if (irq) { 1225bdb4c5b8SRadu Pirea (NXP OSS) /* If ack_ptp_irq is false, the IRQ bit is self-clear and will 1226bdb4c5b8SRadu Pirea (NXP OSS) * be cleared when the EGR TS FIFO is empty. Otherwise, the 1227bdb4c5b8SRadu Pirea (NXP OSS) * IRQ bit should be cleared before reading the timestamp, 1228bdb4c5b8SRadu Pirea (NXP OSS) */ 1229bdb4c5b8SRadu Pirea (NXP OSS) if (data->ack_ptp_irq) 1230bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 1231bdb4c5b8SRadu Pirea (NXP OSS) VEND1_PTP_IRQ_ACK, EGR_TS_IRQ); 1232bdb4c5b8SRadu Pirea (NXP OSS) while (data->get_egressts(priv, &hwts)) 1233514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts); 1234514def5dSRadu Pirea (NXP OSS) 1235514def5dSRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 1236514def5dSRadu Pirea (NXP OSS) } 1237514def5dSRadu Pirea (NXP OSS) 1238425c8348SRadu Pirea (NXP OSS) data->nmi_handler(phydev, &ret); 1239425c8348SRadu Pirea (NXP OSS) 1240b2f0ca00SRadu Pirea (NXP OSS) return ret; 1241b2f0ca00SRadu Pirea (NXP OSS) } 1242b2f0ca00SRadu Pirea (NXP OSS) 1243b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev) 1244b050f2f1SRadu Pirea (NXP OSS) { 1245b050f2f1SRadu Pirea (NXP OSS) int ret; 1246b050f2f1SRadu Pirea (NXP OSS) 1247b050f2f1SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 1248b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_RESET); 1249b050f2f1SRadu Pirea (NXP OSS) if (ret) 1250b050f2f1SRadu Pirea (NXP OSS) return ret; 1251b050f2f1SRadu Pirea (NXP OSS) 1252b050f2f1SRadu Pirea (NXP OSS) return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 1253b050f2f1SRadu Pirea (NXP OSS) VEND1_DEVICE_CONTROL, ret, 1254b050f2f1SRadu Pirea (NXP OSS) !(ret & DEVICE_CONTROL_RESET), 20000, 1255b050f2f1SRadu Pirea (NXP OSS) 240000, false); 1256b050f2f1SRadu Pirea (NXP OSS) } 1257b050f2f1SRadu Pirea (NXP OSS) 1258b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev) 1259b050f2f1SRadu Pirea (NXP OSS) { 12606c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); 12616c0c85daSRadu Pirea (NXP OSS) 1262*c552c110SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1263*c552c110SRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE); 12646c0c85daSRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, 1265b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE | CABLE_TEST_START); 1266b050f2f1SRadu Pirea (NXP OSS) } 1267b050f2f1SRadu Pirea (NXP OSS) 1268b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev, 1269b050f2f1SRadu Pirea (NXP OSS) bool *finished) 1270b050f2f1SRadu Pirea (NXP OSS) { 12716c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); 1272b050f2f1SRadu Pirea (NXP OSS) int ret; 1273b050f2f1SRadu Pirea (NXP OSS) u8 cable_test_result; 1274b050f2f1SRadu Pirea (NXP OSS) 12756c0c85daSRadu Pirea (NXP OSS) ret = nxp_c45_read_reg_field(phydev, ®map->cable_test_valid); 12766c0c85daSRadu Pirea (NXP OSS) if (!ret) { 1277b050f2f1SRadu Pirea (NXP OSS) *finished = false; 1278b050f2f1SRadu Pirea (NXP OSS) return 0; 1279b050f2f1SRadu Pirea (NXP OSS) } 1280b050f2f1SRadu Pirea (NXP OSS) 1281b050f2f1SRadu Pirea (NXP OSS) *finished = true; 12826c0c85daSRadu Pirea (NXP OSS) cable_test_result = nxp_c45_read_reg_field(phydev, 12836c0c85daSRadu Pirea (NXP OSS) ®map->cable_test_result); 1284b050f2f1SRadu Pirea (NXP OSS) 1285b050f2f1SRadu Pirea (NXP OSS) switch (cable_test_result) { 1286b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OK: 1287b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1288b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OK); 1289b050f2f1SRadu Pirea (NXP OSS) break; 1290b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_SHORTED: 1291b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1292b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT); 1293b050f2f1SRadu Pirea (NXP OSS) break; 1294b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OPEN: 1295b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1296b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OPEN); 1297b050f2f1SRadu Pirea (NXP OSS) break; 1298b050f2f1SRadu Pirea (NXP OSS) default: 1299b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1300b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC); 1301b050f2f1SRadu Pirea (NXP OSS) } 1302b050f2f1SRadu Pirea (NXP OSS) 13036c0c85daSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, 1304b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE); 1305*c552c110SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1306*c552c110SRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE); 1307b050f2f1SRadu Pirea (NXP OSS) 1308b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 1309b050f2f1SRadu Pirea (NXP OSS) } 1310b050f2f1SRadu Pirea (NXP OSS) 1311b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev) 1312b050f2f1SRadu Pirea (NXP OSS) { 1313b050f2f1SRadu Pirea (NXP OSS) int reg; 1314b050f2f1SRadu Pirea (NXP OSS) 1315b050f2f1SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY); 1316b050f2f1SRadu Pirea (NXP OSS) if (!(reg & SQI_VALID)) 1317b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1318b050f2f1SRadu Pirea (NXP OSS) 1319b050f2f1SRadu Pirea (NXP OSS) reg &= SQI_MASK; 1320b050f2f1SRadu Pirea (NXP OSS) 1321b050f2f1SRadu Pirea (NXP OSS) return reg; 1322b050f2f1SRadu Pirea (NXP OSS) } 1323b050f2f1SRadu Pirea (NXP OSS) 1324b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev) 1325b050f2f1SRadu Pirea (NXP OSS) { 1326b050f2f1SRadu Pirea (NXP OSS) return MAX_SQI; 1327b050f2f1SRadu Pirea (NXP OSS) } 1328b050f2f1SRadu Pirea (NXP OSS) 1329b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay) 1330b050f2f1SRadu Pirea (NXP OSS) { 1331b050f2f1SRadu Pirea (NXP OSS) if (delay < MIN_ID_PS) { 1332b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS); 1333b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1334b050f2f1SRadu Pirea (NXP OSS) } 1335b050f2f1SRadu Pirea (NXP OSS) 1336b050f2f1SRadu Pirea (NXP OSS) if (delay > MAX_ID_PS) { 1337b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS); 1338b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1339b050f2f1SRadu Pirea (NXP OSS) } 1340b050f2f1SRadu Pirea (NXP OSS) 1341b050f2f1SRadu Pirea (NXP OSS) return 0; 1342b050f2f1SRadu Pirea (NXP OSS) } 1343b050f2f1SRadu Pirea (NXP OSS) 13446c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_counters_enable(struct phy_device *phydev) 13456c0c85daSRadu Pirea (NXP OSS) { 13466c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 13476c0c85daSRadu Pirea (NXP OSS) 13486c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER, 13496c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 13506c0c85daSRadu Pirea (NXP OSS) 13516c0c85daSRadu Pirea (NXP OSS) data->counters_enable(phydev); 13526c0c85daSRadu Pirea (NXP OSS) } 13536c0c85daSRadu Pirea (NXP OSS) 13546c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_ptp_init(struct phy_device *phydev) 13556c0c85daSRadu Pirea (NXP OSS) { 13566c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 13576c0c85daSRadu Pirea (NXP OSS) 13586c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 13596c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_ptp_clk_period, 13606c0c85daSRadu Pirea (NXP OSS) data->ptp_clk_period); 13616c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(phydev, &data->regmap->ltc_lock_ctrl); 13626c0c85daSRadu Pirea (NXP OSS) 13636c0c85daSRadu Pirea (NXP OSS) data->ptp_init(phydev); 13646c0c85daSRadu Pirea (NXP OSS) } 13656c0c85daSRadu Pirea (NXP OSS) 1366b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw) 1367b050f2f1SRadu Pirea (NXP OSS) { 1368b050f2f1SRadu Pirea (NXP OSS) /* The delay in degree phase is 73.8 + phase_offset_raw * 0.9. 1369b050f2f1SRadu Pirea (NXP OSS) * To avoid floating point operations we'll multiply by 10 1370b050f2f1SRadu Pirea (NXP OSS) * and get 1 decimal point precision. 1371b050f2f1SRadu Pirea (NXP OSS) */ 1372b050f2f1SRadu Pirea (NXP OSS) phase_offset_raw *= 10; 13736b3a6310SRadu Pirea (NXP OSS) phase_offset_raw -= 738; 1374b050f2f1SRadu Pirea (NXP OSS) return div_u64(phase_offset_raw, 9); 1375b050f2f1SRadu Pirea (NXP OSS) } 1376b050f2f1SRadu Pirea (NXP OSS) 1377b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev) 1378b050f2f1SRadu Pirea (NXP OSS) { 1379b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE); 1380b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE); 1381b050f2f1SRadu Pirea (NXP OSS) } 1382b050f2f1SRadu Pirea (NXP OSS) 1383b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev) 1384b050f2f1SRadu Pirea (NXP OSS) { 1385b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1386b050f2f1SRadu Pirea (NXP OSS) u64 tx_delay = priv->tx_delay; 1387b050f2f1SRadu Pirea (NXP OSS) u64 rx_delay = priv->rx_delay; 1388b050f2f1SRadu Pirea (NXP OSS) u64 degree; 1389b050f2f1SRadu Pirea (NXP OSS) 1390b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1391b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 1392b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(tx_delay, PS_PER_DEGREE); 1393b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 1394b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 1395b050f2f1SRadu Pirea (NXP OSS) } else { 1396b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 1397b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 1398b050f2f1SRadu Pirea (NXP OSS) } 1399b050f2f1SRadu Pirea (NXP OSS) 1400b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1401b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 1402b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(rx_delay, PS_PER_DEGREE); 1403b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 1404b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 1405b050f2f1SRadu Pirea (NXP OSS) } else { 1406b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 1407b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 1408b050f2f1SRadu Pirea (NXP OSS) } 1409b050f2f1SRadu Pirea (NXP OSS) } 1410b050f2f1SRadu Pirea (NXP OSS) 1411b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev) 1412b050f2f1SRadu Pirea (NXP OSS) { 1413b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1414b050f2f1SRadu Pirea (NXP OSS) int ret; 1415b050f2f1SRadu Pirea (NXP OSS) 1416b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1417b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 1418b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 1419b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps", 1420b050f2f1SRadu Pirea (NXP OSS) &priv->tx_delay); 1421b050f2f1SRadu Pirea (NXP OSS) if (ret) 1422b050f2f1SRadu Pirea (NXP OSS) priv->tx_delay = DEFAULT_ID_PS; 1423b050f2f1SRadu Pirea (NXP OSS) 1424b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->tx_delay); 1425b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1426b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 1427b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps invalid value\n"); 1428b050f2f1SRadu Pirea (NXP OSS) return ret; 1429b050f2f1SRadu Pirea (NXP OSS) } 1430b050f2f1SRadu Pirea (NXP OSS) } 1431b050f2f1SRadu Pirea (NXP OSS) 1432b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1433b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 1434b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 1435b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps", 1436b050f2f1SRadu Pirea (NXP OSS) &priv->rx_delay); 1437b050f2f1SRadu Pirea (NXP OSS) if (ret) 1438b050f2f1SRadu Pirea (NXP OSS) priv->rx_delay = DEFAULT_ID_PS; 1439b050f2f1SRadu Pirea (NXP OSS) 1440b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->rx_delay); 1441b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1442b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 1443b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps invalid value\n"); 1444b050f2f1SRadu Pirea (NXP OSS) return ret; 1445b050f2f1SRadu Pirea (NXP OSS) } 1446b050f2f1SRadu Pirea (NXP OSS) } 1447b050f2f1SRadu Pirea (NXP OSS) 1448b050f2f1SRadu Pirea (NXP OSS) return 0; 1449b050f2f1SRadu Pirea (NXP OSS) } 1450b050f2f1SRadu Pirea (NXP OSS) 1451b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev) 1452b050f2f1SRadu Pirea (NXP OSS) { 1453b050f2f1SRadu Pirea (NXP OSS) int ret; 1454b050f2f1SRadu Pirea (NXP OSS) 1455b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES); 1456b050f2f1SRadu Pirea (NXP OSS) phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret); 1457b050f2f1SRadu Pirea (NXP OSS) 1458b050f2f1SRadu Pirea (NXP OSS) switch (phydev->interface) { 1459b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII: 1460b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ABILITY)) { 1461b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii mode not supported\n"); 1462b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1463b050f2f1SRadu Pirea (NXP OSS) } 1464b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1465b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 1466b050f2f1SRadu Pirea (NXP OSS) nxp_c45_disable_delays(phydev); 1467b050f2f1SRadu Pirea (NXP OSS) break; 1468b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_ID: 1469b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_TXID: 1470b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_RXID: 1471b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ID_ABILITY)) { 1472b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n"); 1473b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1474b050f2f1SRadu Pirea (NXP OSS) } 1475b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1476b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 1477b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_get_delays(phydev); 1478b050f2f1SRadu Pirea (NXP OSS) if (ret) 1479b050f2f1SRadu Pirea (NXP OSS) return ret; 1480b050f2f1SRadu Pirea (NXP OSS) 1481b050f2f1SRadu Pirea (NXP OSS) nxp_c45_set_delays(phydev); 1482b050f2f1SRadu Pirea (NXP OSS) break; 1483b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_MII: 1484b050f2f1SRadu Pirea (NXP OSS) if (!(ret & MII_ABILITY)) { 1485b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "mii mode not supported\n"); 1486b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1487b050f2f1SRadu Pirea (NXP OSS) } 1488b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1489b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII); 1490b050f2f1SRadu Pirea (NXP OSS) break; 1491b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_REVMII: 1492b050f2f1SRadu Pirea (NXP OSS) if (!(ret & REVMII_ABILITY)) { 1493b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rev-mii mode not supported\n"); 1494b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1495b050f2f1SRadu Pirea (NXP OSS) } 1496b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1497b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII | MII_BASIC_CONFIG_REV); 1498b050f2f1SRadu Pirea (NXP OSS) break; 1499b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RMII: 1500b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RMII_ABILITY)) { 1501b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rmii mode not supported\n"); 1502b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1503b050f2f1SRadu Pirea (NXP OSS) } 1504b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1505b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RMII); 1506b050f2f1SRadu Pirea (NXP OSS) break; 1507b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_SGMII: 1508b050f2f1SRadu Pirea (NXP OSS) if (!(ret & SGMII_ABILITY)) { 1509b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "sgmii mode not supported\n"); 1510b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1511b050f2f1SRadu Pirea (NXP OSS) } 1512b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1513b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_SGMII); 1514b050f2f1SRadu Pirea (NXP OSS) break; 1515b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_INTERNAL: 1516b050f2f1SRadu Pirea (NXP OSS) break; 1517b050f2f1SRadu Pirea (NXP OSS) default: 1518b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1519b050f2f1SRadu Pirea (NXP OSS) } 1520b050f2f1SRadu Pirea (NXP OSS) 1521b050f2f1SRadu Pirea (NXP OSS) return 0; 1522b050f2f1SRadu Pirea (NXP OSS) } 1523b050f2f1SRadu Pirea (NXP OSS) 1524b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev) 1525b050f2f1SRadu Pirea (NXP OSS) { 1526b050f2f1SRadu Pirea (NXP OSS) int ret; 1527b050f2f1SRadu Pirea (NXP OSS) 1528b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_config_enable(phydev); 1529b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1530b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "Failed to enable config\n"); 1531b050f2f1SRadu Pirea (NXP OSS) return ret; 1532b050f2f1SRadu Pirea (NXP OSS) } 1533b050f2f1SRadu Pirea (NXP OSS) 15340b5f0f29SVladimir Oltean /* Bug workaround for SJA1110 rev B: enable write access 15350b5f0f29SVladimir Oltean * to MDIO_MMD_PMAPMD 15360b5f0f29SVladimir Oltean */ 15370b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1); 15380b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2); 15390b5f0f29SVladimir Oltean 1540b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG, 1541b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_AUTO); 1542b050f2f1SRadu Pirea (NXP OSS) 1543b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_set_phy_mode(phydev); 1544b050f2f1SRadu Pirea (NXP OSS) if (ret) 1545b050f2f1SRadu Pirea (NXP OSS) return ret; 1546b050f2f1SRadu Pirea (NXP OSS) 1547b050f2f1SRadu Pirea (NXP OSS) phydev->autoneg = AUTONEG_DISABLE; 1548b050f2f1SRadu Pirea (NXP OSS) 15496c0c85daSRadu Pirea (NXP OSS) nxp_c45_counters_enable(phydev); 15506c0c85daSRadu Pirea (NXP OSS) nxp_c45_ptp_init(phydev); 1551514def5dSRadu Pirea (NXP OSS) 1552b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 1553b050f2f1SRadu Pirea (NXP OSS) } 1554b050f2f1SRadu Pirea (NXP OSS) 1555369da333SRadu Pirea (NXP OSS) static int nxp_c45_get_features(struct phy_device *phydev) 1556369da333SRadu Pirea (NXP OSS) { 1557369da333SRadu Pirea (NXP OSS) linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported); 1558369da333SRadu Pirea (NXP OSS) linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported); 1559369da333SRadu Pirea (NXP OSS) 1560369da333SRadu Pirea (NXP OSS) return genphy_c45_pma_read_abilities(phydev); 1561369da333SRadu Pirea (NXP OSS) } 1562369da333SRadu Pirea (NXP OSS) 1563b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev) 1564b050f2f1SRadu Pirea (NXP OSS) { 1565b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv; 1566514def5dSRadu Pirea (NXP OSS) int ptp_ability; 1567514def5dSRadu Pirea (NXP OSS) int ret = 0; 1568b050f2f1SRadu Pirea (NXP OSS) 1569b050f2f1SRadu Pirea (NXP OSS) priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 1570b050f2f1SRadu Pirea (NXP OSS) if (!priv) 1571b050f2f1SRadu Pirea (NXP OSS) return -ENOMEM; 1572b050f2f1SRadu Pirea (NXP OSS) 1573514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->tx_queue); 1574514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->rx_queue); 1575514def5dSRadu Pirea (NXP OSS) 1576514def5dSRadu Pirea (NXP OSS) priv->phydev = phydev; 1577514def5dSRadu Pirea (NXP OSS) 1578b050f2f1SRadu Pirea (NXP OSS) phydev->priv = priv; 1579b050f2f1SRadu Pirea (NXP OSS) 1580514def5dSRadu Pirea (NXP OSS) mutex_init(&priv->ptp_lock); 1581514def5dSRadu Pirea (NXP OSS) 1582514def5dSRadu Pirea (NXP OSS) ptp_ability = phy_read_mmd(phydev, MDIO_MMD_VEND1, 1583514def5dSRadu Pirea (NXP OSS) VEND1_PORT_ABILITIES); 1584514def5dSRadu Pirea (NXP OSS) ptp_ability = !!(ptp_ability & PTP_ABILITY); 1585514def5dSRadu Pirea (NXP OSS) if (!ptp_ability) { 1586565c6d8cSVladimir Oltean phydev_dbg(phydev, "the phy does not support PTP"); 1587514def5dSRadu Pirea (NXP OSS) goto no_ptp_support; 1588514def5dSRadu Pirea (NXP OSS) } 1589514def5dSRadu Pirea (NXP OSS) 1590514def5dSRadu Pirea (NXP OSS) if (IS_ENABLED(CONFIG_PTP_1588_CLOCK) && 1591514def5dSRadu Pirea (NXP OSS) IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) { 1592514def5dSRadu Pirea (NXP OSS) priv->mii_ts.rxtstamp = nxp_c45_rxtstamp; 1593514def5dSRadu Pirea (NXP OSS) priv->mii_ts.txtstamp = nxp_c45_txtstamp; 1594514def5dSRadu Pirea (NXP OSS) priv->mii_ts.hwtstamp = nxp_c45_hwtstamp; 1595514def5dSRadu Pirea (NXP OSS) priv->mii_ts.ts_info = nxp_c45_ts_info; 1596514def5dSRadu Pirea (NXP OSS) phydev->mii_ts = &priv->mii_ts; 1597514def5dSRadu Pirea (NXP OSS) ret = nxp_c45_init_ptp_clock(priv); 1598514def5dSRadu Pirea (NXP OSS) } else { 1599514def5dSRadu Pirea (NXP OSS) phydev_dbg(phydev, "PTP support not enabled even if the phy supports it"); 1600514def5dSRadu Pirea (NXP OSS) } 1601514def5dSRadu Pirea (NXP OSS) 1602514def5dSRadu Pirea (NXP OSS) no_ptp_support: 1603514def5dSRadu Pirea (NXP OSS) 1604514def5dSRadu Pirea (NXP OSS) return ret; 1605b050f2f1SRadu Pirea (NXP OSS) } 1606b050f2f1SRadu Pirea (NXP OSS) 1607a4506722SRadu Pirea (OSS) static void nxp_c45_remove(struct phy_device *phydev) 1608a4506722SRadu Pirea (OSS) { 1609a4506722SRadu Pirea (OSS) struct nxp_c45_phy *priv = phydev->priv; 1610a4506722SRadu Pirea (OSS) 1611a4506722SRadu Pirea (OSS) if (priv->ptp_clock) 1612a4506722SRadu Pirea (OSS) ptp_clock_unregister(priv->ptp_clock); 1613a4506722SRadu Pirea (OSS) 1614a4506722SRadu Pirea (OSS) skb_queue_purge(&priv->tx_queue); 1615a4506722SRadu Pirea (OSS) skb_queue_purge(&priv->rx_queue); 1616a4506722SRadu Pirea (OSS) } 1617a4506722SRadu Pirea (OSS) 16186c0c85daSRadu Pirea (NXP OSS) static void tja1103_counters_enable(struct phy_device *phydev) 16196c0c85daSRadu Pirea (NXP OSS) { 16206c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT, 16216c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 16226c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT, 16236c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 16246c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH, 16256c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 16266c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH, 16276c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 16286c0c85daSRadu Pirea (NXP OSS) } 16296c0c85daSRadu Pirea (NXP OSS) 16306c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_init(struct phy_device *phydev) 16316c0c85daSRadu Pirea (NXP OSS) { 16326c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL, 16336c0c85daSRadu Pirea (NXP OSS) TJA1103_RX_TS_INSRT_MODE2); 16346c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES, 16356c0c85daSRadu Pirea (NXP OSS) PTP_ENABLE); 16366c0c85daSRadu Pirea (NXP OSS) } 16376c0c85daSRadu Pirea (NXP OSS) 16386c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_enable(struct phy_device *phydev, bool enable) 16396c0c85daSRadu Pirea (NXP OSS) { 16406c0c85daSRadu Pirea (NXP OSS) if (enable) 16416c0c85daSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 16426c0c85daSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL, 16436c0c85daSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS); 16446c0c85daSRadu Pirea (NXP OSS) else 16456c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 16466c0c85daSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL, 16476c0c85daSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS); 16486c0c85daSRadu Pirea (NXP OSS) } 16496c0c85daSRadu Pirea (NXP OSS) 1650425c8348SRadu Pirea (NXP OSS) static void tja1103_nmi_handler(struct phy_device *phydev, 1651425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status) 1652425c8348SRadu Pirea (NXP OSS) { 1653425c8348SRadu Pirea (NXP OSS) int ret; 1654425c8348SRadu Pirea (NXP OSS) 1655425c8348SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, 1656425c8348SRadu Pirea (NXP OSS) VEND1_ALWAYS_ACCESSIBLE); 1657425c8348SRadu Pirea (NXP OSS) if (ret & FUSA_PASS) { 1658425c8348SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 1659425c8348SRadu Pirea (NXP OSS) VEND1_ALWAYS_ACCESSIBLE, 1660425c8348SRadu Pirea (NXP OSS) FUSA_PASS); 1661425c8348SRadu Pirea (NXP OSS) *irq_status = IRQ_HANDLED; 1662425c8348SRadu Pirea (NXP OSS) } 1663425c8348SRadu Pirea (NXP OSS) } 1664425c8348SRadu Pirea (NXP OSS) 16656c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1103_regmap = { 16666c0c85daSRadu Pirea (NXP OSS) .vend1_ptp_clk_period = 0x1104, 16676c0c85daSRadu Pirea (NXP OSS) .vend1_event_msg_filt = 0x1148, 16686c0c85daSRadu Pirea (NXP OSS) .pps_enable = 16696c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 3, 1), 16706c0c85daSRadu Pirea (NXP OSS) .pps_polarity = 16716c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 2, 1), 16726c0c85daSRadu Pirea (NXP OSS) .ltc_lock_ctrl = 16736c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1115, MDIO_MMD_VEND1, 0, 1), 16746c0c85daSRadu Pirea (NXP OSS) .ltc_read = 16756c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 2, 1), 16766c0c85daSRadu Pirea (NXP OSS) .ltc_write = 16776c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 0, 1), 16786c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_0 = 0x1106, 16796c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_1 = 0x1107, 16806c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_0 = 0x1108, 16816c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_1 = 0x1109, 16826c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_0 = 0x110A, 16836c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_1 = 0x110B, 16846c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_0 = 0x110C, 16856c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_1 = 0x110D, 16866c0c85daSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_0 = 0x110F, 16876c0c85daSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_1 = 0x1110, 16886c0c85daSRadu Pirea (NXP OSS) .irq_egr_ts_en = 16896c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1131, MDIO_MMD_VEND1, 0, 1), 16906c0c85daSRadu Pirea (NXP OSS) .irq_egr_ts_status = 16916c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1132, MDIO_MMD_VEND1, 0, 1), 16926c0c85daSRadu Pirea (NXP OSS) .domain_number = 16936c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 0, 8), 16946c0c85daSRadu Pirea (NXP OSS) .msg_type = 16956c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 8, 4), 16966c0c85daSRadu Pirea (NXP OSS) .sequence_id = 16976c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114F, MDIO_MMD_VEND1, 0, 16), 16986c0c85daSRadu Pirea (NXP OSS) .sec_1_0 = 16996c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 14, 2), 17006c0c85daSRadu Pirea (NXP OSS) .sec_4_2 = 17016c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 12, 3), 17026c0c85daSRadu Pirea (NXP OSS) .nsec_15_0 = 17036c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1150, MDIO_MMD_VEND1, 0, 16), 17046c0c85daSRadu Pirea (NXP OSS) .nsec_29_16 = 17056c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 0, 14), 17066c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_0 = 0x1121, 17076c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_1 = 0x1122, 17086c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_2 = 0x1123, 17096c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_3 = 0x1124, 17106c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_ctrl = 0x1126, 17116c0c85daSRadu Pirea (NXP OSS) .cable_test = 0x8330, 17126c0c85daSRadu Pirea (NXP OSS) .cable_test_valid = 17136c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 13, 1), 17146c0c85daSRadu Pirea (NXP OSS) .cable_test_result = 17156c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 0, 3), 17166c0c85daSRadu Pirea (NXP OSS) }; 17176c0c85daSRadu Pirea (NXP OSS) 17186c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1103_phy_data = { 17196c0c85daSRadu Pirea (NXP OSS) .regmap = &tja1103_regmap, 17206c0c85daSRadu Pirea (NXP OSS) .stats = tja1103_hw_stats, 17216c0c85daSRadu Pirea (NXP OSS) .n_stats = ARRAY_SIZE(tja1103_hw_stats), 17226c0c85daSRadu Pirea (NXP OSS) .ptp_clk_period = PTP_CLK_PERIOD_100BT1, 1723b0b2247dSRadu Pirea (NXP OSS) .ext_ts_both_edges = false, 1724bdb4c5b8SRadu Pirea (NXP OSS) .ack_ptp_irq = false, 17256c0c85daSRadu Pirea (NXP OSS) .counters_enable = tja1103_counters_enable, 1726bdb4c5b8SRadu Pirea (NXP OSS) .get_egressts = nxp_c45_get_hwtxts, 17276c0c85daSRadu Pirea (NXP OSS) .ptp_init = tja1103_ptp_init, 17286c0c85daSRadu Pirea (NXP OSS) .ptp_enable = tja1103_ptp_enable, 1729425c8348SRadu Pirea (NXP OSS) .nmi_handler = tja1103_nmi_handler, 17306c0c85daSRadu Pirea (NXP OSS) }; 17316c0c85daSRadu Pirea (NXP OSS) 1732f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_counters_enable(struct phy_device *phydev) 1733f1fe5dffSRadu Pirea (NXP OSS) { 1734f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_SYMBOL_ERROR_CNT_XTD, 1735f1fe5dffSRadu Pirea (NXP OSS) EXTENDED_CNT_EN); 1736f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_STATUS, 1737f1fe5dffSRadu Pirea (NXP OSS) MONITOR_RESET); 1738f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_CONFIG, 1739f1fe5dffSRadu Pirea (NXP OSS) ALL_FRAMES_CNT_EN | LOST_FRAMES_CNT_EN); 1740f1fe5dffSRadu Pirea (NXP OSS) } 1741f1fe5dffSRadu Pirea (NXP OSS) 1742f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_init(struct phy_device *phydev) 1743f1fe5dffSRadu Pirea (NXP OSS) { 1744f1fe5dffSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_RX_TS_INSRT_CTRL, 1745f1fe5dffSRadu Pirea (NXP OSS) TJA1120_RX_TS_INSRT_EN | TJA1120_TS_INSRT_MODE); 1746f1fe5dffSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_VEND1_EXT_TS_MODE, 1747f1fe5dffSRadu Pirea (NXP OSS) TJA1120_TS_INSRT_MODE); 1748f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONFIG, 1749f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1750f1fe5dffSRadu Pirea (NXP OSS) } 1751f1fe5dffSRadu Pirea (NXP OSS) 1752f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_enable(struct phy_device *phydev, bool enable) 1753f1fe5dffSRadu Pirea (NXP OSS) { 1754f1fe5dffSRadu Pirea (NXP OSS) if (enable) 1755f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1756f1fe5dffSRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, 1757f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1758f1fe5dffSRadu Pirea (NXP OSS) else 1759f1fe5dffSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1760f1fe5dffSRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, 1761f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1762f1fe5dffSRadu Pirea (NXP OSS) } 1763f1fe5dffSRadu Pirea (NXP OSS) 1764425c8348SRadu Pirea (NXP OSS) static void tja1120_nmi_handler(struct phy_device *phydev, 1765425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status) 1766425c8348SRadu Pirea (NXP OSS) { 1767425c8348SRadu Pirea (NXP OSS) int ret; 1768425c8348SRadu Pirea (NXP OSS) 1769425c8348SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, 1770425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_STATUS); 1771425c8348SRadu Pirea (NXP OSS) if (ret & TJA1120_DEV_BOOT_DONE) { 1772425c8348SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 1773425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_ACK, 1774425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE); 1775425c8348SRadu Pirea (NXP OSS) *irq_status = IRQ_HANDLED; 1776425c8348SRadu Pirea (NXP OSS) } 1777425c8348SRadu Pirea (NXP OSS) } 1778425c8348SRadu Pirea (NXP OSS) 1779f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1120_regmap = { 1780f1fe5dffSRadu Pirea (NXP OSS) .vend1_ptp_clk_period = 0x1020, 1781f1fe5dffSRadu Pirea (NXP OSS) .vend1_event_msg_filt = 0x9010, 1782f1fe5dffSRadu Pirea (NXP OSS) .pps_enable = 1783f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 4, 1), 1784f1fe5dffSRadu Pirea (NXP OSS) .pps_polarity = 1785f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 5, 1), 1786f1fe5dffSRadu Pirea (NXP OSS) .ltc_lock_ctrl = 1787f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 2, 1), 1788f1fe5dffSRadu Pirea (NXP OSS) .ltc_read = 1789f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 1, 1), 1790f1fe5dffSRadu Pirea (NXP OSS) .ltc_write = 1791f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 2, 1), 1792f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_0 = 0x1040, 1793f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_1 = 0x1041, 1794f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_0 = 0x1042, 1795f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_1 = 0x1043, 1796f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_0 = 0x1048, 1797f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_1 = 0x1049, 1798f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_0 = 0x104A, 1799f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_1 = 0x104B, 1800f1fe5dffSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_0 = 0x1030, 1801f1fe5dffSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_1 = 0x1031, 1802f1fe5dffSRadu Pirea (NXP OSS) .irq_egr_ts_en = 1803f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x900A, MDIO_MMD_VEND1, 1, 1), 1804f1fe5dffSRadu Pirea (NXP OSS) .irq_egr_ts_status = 1805f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x900C, MDIO_MMD_VEND1, 1, 1), 1806f1fe5dffSRadu Pirea (NXP OSS) .domain_number = 1807f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 8, 8), 1808f1fe5dffSRadu Pirea (NXP OSS) .msg_type = 1809f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 4, 4), 1810f1fe5dffSRadu Pirea (NXP OSS) .sequence_id = 1811f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9062, MDIO_MMD_VEND1, 0, 16), 1812f1fe5dffSRadu Pirea (NXP OSS) .sec_1_0 = 1813f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 0, 2), 1814f1fe5dffSRadu Pirea (NXP OSS) .sec_4_2 = 1815f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 2, 3), 1816f1fe5dffSRadu Pirea (NXP OSS) .nsec_15_0 = 1817f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9063, MDIO_MMD_VEND1, 0, 16), 1818f1fe5dffSRadu Pirea (NXP OSS) .nsec_29_16 = 1819f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9064, MDIO_MMD_VEND1, 0, 14), 1820f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_0 = 0x1071, 1821f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_1 = 0x1072, 1822f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_2 = 0x1073, 1823f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_3 = 0x1074, 1824f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_ctrl = 0x1075, 1825f1fe5dffSRadu Pirea (NXP OSS) .cable_test = 0x8360, 1826f1fe5dffSRadu Pirea (NXP OSS) .cable_test_valid = 1827f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 15, 1), 1828f1fe5dffSRadu Pirea (NXP OSS) .cable_test_result = 1829f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 0, 3), 1830f1fe5dffSRadu Pirea (NXP OSS) }; 1831f1fe5dffSRadu Pirea (NXP OSS) 1832f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1120_phy_data = { 1833f1fe5dffSRadu Pirea (NXP OSS) .regmap = &tja1120_regmap, 1834f1fe5dffSRadu Pirea (NXP OSS) .stats = tja1120_hw_stats, 1835f1fe5dffSRadu Pirea (NXP OSS) .n_stats = ARRAY_SIZE(tja1120_hw_stats), 1836f1fe5dffSRadu Pirea (NXP OSS) .ptp_clk_period = PTP_CLK_PERIOD_1000BT1, 1837b0b2247dSRadu Pirea (NXP OSS) .ext_ts_both_edges = true, 1838bdb4c5b8SRadu Pirea (NXP OSS) .ack_ptp_irq = true, 1839f1fe5dffSRadu Pirea (NXP OSS) .counters_enable = tja1120_counters_enable, 1840bdb4c5b8SRadu Pirea (NXP OSS) .get_egressts = tja1120_get_hwtxts, 1841f1fe5dffSRadu Pirea (NXP OSS) .ptp_init = tja1120_ptp_init, 1842f1fe5dffSRadu Pirea (NXP OSS) .ptp_enable = tja1120_ptp_enable, 1843425c8348SRadu Pirea (NXP OSS) .nmi_handler = tja1120_nmi_handler, 1844f1fe5dffSRadu Pirea (NXP OSS) }; 1845f1fe5dffSRadu Pirea (NXP OSS) 1846b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = { 1847b050f2f1SRadu Pirea (NXP OSS) { 1848b050f2f1SRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), 1849b050f2f1SRadu Pirea (NXP OSS) .name = "NXP C45 TJA1103", 1850369da333SRadu Pirea (NXP OSS) .get_features = nxp_c45_get_features, 18516c0c85daSRadu Pirea (NXP OSS) .driver_data = &tja1103_phy_data, 1852b050f2f1SRadu Pirea (NXP OSS) .probe = nxp_c45_probe, 1853b050f2f1SRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset, 1854ac0687e8SRadu Pirea (NXP OSS) .config_aneg = genphy_c45_config_aneg, 1855b050f2f1SRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init, 1856425c8348SRadu Pirea (NXP OSS) .config_intr = tja1103_config_intr, 1857b2f0ca00SRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt, 1858ac0687e8SRadu Pirea (NXP OSS) .read_status = genphy_c45_read_status, 1859b050f2f1SRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend, 1860b050f2f1SRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume, 1861b050f2f1SRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count, 1862b050f2f1SRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings, 1863b050f2f1SRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats, 1864b050f2f1SRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start, 1865b050f2f1SRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status, 1866b050f2f1SRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback, 1867b050f2f1SRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi, 1868b050f2f1SRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max, 1869a4506722SRadu Pirea (OSS) .remove = nxp_c45_remove, 1870b050f2f1SRadu Pirea (NXP OSS) }, 1871f1fe5dffSRadu Pirea (NXP OSS) { 1872f1fe5dffSRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120), 1873f1fe5dffSRadu Pirea (NXP OSS) .name = "NXP C45 TJA1120", 1874f1fe5dffSRadu Pirea (NXP OSS) .get_features = nxp_c45_get_features, 1875f1fe5dffSRadu Pirea (NXP OSS) .driver_data = &tja1120_phy_data, 1876f1fe5dffSRadu Pirea (NXP OSS) .probe = nxp_c45_probe, 1877f1fe5dffSRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset, 1878f1fe5dffSRadu Pirea (NXP OSS) .config_aneg = genphy_c45_config_aneg, 1879f1fe5dffSRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init, 1880425c8348SRadu Pirea (NXP OSS) .config_intr = tja1120_config_intr, 1881f1fe5dffSRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt, 1882f1fe5dffSRadu Pirea (NXP OSS) .read_status = genphy_c45_read_status, 1883f1fe5dffSRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend, 1884f1fe5dffSRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume, 1885f1fe5dffSRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count, 1886f1fe5dffSRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings, 1887f1fe5dffSRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats, 1888f1fe5dffSRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start, 1889f1fe5dffSRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status, 1890f1fe5dffSRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback, 1891f1fe5dffSRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi, 1892f1fe5dffSRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max, 1893f1fe5dffSRadu Pirea (NXP OSS) .remove = nxp_c45_remove, 1894f1fe5dffSRadu Pirea (NXP OSS) }, 1895b050f2f1SRadu Pirea (NXP OSS) }; 1896b050f2f1SRadu Pirea (NXP OSS) 1897b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver); 1898b050f2f1SRadu Pirea (NXP OSS) 1899b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = { 1900b050f2f1SRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) }, 1901f1fe5dffSRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120) }, 1902b050f2f1SRadu Pirea (NXP OSS) { /*sentinel*/ }, 1903b050f2f1SRadu Pirea (NXP OSS) }; 1904b050f2f1SRadu Pirea (NXP OSS) 1905b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl); 1906b050f2f1SRadu Pirea (NXP OSS) 1907b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>"); 1908b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver"); 1909b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2"); 1910