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) 32b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_ACK 0x80A0 33b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_EN 0x80A1 34b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_STATUS 0x80A2 35b2f0ca00SRadu Pirea (NXP OSS) #define PHY_IRQ_LINK_EVENT BIT(1) 36b2f0ca00SRadu Pirea (NXP OSS) 37b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONTROL 0x8100 38b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_EN BIT(14) 39b050f2f1SRadu Pirea (NXP OSS) #define PHY_START_OP BIT(0) 40b050f2f1SRadu Pirea (NXP OSS) 41b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONFIG 0x8108 42b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_AUTO BIT(0) 43b050f2f1SRadu Pirea (NXP OSS) 44b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SIGNAL_QUALITY 0x8320 45b050f2f1SRadu Pirea (NXP OSS) #define SQI_VALID BIT(14) 46b050f2f1SRadu Pirea (NXP OSS) #define SQI_MASK GENMASK(2, 0) 47b050f2f1SRadu Pirea (NXP OSS) #define MAX_SQI SQI_MASK 48b050f2f1SRadu Pirea (NXP OSS) 49b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_ENABLE BIT(15) 50b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_START BIT(14) 51b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OK 0x00 52b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_SHORTED 0x01 53b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OPEN 0x02 54b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_UNKNOWN 0x07 55b050f2f1SRadu Pirea (NXP OSS) 56b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_CONTROL 0x8040 57b050f2f1SRadu Pirea (NXP OSS) #define PORT_CONTROL_EN BIT(14) 58b050f2f1SRadu Pirea (NXP OSS) 59514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_ABILITIES 0x8046 60514def5dSRadu Pirea (NXP OSS) #define PTP_ABILITY BIT(3) 61514def5dSRadu Pirea (NXP OSS) 62b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_INFRA_CONTROL 0xAC00 63b050f2f1SRadu Pirea (NXP OSS) #define PORT_INFRA_CONTROL_EN BIT(14) 64b050f2f1SRadu Pirea (NXP OSS) 65b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RXID 0xAFCC 66b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TXID 0xAFCD 67b050f2f1SRadu Pirea (NXP OSS) #define ID_ENABLE BIT(15) 68b050f2f1SRadu Pirea (NXP OSS) 69b050f2f1SRadu Pirea (NXP OSS) #define VEND1_ABILITIES 0xAFC4 70b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ID_ABILITY BIT(15) 71b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ABILITY BIT(14) 72b050f2f1SRadu Pirea (NXP OSS) #define RMII_ABILITY BIT(10) 73b050f2f1SRadu Pirea (NXP OSS) #define REVMII_ABILITY BIT(9) 74b050f2f1SRadu Pirea (NXP OSS) #define MII_ABILITY BIT(8) 75b050f2f1SRadu Pirea (NXP OSS) #define SGMII_ABILITY BIT(0) 76b050f2f1SRadu Pirea (NXP OSS) 77b050f2f1SRadu Pirea (NXP OSS) #define VEND1_MII_BASIC_CONFIG 0xAFC6 788ba57205SRadu Pirea (OSS) #define MII_BASIC_CONFIG_REV BIT(4) 79b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_SGMII 0x9 80b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RGMII 0x7 81b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RMII 0x5 82b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_MII 0x4 83b050f2f1SRadu Pirea (NXP OSS) 84f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_CNT_XTD 0x8351 85f1fe5dffSRadu Pirea (NXP OSS) #define EXTENDED_CNT_EN BIT(15) 86f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_STATUS 0xAC80 87f1fe5dffSRadu Pirea (NXP OSS) #define MONITOR_RESET BIT(15) 88f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_CONFIG 0xAC86 89f1fe5dffSRadu Pirea (NXP OSS) #define LOST_FRAMES_CNT_EN BIT(9) 90f1fe5dffSRadu Pirea (NXP OSS) #define ALL_FRAMES_CNT_EN BIT(8) 91f1fe5dffSRadu Pirea (NXP OSS) 92b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_COUNTER 0x8350 93b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_DROP_COUNTER 0x8352 94b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_LOSSES_AND_FAILURES 0x8353 95b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_PREAMBLE_COUNT 0xAFCE 96b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_PREAMBLE_COUNT 0xAFCF 97b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_IPG_LENGTH 0xAFD0 98b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_IPG_LENGTH 0xAFD1 99b050f2f1SRadu Pirea (NXP OSS) #define COUNTER_EN BIT(15) 100b050f2f1SRadu Pirea (NXP OSS) 1017a71c8aaSRadu Pirea (NXP OSS) #define VEND1_PTP_CONFIG 0x1102 1027a71c8aaSRadu Pirea (NXP OSS) #define EXT_TRG_EDGE BIT(1) 1037a71c8aaSRadu Pirea (NXP OSS) 104*b0b2247dSRadu Pirea (NXP OSS) #define TJA1120_SYNC_TRIG_FILTER 0x1010 105*b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_RISE_TS BIT(3) 106*b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_FALLING_TS BIT(2) 107*b0b2247dSRadu Pirea (NXP OSS) 108514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_LD BIT(15) 109514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_DIR BIT(14) 110514def5dSRadu Pirea (NXP OSS) 111514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_TS_INSRT_CTRL 0x114D 1126c0c85daSRadu Pirea (NXP OSS) #define TJA1103_RX_TS_INSRT_MODE2 0x02 113514def5dSRadu Pirea (NXP OSS) 114f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_CTRL 0x9012 115f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_EN BIT(15) 116f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_TS_INSRT_MODE BIT(4) 117f1fe5dffSRadu Pirea (NXP OSS) 118514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_0 0x114E 119514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_CTRL 0x1154 120514def5dSRadu Pirea (NXP OSS) 121514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_TS_VALID BIT(15) 122514def5dSRadu Pirea (NXP OSS) 123514def5dSRadu Pirea (NXP OSS) #define RING_DONE BIT(0) 124514def5dSRadu Pirea (NXP OSS) 125514def5dSRadu Pirea (NXP OSS) #define TS_SEC_MASK GENMASK(1, 0) 126514def5dSRadu Pirea (NXP OSS) 127514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_ENABLES 0x8048 128514def5dSRadu Pirea (NXP OSS) #define PTP_ENABLE BIT(3) 129514def5dSRadu Pirea (NXP OSS) 130514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_PTP_CONTROL 0x9000 131514def5dSRadu Pirea (NXP OSS) #define PORT_PTP_CONTROL_BYPASS BIT(11) 132514def5dSRadu Pirea (NXP OSS) 133514def5dSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_100BT1 15ULL 134f1fe5dffSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_1000BT1 8ULL 135514def5dSRadu Pirea (NXP OSS) 136514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_ALL 0x0F 137514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_NONE 0x00 138514def5dSRadu Pirea (NXP OSS) 1397a71c8aaSRadu Pirea (NXP OSS) #define VEND1_GPIO_FUNC_CONFIG_BASE 0x2C40 1407a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_EN BIT(15) 1417a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_PTP BIT(6) 1427a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PTP_TRIGGER 0x01 1437a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PPS_OUT 0x12 1447a71c8aaSRadu Pirea (NXP OSS) #define GPIO_DISABLE 0 1457a71c8aaSRadu Pirea (NXP OSS) #define GPIO_PPS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \ 1467a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PPS_OUT) 1477a71c8aaSRadu Pirea (NXP OSS) #define GPIO_EXTTS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \ 1487a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PTP_TRIGGER) 1497a71c8aaSRadu Pirea (NXP OSS) 150b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS 8000U 151b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE div_u64(RGMII_PERIOD_PS, 360) 152b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS 1644U 153b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS 2260U 154b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS 2000U 155b050f2f1SRadu Pirea (NXP OSS) 1566c0c85daSRadu Pirea (NXP OSS) #define PPM_TO_SUBNS_INC(ppb, ptp_clk_period) div_u64(GENMASK_ULL(31, 0) * \ 1576c0c85daSRadu Pirea (NXP OSS) (ppb) * (ptp_clk_period), NSEC_PER_SEC) 158514def5dSRadu Pirea (NXP OSS) 159514def5dSRadu Pirea (NXP OSS) #define NXP_C45_SKB_CB(skb) ((struct nxp_c45_skb_cb *)(skb)->cb) 160514def5dSRadu Pirea (NXP OSS) 161514def5dSRadu Pirea (NXP OSS) struct nxp_c45_skb_cb { 162514def5dSRadu Pirea (NXP OSS) struct ptp_header *header; 163514def5dSRadu Pirea (NXP OSS) unsigned int type; 164514def5dSRadu Pirea (NXP OSS) }; 165514def5dSRadu Pirea (NXP OSS) 1666c0c85daSRadu Pirea (NXP OSS) #define NXP_C45_REG_FIELD(_reg, _devad, _offset, _size) \ 1676c0c85daSRadu Pirea (NXP OSS) ((struct nxp_c45_reg_field) { \ 1686c0c85daSRadu Pirea (NXP OSS) .reg = _reg, \ 1696c0c85daSRadu Pirea (NXP OSS) .devad = _devad, \ 1706c0c85daSRadu Pirea (NXP OSS) .offset = _offset, \ 1716c0c85daSRadu Pirea (NXP OSS) .size = _size, \ 1726c0c85daSRadu Pirea (NXP OSS) }) 1736c0c85daSRadu Pirea (NXP OSS) 1746c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field { 1756c0c85daSRadu Pirea (NXP OSS) u16 reg; 1766c0c85daSRadu Pirea (NXP OSS) u8 devad; 1776c0c85daSRadu Pirea (NXP OSS) u8 offset; 1786c0c85daSRadu Pirea (NXP OSS) u8 size; 1796c0c85daSRadu Pirea (NXP OSS) }; 1806c0c85daSRadu Pirea (NXP OSS) 181514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts { 182514def5dSRadu Pirea (NXP OSS) u32 nsec; 183514def5dSRadu Pirea (NXP OSS) u32 sec; 184514def5dSRadu Pirea (NXP OSS) u8 domain_number; 185514def5dSRadu Pirea (NXP OSS) u16 sequence_id; 186514def5dSRadu Pirea (NXP OSS) u8 msg_type; 187514def5dSRadu Pirea (NXP OSS) }; 188514def5dSRadu Pirea (NXP OSS) 1896c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap { 1906c0c85daSRadu Pirea (NXP OSS) /* PTP config regs. */ 1916c0c85daSRadu Pirea (NXP OSS) u16 vend1_ptp_clk_period; 1926c0c85daSRadu Pirea (NXP OSS) u16 vend1_event_msg_filt; 1936c0c85daSRadu Pirea (NXP OSS) 1946c0c85daSRadu Pirea (NXP OSS) /* LTC bits and regs. */ 1956c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_read; 1966c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_write; 1976c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_lock_ctrl; 1986c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_nsec_0; 1996c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_nsec_1; 2006c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_sec_0; 2016c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_sec_1; 2026c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_nsec_0; 2036c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_nsec_1; 2046c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_sec_0; 2056c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_sec_1; 2066c0c85daSRadu Pirea (NXP OSS) u16 vend1_rate_adj_subns_0; 2076c0c85daSRadu Pirea (NXP OSS) u16 vend1_rate_adj_subns_1; 2086c0c85daSRadu Pirea (NXP OSS) 2096c0c85daSRadu Pirea (NXP OSS) /* External trigger reg fields. */ 2106c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field irq_egr_ts_en; 2116c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field irq_egr_ts_status; 2126c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field domain_number; 2136c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field msg_type; 2146c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sequence_id; 2156c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sec_1_0; 2166c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sec_4_2; 2176c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field nsec_15_0; 2186c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field nsec_29_16; 2196c0c85daSRadu Pirea (NXP OSS) 2206c0c85daSRadu Pirea (NXP OSS) /* PPS and EXT Trigger bits and regs. */ 2216c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field pps_enable; 2226c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field pps_polarity; 2236c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_0; 2246c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_1; 2256c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_2; 2266c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_3; 2276c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_ctrl; 2286c0c85daSRadu Pirea (NXP OSS) 2296c0c85daSRadu Pirea (NXP OSS) /* Cable test reg fields. */ 2306c0c85daSRadu Pirea (NXP OSS) u16 cable_test; 2316c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field cable_test_valid; 2326c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field cable_test_result; 2336c0c85daSRadu Pirea (NXP OSS) }; 2346c0c85daSRadu Pirea (NXP OSS) 2356c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_stats { 2366c0c85daSRadu Pirea (NXP OSS) const char *name; 2376c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field counter; 2386c0c85daSRadu Pirea (NXP OSS) }; 2396c0c85daSRadu Pirea (NXP OSS) 2406c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data { 2416c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap; 2426c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_stats *stats; 2436c0c85daSRadu Pirea (NXP OSS) int n_stats; 2446c0c85daSRadu Pirea (NXP OSS) u8 ptp_clk_period; 245*b0b2247dSRadu Pirea (NXP OSS) bool ext_ts_both_edges; 2466c0c85daSRadu Pirea (NXP OSS) void (*counters_enable)(struct phy_device *phydev); 2476c0c85daSRadu Pirea (NXP OSS) void (*ptp_init)(struct phy_device *phydev); 2486c0c85daSRadu Pirea (NXP OSS) void (*ptp_enable)(struct phy_device *phydev, bool enable); 2496c0c85daSRadu Pirea (NXP OSS) }; 2506c0c85daSRadu Pirea (NXP OSS) 251b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy { 2526c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data; 253514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev; 254514def5dSRadu Pirea (NXP OSS) struct mii_timestamper mii_ts; 255514def5dSRadu Pirea (NXP OSS) struct ptp_clock *ptp_clock; 256514def5dSRadu Pirea (NXP OSS) struct ptp_clock_info caps; 257514def5dSRadu Pirea (NXP OSS) struct sk_buff_head tx_queue; 258514def5dSRadu Pirea (NXP OSS) struct sk_buff_head rx_queue; 259514def5dSRadu Pirea (NXP OSS) /* used to access the PTP registers atomic */ 260514def5dSRadu Pirea (NXP OSS) struct mutex ptp_lock; 261514def5dSRadu Pirea (NXP OSS) int hwts_tx; 262514def5dSRadu Pirea (NXP OSS) int hwts_rx; 263b050f2f1SRadu Pirea (NXP OSS) u32 tx_delay; 264b050f2f1SRadu Pirea (NXP OSS) u32 rx_delay; 2657a71c8aaSRadu Pirea (NXP OSS) struct timespec64 extts_ts; 2667a71c8aaSRadu Pirea (NXP OSS) int extts_index; 2677a71c8aaSRadu Pirea (NXP OSS) bool extts; 268b050f2f1SRadu Pirea (NXP OSS) }; 269b050f2f1SRadu Pirea (NXP OSS) 2706c0c85daSRadu Pirea (NXP OSS) static const 2716c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data *nxp_c45_get_data(struct phy_device *phydev) 2726c0c85daSRadu Pirea (NXP OSS) { 2736c0c85daSRadu Pirea (NXP OSS) return phydev->drv->driver_data; 2746c0c85daSRadu Pirea (NXP OSS) } 2756c0c85daSRadu Pirea (NXP OSS) 2766c0c85daSRadu Pirea (NXP OSS) static const 2776c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap *nxp_c45_get_regmap(struct phy_device *phydev) 2786c0c85daSRadu Pirea (NXP OSS) { 2796c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 2806c0c85daSRadu Pirea (NXP OSS) 2816c0c85daSRadu Pirea (NXP OSS) return phy_data->regmap; 2826c0c85daSRadu Pirea (NXP OSS) } 2836c0c85daSRadu Pirea (NXP OSS) 2846c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_read_reg_field(struct phy_device *phydev, 2856c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 2866c0c85daSRadu Pirea (NXP OSS) { 287b050f2f1SRadu Pirea (NXP OSS) u16 mask; 2886c0c85daSRadu Pirea (NXP OSS) int ret; 2896c0c85daSRadu Pirea (NXP OSS) 2906c0c85daSRadu Pirea (NXP OSS) if (reg_field->size == 0) { 2916c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to read a reg field of size 0.\n"); 2926c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 2936c0c85daSRadu Pirea (NXP OSS) } 2946c0c85daSRadu Pirea (NXP OSS) 2956c0c85daSRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, reg_field->devad, reg_field->reg); 2966c0c85daSRadu Pirea (NXP OSS) if (ret < 0) 2976c0c85daSRadu Pirea (NXP OSS) return ret; 2986c0c85daSRadu Pirea (NXP OSS) 2996c0c85daSRadu Pirea (NXP OSS) mask = reg_field->size == 1 ? BIT(reg_field->offset) : 3006c0c85daSRadu Pirea (NXP OSS) GENMASK(reg_field->offset + reg_field->size - 1, 3016c0c85daSRadu Pirea (NXP OSS) reg_field->offset); 3026c0c85daSRadu Pirea (NXP OSS) ret &= mask; 3036c0c85daSRadu Pirea (NXP OSS) ret >>= reg_field->offset; 3046c0c85daSRadu Pirea (NXP OSS) 3056c0c85daSRadu Pirea (NXP OSS) return ret; 3066c0c85daSRadu Pirea (NXP OSS) } 3076c0c85daSRadu Pirea (NXP OSS) 3086c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_write_reg_field(struct phy_device *phydev, 3096c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field, 3106c0c85daSRadu Pirea (NXP OSS) u16 val) 3116c0c85daSRadu Pirea (NXP OSS) { 3126c0c85daSRadu Pirea (NXP OSS) u16 mask; 3136c0c85daSRadu Pirea (NXP OSS) u16 set; 3146c0c85daSRadu Pirea (NXP OSS) 3156c0c85daSRadu Pirea (NXP OSS) if (reg_field->size == 0) { 3166c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to write a reg field of size 0.\n"); 3176c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3186c0c85daSRadu Pirea (NXP OSS) } 3196c0c85daSRadu Pirea (NXP OSS) 3206c0c85daSRadu Pirea (NXP OSS) mask = reg_field->size == 1 ? BIT(reg_field->offset) : 3216c0c85daSRadu Pirea (NXP OSS) GENMASK(reg_field->offset + reg_field->size - 1, 3226c0c85daSRadu Pirea (NXP OSS) reg_field->offset); 3236c0c85daSRadu Pirea (NXP OSS) set = val << reg_field->offset; 3246c0c85daSRadu Pirea (NXP OSS) 3256c0c85daSRadu Pirea (NXP OSS) return phy_modify_mmd_changed(phydev, reg_field->devad, 3266c0c85daSRadu Pirea (NXP OSS) reg_field->reg, mask, set); 3276c0c85daSRadu Pirea (NXP OSS) } 3286c0c85daSRadu Pirea (NXP OSS) 3296c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_set_reg_field(struct phy_device *phydev, 3306c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 3316c0c85daSRadu Pirea (NXP OSS) { 3326c0c85daSRadu Pirea (NXP OSS) if (reg_field->size != 1) { 3336c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to set a reg field of size different than 1.\n"); 3346c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3356c0c85daSRadu Pirea (NXP OSS) } 3366c0c85daSRadu Pirea (NXP OSS) 3376c0c85daSRadu Pirea (NXP OSS) return nxp_c45_write_reg_field(phydev, reg_field, 1); 3386c0c85daSRadu Pirea (NXP OSS) } 3396c0c85daSRadu Pirea (NXP OSS) 3406c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_clear_reg_field(struct phy_device *phydev, 3416c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field) 3426c0c85daSRadu Pirea (NXP OSS) { 3436c0c85daSRadu Pirea (NXP OSS) if (reg_field->size != 1) { 3446c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to set a reg field of size different than 1.\n"); 3456c0c85daSRadu Pirea (NXP OSS) return -EINVAL; 3466c0c85daSRadu Pirea (NXP OSS) } 3476c0c85daSRadu Pirea (NXP OSS) 3486c0c85daSRadu Pirea (NXP OSS) return nxp_c45_write_reg_field(phydev, reg_field, 0); 3496c0c85daSRadu Pirea (NXP OSS) } 350b050f2f1SRadu Pirea (NXP OSS) 351514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_poll_txts(struct phy_device *phydev) 352514def5dSRadu Pirea (NXP OSS) { 353514def5dSRadu Pirea (NXP OSS) return phydev->irq <= 0; 354514def5dSRadu Pirea (NXP OSS) } 355514def5dSRadu Pirea (NXP OSS) 356514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, 357514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts, 358514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts) 359514def5dSRadu Pirea (NXP OSS) { 360514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 3616c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 362514def5dSRadu Pirea (NXP OSS) 3636c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->ltc_read); 364514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3656c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_nsec_0); 366514def5dSRadu Pirea (NXP OSS) ts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3676c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_nsec_1) << 16; 368514def5dSRadu Pirea (NXP OSS) ts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3696c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_sec_0); 370514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3716c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_sec_1) << 16; 372514def5dSRadu Pirea (NXP OSS) 373514def5dSRadu Pirea (NXP OSS) return 0; 374514def5dSRadu Pirea (NXP OSS) } 375514def5dSRadu Pirea (NXP OSS) 376514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, 377514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts, 378514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts) 379514def5dSRadu Pirea (NXP OSS) { 380514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 381514def5dSRadu Pirea (NXP OSS) 382514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 383514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, ts, sts); 384514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 385514def5dSRadu Pirea (NXP OSS) 386514def5dSRadu Pirea (NXP OSS) return 0; 387514def5dSRadu Pirea (NXP OSS) } 388514def5dSRadu Pirea (NXP OSS) 389514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, 390514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts) 391514def5dSRadu Pirea (NXP OSS) { 392514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 3936c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 394514def5dSRadu Pirea (NXP OSS) 3956c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_0, 396514def5dSRadu Pirea (NXP OSS) ts->tv_nsec); 3976c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_1, 398514def5dSRadu Pirea (NXP OSS) ts->tv_nsec >> 16); 3996c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_0, 400514def5dSRadu Pirea (NXP OSS) ts->tv_sec); 4016c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_1, 402514def5dSRadu Pirea (NXP OSS) ts->tv_sec >> 16); 4036c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->ltc_write); 404514def5dSRadu Pirea (NXP OSS) 405514def5dSRadu Pirea (NXP OSS) return 0; 406514def5dSRadu Pirea (NXP OSS) } 407514def5dSRadu Pirea (NXP OSS) 408514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, 409514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts) 410514def5dSRadu Pirea (NXP OSS) { 411514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 412514def5dSRadu Pirea (NXP OSS) 413514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 414514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, ts); 415514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 416514def5dSRadu Pirea (NXP OSS) 417514def5dSRadu Pirea (NXP OSS) return 0; 418514def5dSRadu Pirea (NXP OSS) } 419514def5dSRadu Pirea (NXP OSS) 420514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 421514def5dSRadu Pirea (NXP OSS) { 422514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 4236c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); 4246c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = data->regmap; 425514def5dSRadu Pirea (NXP OSS) s32 ppb = scaled_ppm_to_ppb(scaled_ppm); 426514def5dSRadu Pirea (NXP OSS) u64 subns_inc_val; 427514def5dSRadu Pirea (NXP OSS) bool inc; 428514def5dSRadu Pirea (NXP OSS) 429514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 430514def5dSRadu Pirea (NXP OSS) inc = ppb >= 0; 431514def5dSRadu Pirea (NXP OSS) ppb = abs(ppb); 432514def5dSRadu Pirea (NXP OSS) 4336c0c85daSRadu Pirea (NXP OSS) subns_inc_val = PPM_TO_SUBNS_INC(ppb, data->ptp_clk_period); 434514def5dSRadu Pirea (NXP OSS) 4356c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 4366c0c85daSRadu Pirea (NXP OSS) regmap->vend1_rate_adj_subns_0, 437514def5dSRadu Pirea (NXP OSS) subns_inc_val); 438514def5dSRadu Pirea (NXP OSS) subns_inc_val >>= 16; 439514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_LD; 440514def5dSRadu Pirea (NXP OSS) if (inc) 441514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_DIR; 442514def5dSRadu Pirea (NXP OSS) 4436c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 4446c0c85daSRadu Pirea (NXP OSS) regmap->vend1_rate_adj_subns_1, 445514def5dSRadu Pirea (NXP OSS) subns_inc_val); 446514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 447514def5dSRadu Pirea (NXP OSS) 448514def5dSRadu Pirea (NXP OSS) return 0; 449514def5dSRadu Pirea (NXP OSS) } 450514def5dSRadu Pirea (NXP OSS) 451514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) 452514def5dSRadu Pirea (NXP OSS) { 453514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 454514def5dSRadu Pirea (NXP OSS) struct timespec64 now, then; 455514def5dSRadu Pirea (NXP OSS) 456514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 457514def5dSRadu Pirea (NXP OSS) then = ns_to_timespec64(delta); 458514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, &now, NULL); 459514def5dSRadu Pirea (NXP OSS) now = timespec64_add(now, then); 460514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, &now); 461514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 462514def5dSRadu Pirea (NXP OSS) 463514def5dSRadu Pirea (NXP OSS) return 0; 464514def5dSRadu Pirea (NXP OSS) } 465514def5dSRadu Pirea (NXP OSS) 466514def5dSRadu Pirea (NXP OSS) static void nxp_c45_reconstruct_ts(struct timespec64 *ts, 467514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 468514def5dSRadu Pirea (NXP OSS) { 469514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = hwts->nsec; 470514def5dSRadu Pirea (NXP OSS) if ((ts->tv_sec & TS_SEC_MASK) < (hwts->sec & TS_SEC_MASK)) 471661fef56SVladimir Oltean ts->tv_sec -= TS_SEC_MASK + 1; 472514def5dSRadu Pirea (NXP OSS) ts->tv_sec &= ~TS_SEC_MASK; 473514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= hwts->sec & TS_SEC_MASK; 474514def5dSRadu Pirea (NXP OSS) } 475514def5dSRadu Pirea (NXP OSS) 476514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_match_ts(struct ptp_header *header, 477514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts, 478514def5dSRadu Pirea (NXP OSS) unsigned int type) 479514def5dSRadu Pirea (NXP OSS) { 480514def5dSRadu Pirea (NXP OSS) return ntohs(header->sequence_id) == hwts->sequence_id && 481514def5dSRadu Pirea (NXP OSS) ptp_get_msgtype(header, type) == hwts->msg_type && 482514def5dSRadu Pirea (NXP OSS) header->domain_number == hwts->domain_number; 483514def5dSRadu Pirea (NXP OSS) } 484514def5dSRadu Pirea (NXP OSS) 4857a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_get_extts(struct nxp_c45_phy *priv, 4867a71c8aaSRadu Pirea (NXP OSS) struct timespec64 *extts) 4877a71c8aaSRadu Pirea (NXP OSS) { 4886c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 4896c0c85daSRadu Pirea (NXP OSS) 4907a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 4916c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_0); 4927a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 4936c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_1) << 16; 4947a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 4956c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_2); 4967a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 4976c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_3) << 16; 4986c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, 4996c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_ctrl, RING_DONE); 5007a71c8aaSRadu Pirea (NXP OSS) } 5017a71c8aaSRadu Pirea (NXP OSS) 502514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, 503514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 504514def5dSRadu Pirea (NXP OSS) { 5056c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 5066c0c85daSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 507514def5dSRadu Pirea (NXP OSS) bool valid; 508514def5dSRadu Pirea (NXP OSS) u16 reg; 509514def5dSRadu Pirea (NXP OSS) 510514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 511514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL, 512514def5dSRadu Pirea (NXP OSS) RING_DONE); 513514def5dSRadu Pirea (NXP OSS) reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0); 514514def5dSRadu Pirea (NXP OSS) valid = !!(reg & RING_DATA_0_TS_VALID); 515514def5dSRadu Pirea (NXP OSS) if (!valid) 516514def5dSRadu Pirea (NXP OSS) goto nxp_c45_get_hwtxts_out; 517514def5dSRadu Pirea (NXP OSS) 5186c0c85daSRadu Pirea (NXP OSS) hwts->domain_number = 5196c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->domain_number); 5206c0c85daSRadu Pirea (NXP OSS) hwts->msg_type = 5216c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->msg_type); 5226c0c85daSRadu Pirea (NXP OSS) hwts->sequence_id = 5236c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->sequence_id); 5246c0c85daSRadu Pirea (NXP OSS) hwts->nsec = 5256c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->nsec_15_0); 5266c0c85daSRadu Pirea (NXP OSS) hwts->nsec |= 5276c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->nsec_29_16) << 16; 5286c0c85daSRadu Pirea (NXP OSS) hwts->sec = nxp_c45_read_reg_field(phydev, ®map->sec_1_0); 5296c0c85daSRadu Pirea (NXP OSS) hwts->sec |= nxp_c45_read_reg_field(phydev, ®map->sec_4_2) << 2; 530514def5dSRadu Pirea (NXP OSS) 531514def5dSRadu Pirea (NXP OSS) nxp_c45_get_hwtxts_out: 532514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 533514def5dSRadu Pirea (NXP OSS) return valid; 534514def5dSRadu Pirea (NXP OSS) } 535514def5dSRadu Pirea (NXP OSS) 536514def5dSRadu Pirea (NXP OSS) static void nxp_c45_process_txts(struct nxp_c45_phy *priv, 537514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *txts) 538514def5dSRadu Pirea (NXP OSS) { 539514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, *tmp, *skb_match = NULL; 540514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps shhwtstamps; 541514def5dSRadu Pirea (NXP OSS) struct timespec64 ts; 542514def5dSRadu Pirea (NXP OSS) unsigned long flags; 543514def5dSRadu Pirea (NXP OSS) bool ts_match; 544514def5dSRadu Pirea (NXP OSS) s64 ts_ns; 545514def5dSRadu Pirea (NXP OSS) 546514def5dSRadu Pirea (NXP OSS) spin_lock_irqsave(&priv->tx_queue.lock, flags); 547514def5dSRadu Pirea (NXP OSS) skb_queue_walk_safe(&priv->tx_queue, skb, tmp) { 548514def5dSRadu Pirea (NXP OSS) ts_match = nxp_c45_match_ts(NXP_C45_SKB_CB(skb)->header, txts, 549514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type); 550514def5dSRadu Pirea (NXP OSS) if (!ts_match) 551514def5dSRadu Pirea (NXP OSS) continue; 552514def5dSRadu Pirea (NXP OSS) skb_match = skb; 553514def5dSRadu Pirea (NXP OSS) __skb_unlink(skb, &priv->tx_queue); 554514def5dSRadu Pirea (NXP OSS) break; 555514def5dSRadu Pirea (NXP OSS) } 556514def5dSRadu Pirea (NXP OSS) spin_unlock_irqrestore(&priv->tx_queue.lock, flags); 557514def5dSRadu Pirea (NXP OSS) 558514def5dSRadu Pirea (NXP OSS) if (skb_match) { 559514def5dSRadu Pirea (NXP OSS) nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL); 560514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, txts); 561514def5dSRadu Pirea (NXP OSS) memset(&shhwtstamps, 0, sizeof(shhwtstamps)); 562514def5dSRadu Pirea (NXP OSS) ts_ns = timespec64_to_ns(&ts); 563514def5dSRadu Pirea (NXP OSS) shhwtstamps.hwtstamp = ns_to_ktime(ts_ns); 564514def5dSRadu Pirea (NXP OSS) skb_complete_tx_timestamp(skb_match, &shhwtstamps); 565514def5dSRadu Pirea (NXP OSS) } else { 566514def5dSRadu Pirea (NXP OSS) phydev_warn(priv->phydev, 567514def5dSRadu Pirea (NXP OSS) "the tx timestamp doesn't match with any skb\n"); 568514def5dSRadu Pirea (NXP OSS) } 569514def5dSRadu Pirea (NXP OSS) } 570514def5dSRadu Pirea (NXP OSS) 571514def5dSRadu Pirea (NXP OSS) static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp) 572514def5dSRadu Pirea (NXP OSS) { 573514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 574514def5dSRadu Pirea (NXP OSS) bool poll_txts = nxp_c45_poll_txts(priv->phydev); 575514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps *shhwtstamps_rx; 5767a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_event event; 577514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts; 578514def5dSRadu Pirea (NXP OSS) bool reschedule = false; 579514def5dSRadu Pirea (NXP OSS) struct timespec64 ts; 580514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb; 581514def5dSRadu Pirea (NXP OSS) bool txts_valid; 582514def5dSRadu Pirea (NXP OSS) u32 ts_raw; 583514def5dSRadu Pirea (NXP OSS) 584514def5dSRadu Pirea (NXP OSS) while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) { 585514def5dSRadu Pirea (NXP OSS) txts_valid = nxp_c45_get_hwtxts(priv, &hwts); 586514def5dSRadu Pirea (NXP OSS) if (unlikely(!txts_valid)) { 587514def5dSRadu Pirea (NXP OSS) /* Still more skbs in the queue */ 588514def5dSRadu Pirea (NXP OSS) reschedule = true; 589514def5dSRadu Pirea (NXP OSS) break; 590514def5dSRadu Pirea (NXP OSS) } 591514def5dSRadu Pirea (NXP OSS) 592514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts); 593514def5dSRadu Pirea (NXP OSS) } 594514def5dSRadu Pirea (NXP OSS) 595514def5dSRadu Pirea (NXP OSS) while ((skb = skb_dequeue(&priv->rx_queue)) != NULL) { 596109258edSVladimir Oltean nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL); 597514def5dSRadu Pirea (NXP OSS) ts_raw = __be32_to_cpu(NXP_C45_SKB_CB(skb)->header->reserved2); 598514def5dSRadu Pirea (NXP OSS) hwts.sec = ts_raw >> 30; 599514def5dSRadu Pirea (NXP OSS) hwts.nsec = ts_raw & GENMASK(29, 0); 600514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, &hwts); 601514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx = skb_hwtstamps(skb); 602514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx->hwtstamp = ns_to_ktime(timespec64_to_ns(&ts)); 603514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header->reserved2 = 0; 604a3d73e15SSebastian Andrzej Siewior netif_rx(skb); 605514def5dSRadu Pirea (NXP OSS) } 606514def5dSRadu Pirea (NXP OSS) 6077a71c8aaSRadu Pirea (NXP OSS) if (priv->extts) { 6087a71c8aaSRadu Pirea (NXP OSS) nxp_c45_get_extts(priv, &ts); 6097a71c8aaSRadu Pirea (NXP OSS) if (timespec64_compare(&ts, &priv->extts_ts) != 0) { 6107a71c8aaSRadu Pirea (NXP OSS) priv->extts_ts = ts; 6117a71c8aaSRadu Pirea (NXP OSS) event.index = priv->extts_index; 6127a71c8aaSRadu Pirea (NXP OSS) event.type = PTP_CLOCK_EXTTS; 6137a71c8aaSRadu Pirea (NXP OSS) event.timestamp = ns_to_ktime(timespec64_to_ns(&ts)); 6147a71c8aaSRadu Pirea (NXP OSS) ptp_clock_event(priv->ptp_clock, &event); 6157a71c8aaSRadu Pirea (NXP OSS) } 6167a71c8aaSRadu Pirea (NXP OSS) reschedule = true; 6177a71c8aaSRadu Pirea (NXP OSS) } 6187a71c8aaSRadu Pirea (NXP OSS) 619514def5dSRadu Pirea (NXP OSS) return reschedule ? 1 : -1; 620514def5dSRadu Pirea (NXP OSS) } 621514def5dSRadu Pirea (NXP OSS) 6227a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_gpio_config(struct nxp_c45_phy *priv, 6237a71c8aaSRadu Pirea (NXP OSS) int pin, u16 pin_cfg) 6247a71c8aaSRadu Pirea (NXP OSS) { 6257a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 6267a71c8aaSRadu Pirea (NXP OSS) 6277a71c8aaSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 6287a71c8aaSRadu Pirea (NXP OSS) VEND1_GPIO_FUNC_CONFIG_BASE + pin, pin_cfg); 6297a71c8aaSRadu Pirea (NXP OSS) } 6307a71c8aaSRadu Pirea (NXP OSS) 6317a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_perout_enable(struct nxp_c45_phy *priv, 6327a71c8aaSRadu Pirea (NXP OSS) struct ptp_perout_request *perout, int on) 6337a71c8aaSRadu Pirea (NXP OSS) { 6346c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev); 6357a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 6367a71c8aaSRadu Pirea (NXP OSS) int pin; 6377a71c8aaSRadu Pirea (NXP OSS) 6387a71c8aaSRadu Pirea (NXP OSS) if (perout->flags & ~PTP_PEROUT_PHASE) 6397a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 6407a71c8aaSRadu Pirea (NXP OSS) 6417a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_PEROUT, perout->index); 6427a71c8aaSRadu Pirea (NXP OSS) if (pin < 0) 6437a71c8aaSRadu Pirea (NXP OSS) return pin; 6447a71c8aaSRadu Pirea (NXP OSS) 6457a71c8aaSRadu Pirea (NXP OSS) if (!on) { 6466c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 6476c0c85daSRadu Pirea (NXP OSS) ®map->pps_enable); 6486c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 6496c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 6507a71c8aaSRadu Pirea (NXP OSS) 6517a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); 6527a71c8aaSRadu Pirea (NXP OSS) 6537a71c8aaSRadu Pirea (NXP OSS) return 0; 6547a71c8aaSRadu Pirea (NXP OSS) } 6557a71c8aaSRadu Pirea (NXP OSS) 6567a71c8aaSRadu Pirea (NXP OSS) /* The PPS signal is fixed to 1 second and is always generated when the 6577a71c8aaSRadu Pirea (NXP OSS) * seconds counter is incremented. The start time is not configurable. 6587a71c8aaSRadu Pirea (NXP OSS) * If the clock is adjusted, the PPS signal is automatically readjusted. 6597a71c8aaSRadu Pirea (NXP OSS) */ 6607a71c8aaSRadu Pirea (NXP OSS) if (perout->period.sec != 1 || perout->period.nsec != 0) { 6617a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The period can be set only to 1 second."); 6627a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 6637a71c8aaSRadu Pirea (NXP OSS) } 6647a71c8aaSRadu Pirea (NXP OSS) 6657a71c8aaSRadu Pirea (NXP OSS) if (!(perout->flags & PTP_PEROUT_PHASE)) { 6667a71c8aaSRadu Pirea (NXP OSS) if (perout->start.sec != 0 || perout->start.nsec != 0) { 6677a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The start time is not configurable. Should be set to 0 seconds and 0 nanoseconds."); 6687a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 6697a71c8aaSRadu Pirea (NXP OSS) } 6707a71c8aaSRadu Pirea (NXP OSS) } else { 6717a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec != 0 && 6727a71c8aaSRadu Pirea (NXP OSS) perout->phase.nsec != (NSEC_PER_SEC >> 1)) { 6737a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The phase can be set only to 0 or 500000000 nanoseconds."); 6747a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 6757a71c8aaSRadu Pirea (NXP OSS) } 6767a71c8aaSRadu Pirea (NXP OSS) 6777a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec == 0) 6786c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev, 6796c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 6807a71c8aaSRadu Pirea (NXP OSS) else 6816c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, 6826c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity); 6837a71c8aaSRadu Pirea (NXP OSS) } 6847a71c8aaSRadu Pirea (NXP OSS) 6857a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_PPS_OUT_CFG); 6867a71c8aaSRadu Pirea (NXP OSS) 6876c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->pps_enable); 6887a71c8aaSRadu Pirea (NXP OSS) 6897a71c8aaSRadu Pirea (NXP OSS) return 0; 6907a71c8aaSRadu Pirea (NXP OSS) } 6917a71c8aaSRadu Pirea (NXP OSS) 692*b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_or_falling(struct phy_device *phydev, 693*b0b2247dSRadu Pirea (NXP OSS) struct ptp_extts_request *extts) 694*b0b2247dSRadu Pirea (NXP OSS) { 695*b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE) 696*b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 697*b0b2247dSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE); 698*b0b2247dSRadu Pirea (NXP OSS) 699*b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE) 700*b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 701*b0b2247dSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE); 702*b0b2247dSRadu Pirea (NXP OSS) } 703*b0b2247dSRadu Pirea (NXP OSS) 704*b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_and_falling(struct phy_device *phydev, 705*b0b2247dSRadu Pirea (NXP OSS) struct ptp_extts_request *extts) 706*b0b2247dSRadu Pirea (NXP OSS) { 707*b0b2247dSRadu Pirea (NXP OSS) /* PTP_EXTTS_REQUEST may have only the PTP_ENABLE_FEATURE flag set. In 708*b0b2247dSRadu Pirea (NXP OSS) * this case external ts will be enabled on rising edge. 709*b0b2247dSRadu Pirea (NXP OSS) */ 710*b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE || 711*b0b2247dSRadu Pirea (NXP OSS) extts->flags == PTP_ENABLE_FEATURE) 712*b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 713*b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 714*b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_RISE_TS); 715*b0b2247dSRadu Pirea (NXP OSS) else 716*b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 717*b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 718*b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_RISE_TS); 719*b0b2247dSRadu Pirea (NXP OSS) 720*b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE) 721*b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 722*b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 723*b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_FALLING_TS); 724*b0b2247dSRadu Pirea (NXP OSS) else 725*b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 726*b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER, 727*b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_FALLING_TS); 728*b0b2247dSRadu Pirea (NXP OSS) } 729*b0b2247dSRadu Pirea (NXP OSS) 7307a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_extts_enable(struct nxp_c45_phy *priv, 7317a71c8aaSRadu Pirea (NXP OSS) struct ptp_extts_request *extts, int on) 7327a71c8aaSRadu Pirea (NXP OSS) { 733*b0b2247dSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev); 7347a71c8aaSRadu Pirea (NXP OSS) int pin; 7357a71c8aaSRadu Pirea (NXP OSS) 7367a71c8aaSRadu Pirea (NXP OSS) if (extts->flags & ~(PTP_ENABLE_FEATURE | 7377a71c8aaSRadu Pirea (NXP OSS) PTP_RISING_EDGE | 7387a71c8aaSRadu Pirea (NXP OSS) PTP_FALLING_EDGE | 7397a71c8aaSRadu Pirea (NXP OSS) PTP_STRICT_FLAGS)) 7407a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 7417a71c8aaSRadu Pirea (NXP OSS) 7427a71c8aaSRadu Pirea (NXP OSS) /* Sampling on both edges is not supported */ 7437a71c8aaSRadu Pirea (NXP OSS) if ((extts->flags & PTP_RISING_EDGE) && 744*b0b2247dSRadu Pirea (NXP OSS) (extts->flags & PTP_FALLING_EDGE) && 745*b0b2247dSRadu Pirea (NXP OSS) !data->ext_ts_both_edges) 7467a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 7477a71c8aaSRadu Pirea (NXP OSS) 7487a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_EXTTS, extts->index); 7497a71c8aaSRadu Pirea (NXP OSS) if (pin < 0) 7507a71c8aaSRadu Pirea (NXP OSS) return pin; 7517a71c8aaSRadu Pirea (NXP OSS) 7527a71c8aaSRadu Pirea (NXP OSS) if (!on) { 7537a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); 7547a71c8aaSRadu Pirea (NXP OSS) priv->extts = false; 7557a71c8aaSRadu Pirea (NXP OSS) 7567a71c8aaSRadu Pirea (NXP OSS) return 0; 7577a71c8aaSRadu Pirea (NXP OSS) } 7587a71c8aaSRadu Pirea (NXP OSS) 759*b0b2247dSRadu Pirea (NXP OSS) if (data->ext_ts_both_edges) 760*b0b2247dSRadu Pirea (NXP OSS) nxp_c45_set_rising_and_falling(priv->phydev, extts); 761*b0b2247dSRadu Pirea (NXP OSS) else 762*b0b2247dSRadu Pirea (NXP OSS) nxp_c45_set_rising_or_falling(priv->phydev, extts); 7637a71c8aaSRadu Pirea (NXP OSS) 7647a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_EXTTS_OUT_CFG); 7657a71c8aaSRadu Pirea (NXP OSS) priv->extts = true; 7667a71c8aaSRadu Pirea (NXP OSS) priv->extts_index = extts->index; 7677a71c8aaSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 7687a71c8aaSRadu Pirea (NXP OSS) 7697a71c8aaSRadu Pirea (NXP OSS) return 0; 7707a71c8aaSRadu Pirea (NXP OSS) } 7717a71c8aaSRadu Pirea (NXP OSS) 7727a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_enable(struct ptp_clock_info *ptp, 7737a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_request *req, int on) 7747a71c8aaSRadu Pirea (NXP OSS) { 7757a71c8aaSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 7767a71c8aaSRadu Pirea (NXP OSS) 7777a71c8aaSRadu Pirea (NXP OSS) switch (req->type) { 7787a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_EXTTS: 7797a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_extts_enable(priv, &req->extts, on); 7807a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_PEROUT: 7817a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_perout_enable(priv, &req->perout, on); 7827a71c8aaSRadu Pirea (NXP OSS) default: 7837a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 7847a71c8aaSRadu Pirea (NXP OSS) } 7857a71c8aaSRadu Pirea (NXP OSS) } 7867a71c8aaSRadu Pirea (NXP OSS) 7877a71c8aaSRadu Pirea (NXP OSS) static struct ptp_pin_desc nxp_c45_ptp_pins[] = { 7887a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio0", 0, PTP_PF_NONE}, 7897a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio1", 1, PTP_PF_NONE}, 7907a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio2", 2, PTP_PF_NONE}, 7917a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio3", 3, PTP_PF_NONE}, 7927a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio4", 4, PTP_PF_NONE}, 7937a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio5", 5, PTP_PF_NONE}, 7947a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio6", 6, PTP_PF_NONE}, 7957a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio7", 7, PTP_PF_NONE}, 7967a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio8", 8, PTP_PF_NONE}, 7977a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio9", 9, PTP_PF_NONE}, 7987a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio10", 10, PTP_PF_NONE}, 7997a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio11", 11, PTP_PF_NONE}, 8007a71c8aaSRadu Pirea (NXP OSS) }; 8017a71c8aaSRadu Pirea (NXP OSS) 8027a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, 8037a71c8aaSRadu Pirea (NXP OSS) enum ptp_pin_function func, unsigned int chan) 8047a71c8aaSRadu Pirea (NXP OSS) { 8057a71c8aaSRadu Pirea (NXP OSS) if (pin >= ARRAY_SIZE(nxp_c45_ptp_pins)) 8067a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 8077a71c8aaSRadu Pirea (NXP OSS) 8087a71c8aaSRadu Pirea (NXP OSS) switch (func) { 8097a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_NONE: 8107a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_PEROUT: 8117a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_EXTTS: 8127a71c8aaSRadu Pirea (NXP OSS) break; 8137a71c8aaSRadu Pirea (NXP OSS) default: 8147a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 8157a71c8aaSRadu Pirea (NXP OSS) } 8167a71c8aaSRadu Pirea (NXP OSS) 8177a71c8aaSRadu Pirea (NXP OSS) return 0; 8187a71c8aaSRadu Pirea (NXP OSS) } 8197a71c8aaSRadu Pirea (NXP OSS) 820514def5dSRadu Pirea (NXP OSS) static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv) 821514def5dSRadu Pirea (NXP OSS) { 822514def5dSRadu Pirea (NXP OSS) priv->caps = (struct ptp_clock_info) { 823514def5dSRadu Pirea (NXP OSS) .owner = THIS_MODULE, 824514def5dSRadu Pirea (NXP OSS) .name = "NXP C45 PHC", 825514def5dSRadu Pirea (NXP OSS) .max_adj = 16666666, 826514def5dSRadu Pirea (NXP OSS) .adjfine = nxp_c45_ptp_adjfine, 827514def5dSRadu Pirea (NXP OSS) .adjtime = nxp_c45_ptp_adjtime, 828514def5dSRadu Pirea (NXP OSS) .gettimex64 = nxp_c45_ptp_gettimex64, 829514def5dSRadu Pirea (NXP OSS) .settime64 = nxp_c45_ptp_settime64, 8307a71c8aaSRadu Pirea (NXP OSS) .enable = nxp_c45_ptp_enable, 8317a71c8aaSRadu Pirea (NXP OSS) .verify = nxp_c45_ptp_verify_pin, 832514def5dSRadu Pirea (NXP OSS) .do_aux_work = nxp_c45_do_aux_work, 8337a71c8aaSRadu Pirea (NXP OSS) .pin_config = nxp_c45_ptp_pins, 8347a71c8aaSRadu Pirea (NXP OSS) .n_pins = ARRAY_SIZE(nxp_c45_ptp_pins), 8357a71c8aaSRadu Pirea (NXP OSS) .n_ext_ts = 1, 8367a71c8aaSRadu Pirea (NXP OSS) .n_per_out = 1, 837514def5dSRadu Pirea (NXP OSS) }; 838514def5dSRadu Pirea (NXP OSS) 839514def5dSRadu Pirea (NXP OSS) priv->ptp_clock = ptp_clock_register(&priv->caps, 840514def5dSRadu Pirea (NXP OSS) &priv->phydev->mdio.dev); 841514def5dSRadu Pirea (NXP OSS) 842514def5dSRadu Pirea (NXP OSS) if (IS_ERR(priv->ptp_clock)) 843514def5dSRadu Pirea (NXP OSS) return PTR_ERR(priv->ptp_clock); 844514def5dSRadu Pirea (NXP OSS) 845514def5dSRadu Pirea (NXP OSS) if (!priv->ptp_clock) 846514def5dSRadu Pirea (NXP OSS) return -ENOMEM; 847514def5dSRadu Pirea (NXP OSS) 848514def5dSRadu Pirea (NXP OSS) return 0; 849514def5dSRadu Pirea (NXP OSS) } 850514def5dSRadu Pirea (NXP OSS) 851514def5dSRadu Pirea (NXP OSS) static void nxp_c45_txtstamp(struct mii_timestamper *mii_ts, 852514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type) 853514def5dSRadu Pirea (NXP OSS) { 854514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 855514def5dSRadu Pirea (NXP OSS) mii_ts); 856514def5dSRadu Pirea (NXP OSS) 857514def5dSRadu Pirea (NXP OSS) switch (priv->hwts_tx) { 858514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_ON: 859514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type = type; 860514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = ptp_parse_header(skb, type); 861514def5dSRadu Pirea (NXP OSS) skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 862514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->tx_queue, skb); 863514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev)) 864514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 865514def5dSRadu Pirea (NXP OSS) break; 866514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_OFF: 867514def5dSRadu Pirea (NXP OSS) default: 868514def5dSRadu Pirea (NXP OSS) kfree_skb(skb); 869514def5dSRadu Pirea (NXP OSS) break; 870514def5dSRadu Pirea (NXP OSS) } 871514def5dSRadu Pirea (NXP OSS) } 872514def5dSRadu Pirea (NXP OSS) 873514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_rxtstamp(struct mii_timestamper *mii_ts, 874514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type) 875514def5dSRadu Pirea (NXP OSS) { 876514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 877514def5dSRadu Pirea (NXP OSS) mii_ts); 878514def5dSRadu Pirea (NXP OSS) struct ptp_header *header = ptp_parse_header(skb, type); 879514def5dSRadu Pirea (NXP OSS) 880514def5dSRadu Pirea (NXP OSS) if (!header) 881514def5dSRadu Pirea (NXP OSS) return false; 882514def5dSRadu Pirea (NXP OSS) 883514def5dSRadu Pirea (NXP OSS) if (!priv->hwts_rx) 884514def5dSRadu Pirea (NXP OSS) return false; 885514def5dSRadu Pirea (NXP OSS) 886514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = header; 887514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->rx_queue, skb); 888514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 889514def5dSRadu Pirea (NXP OSS) 890514def5dSRadu Pirea (NXP OSS) return true; 891514def5dSRadu Pirea (NXP OSS) } 892514def5dSRadu Pirea (NXP OSS) 893514def5dSRadu Pirea (NXP OSS) static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts, 894514def5dSRadu Pirea (NXP OSS) struct ifreq *ifreq) 895514def5dSRadu Pirea (NXP OSS) { 896514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 897514def5dSRadu Pirea (NXP OSS) mii_ts); 898514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 8996c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data; 900514def5dSRadu Pirea (NXP OSS) struct hwtstamp_config cfg; 901514def5dSRadu Pirea (NXP OSS) 902514def5dSRadu Pirea (NXP OSS) if (copy_from_user(&cfg, ifreq->ifr_data, sizeof(cfg))) 903514def5dSRadu Pirea (NXP OSS) return -EFAULT; 904514def5dSRadu Pirea (NXP OSS) 905514def5dSRadu Pirea (NXP OSS) if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ON) 906514def5dSRadu Pirea (NXP OSS) return -ERANGE; 907514def5dSRadu Pirea (NXP OSS) 9086c0c85daSRadu Pirea (NXP OSS) data = nxp_c45_get_data(phydev); 909514def5dSRadu Pirea (NXP OSS) priv->hwts_tx = cfg.tx_type; 910514def5dSRadu Pirea (NXP OSS) 911514def5dSRadu Pirea (NXP OSS) switch (cfg.rx_filter) { 912514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_NONE: 913514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 0; 914514def5dSRadu Pirea (NXP OSS) break; 915514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 916514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 917514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 918514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 1; 919514def5dSRadu Pirea (NXP OSS) cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; 920514def5dSRadu Pirea (NXP OSS) break; 921514def5dSRadu Pirea (NXP OSS) default: 922514def5dSRadu Pirea (NXP OSS) return -ERANGE; 923514def5dSRadu Pirea (NXP OSS) } 924514def5dSRadu Pirea (NXP OSS) 925514def5dSRadu Pirea (NXP OSS) if (priv->hwts_rx || priv->hwts_tx) { 9266c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 9276c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_event_msg_filt, 928514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_ALL); 9296c0c85daSRadu Pirea (NXP OSS) data->ptp_enable(phydev, true); 930514def5dSRadu Pirea (NXP OSS) } else { 9316c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 9326c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_event_msg_filt, 933514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_NONE); 9346c0c85daSRadu Pirea (NXP OSS) data->ptp_enable(phydev, false); 935514def5dSRadu Pirea (NXP OSS) } 936514def5dSRadu Pirea (NXP OSS) 937514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev)) 938514def5dSRadu Pirea (NXP OSS) goto nxp_c45_no_ptp_irq; 939514def5dSRadu Pirea (NXP OSS) 940514def5dSRadu Pirea (NXP OSS) if (priv->hwts_tx) 9416c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(phydev, &data->regmap->irq_egr_ts_en); 942514def5dSRadu Pirea (NXP OSS) else 9436c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(phydev, &data->regmap->irq_egr_ts_en); 944514def5dSRadu Pirea (NXP OSS) 945514def5dSRadu Pirea (NXP OSS) nxp_c45_no_ptp_irq: 946514def5dSRadu Pirea (NXP OSS) return copy_to_user(ifreq->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 947514def5dSRadu Pirea (NXP OSS) } 948514def5dSRadu Pirea (NXP OSS) 949514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ts_info(struct mii_timestamper *mii_ts, 950514def5dSRadu Pirea (NXP OSS) struct ethtool_ts_info *ts_info) 951514def5dSRadu Pirea (NXP OSS) { 952514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 953514def5dSRadu Pirea (NXP OSS) mii_ts); 954514def5dSRadu Pirea (NXP OSS) 955514def5dSRadu Pirea (NXP OSS) ts_info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | 956514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RX_HARDWARE | 957514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RAW_HARDWARE; 958514def5dSRadu Pirea (NXP OSS) ts_info->phc_index = ptp_clock_index(priv->ptp_clock); 959514def5dSRadu Pirea (NXP OSS) ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); 960514def5dSRadu Pirea (NXP OSS) ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | 961514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | 962514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | 963514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT); 964514def5dSRadu Pirea (NXP OSS) 965514def5dSRadu Pirea (NXP OSS) return 0; 966514def5dSRadu Pirea (NXP OSS) } 967514def5dSRadu Pirea (NXP OSS) 9686c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats common_hw_stats[] = { 9696c0c85daSRadu Pirea (NXP OSS) { "phy_link_status_drop_cnt", 9706c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 8, 6), }, 9716c0c85daSRadu Pirea (NXP OSS) { "phy_link_availability_drop_cnt", 9726c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 0, 6), }, 9736c0c85daSRadu Pirea (NXP OSS) { "phy_link_loss_cnt", 9746c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 10, 6), }, 9756c0c85daSRadu Pirea (NXP OSS) { "phy_link_failure_cnt", 9766c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 0, 10), }, 9776c0c85daSRadu Pirea (NXP OSS) { "phy_symbol_error_cnt", 9786c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8350, MDIO_MMD_VEND1, 0, 16) }, 9796c0c85daSRadu Pirea (NXP OSS) }; 9806c0c85daSRadu Pirea (NXP OSS) 9816c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1103_hw_stats[] = { 9826c0c85daSRadu Pirea (NXP OSS) { "rx_preamble_count", 9836c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFCE, MDIO_MMD_VEND1, 0, 6), }, 9846c0c85daSRadu Pirea (NXP OSS) { "tx_preamble_count", 9856c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFCF, MDIO_MMD_VEND1, 0, 6), }, 9866c0c85daSRadu Pirea (NXP OSS) { "rx_ipg_length", 9876c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFD0, MDIO_MMD_VEND1, 0, 9), }, 9886c0c85daSRadu Pirea (NXP OSS) { "tx_ipg_length", 9896c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFD1, MDIO_MMD_VEND1, 0, 9), }, 990b050f2f1SRadu Pirea (NXP OSS) }; 991b050f2f1SRadu Pirea (NXP OSS) 992f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1120_hw_stats[] = { 993f1fe5dffSRadu Pirea (NXP OSS) { "phy_symbol_error_cnt_ext", 994f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8351, MDIO_MMD_VEND1, 0, 14) }, 995f1fe5dffSRadu Pirea (NXP OSS) { "tx_frames_xtd", 996f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA1, MDIO_MMD_VEND1, 0, 8), }, 997f1fe5dffSRadu Pirea (NXP OSS) { "tx_frames", 998f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA0, MDIO_MMD_VEND1, 0, 16), }, 999f1fe5dffSRadu Pirea (NXP OSS) { "rx_frames_xtd", 1000f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA3, MDIO_MMD_VEND1, 0, 8), }, 1001f1fe5dffSRadu Pirea (NXP OSS) { "rx_frames", 1002f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA2, MDIO_MMD_VEND1, 0, 16), }, 1003f1fe5dffSRadu Pirea (NXP OSS) { "tx_lost_frames_xtd", 1004f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA5, MDIO_MMD_VEND1, 0, 8), }, 1005f1fe5dffSRadu Pirea (NXP OSS) { "tx_lost_frames", 1006f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA4, MDIO_MMD_VEND1, 0, 16), }, 1007f1fe5dffSRadu Pirea (NXP OSS) { "rx_lost_frames_xtd", 1008f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA7, MDIO_MMD_VEND1, 0, 8), }, 1009f1fe5dffSRadu Pirea (NXP OSS) { "rx_lost_frames", 1010f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA6, MDIO_MMD_VEND1, 0, 16), }, 1011f1fe5dffSRadu Pirea (NXP OSS) }; 1012f1fe5dffSRadu Pirea (NXP OSS) 1013b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev) 1014b050f2f1SRadu Pirea (NXP OSS) { 10156c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 10166c0c85daSRadu Pirea (NXP OSS) 10176c0c85daSRadu Pirea (NXP OSS) return ARRAY_SIZE(common_hw_stats) + (phy_data ? phy_data->n_stats : 0); 1018b050f2f1SRadu Pirea (NXP OSS) } 1019b050f2f1SRadu Pirea (NXP OSS) 1020b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data) 1021b050f2f1SRadu Pirea (NXP OSS) { 10226c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 10236c0c85daSRadu Pirea (NXP OSS) size_t count = nxp_c45_get_sset_count(phydev); 10246c0c85daSRadu Pirea (NXP OSS) size_t idx; 1025b050f2f1SRadu Pirea (NXP OSS) size_t i; 1026b050f2f1SRadu Pirea (NXP OSS) 10276c0c85daSRadu Pirea (NXP OSS) for (i = 0; i < count; i++) { 10286c0c85daSRadu Pirea (NXP OSS) if (i < ARRAY_SIZE(common_hw_stats)) { 10296c0c85daSRadu Pirea (NXP OSS) strscpy(data + i * ETH_GSTRING_LEN, 10306c0c85daSRadu Pirea (NXP OSS) common_hw_stats[i].name, ETH_GSTRING_LEN); 10316c0c85daSRadu Pirea (NXP OSS) continue; 10326c0c85daSRadu Pirea (NXP OSS) } 10336c0c85daSRadu Pirea (NXP OSS) idx = i - ARRAY_SIZE(common_hw_stats); 10346c0c85daSRadu Pirea (NXP OSS) strscpy(data + i * ETH_GSTRING_LEN, 10356c0c85daSRadu Pirea (NXP OSS) phy_data->stats[idx].name, ETH_GSTRING_LEN); 1036b050f2f1SRadu Pirea (NXP OSS) } 1037b050f2f1SRadu Pirea (NXP OSS) } 1038b050f2f1SRadu Pirea (NXP OSS) 1039b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev, 1040b050f2f1SRadu Pirea (NXP OSS) struct ethtool_stats *stats, u64 *data) 1041b050f2f1SRadu Pirea (NXP OSS) { 10426c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev); 10436c0c85daSRadu Pirea (NXP OSS) size_t count = nxp_c45_get_sset_count(phydev); 10446c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field; 10456c0c85daSRadu Pirea (NXP OSS) size_t idx; 1046b050f2f1SRadu Pirea (NXP OSS) size_t i; 1047b050f2f1SRadu Pirea (NXP OSS) int ret; 1048b050f2f1SRadu Pirea (NXP OSS) 10496c0c85daSRadu Pirea (NXP OSS) for (i = 0; i < count; i++) { 10506c0c85daSRadu Pirea (NXP OSS) if (i < ARRAY_SIZE(common_hw_stats)) { 10516c0c85daSRadu Pirea (NXP OSS) reg_field = &common_hw_stats[i].counter; 1052b050f2f1SRadu Pirea (NXP OSS) } else { 10536c0c85daSRadu Pirea (NXP OSS) idx = i - ARRAY_SIZE(common_hw_stats); 10546c0c85daSRadu Pirea (NXP OSS) reg_field = &phy_data->stats[idx].counter; 1055b050f2f1SRadu Pirea (NXP OSS) } 10566c0c85daSRadu Pirea (NXP OSS) 10576c0c85daSRadu Pirea (NXP OSS) ret = nxp_c45_read_reg_field(phydev, reg_field); 10586c0c85daSRadu Pirea (NXP OSS) if (ret < 0) 10596c0c85daSRadu Pirea (NXP OSS) data[i] = U64_MAX; 10606c0c85daSRadu Pirea (NXP OSS) else 10616c0c85daSRadu Pirea (NXP OSS) data[i] = ret; 1062b050f2f1SRadu Pirea (NXP OSS) } 1063b050f2f1SRadu Pirea (NXP OSS) } 1064b050f2f1SRadu Pirea (NXP OSS) 1065b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev) 1066b050f2f1SRadu Pirea (NXP OSS) { 1067b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 1068b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_GLOBAL_EN | 1069b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_ALL_EN); 1070b050f2f1SRadu Pirea (NXP OSS) usleep_range(400, 450); 1071b050f2f1SRadu Pirea (NXP OSS) 1072b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL, 1073b050f2f1SRadu Pirea (NXP OSS) PORT_CONTROL_EN); 1074b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 1075b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_EN); 1076b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL, 1077b050f2f1SRadu Pirea (NXP OSS) PORT_INFRA_CONTROL_EN); 1078b050f2f1SRadu Pirea (NXP OSS) 1079b050f2f1SRadu Pirea (NXP OSS) return 0; 1080b050f2f1SRadu Pirea (NXP OSS) } 1081b050f2f1SRadu Pirea (NXP OSS) 1082b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev) 1083b050f2f1SRadu Pirea (NXP OSS) { 1084b050f2f1SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 1085b050f2f1SRadu Pirea (NXP OSS) PHY_START_OP); 1086b050f2f1SRadu Pirea (NXP OSS) } 1087b050f2f1SRadu Pirea (NXP OSS) 1088b2f0ca00SRadu Pirea (NXP OSS) static int nxp_c45_config_intr(struct phy_device *phydev) 1089b2f0ca00SRadu Pirea (NXP OSS) { 1090b2f0ca00SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 1091b2f0ca00SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1092b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 1093b2f0ca00SRadu Pirea (NXP OSS) else 1094b2f0ca00SRadu Pirea (NXP OSS) return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1095b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 1096b2f0ca00SRadu Pirea (NXP OSS) } 1097b2f0ca00SRadu Pirea (NXP OSS) 1098b2f0ca00SRadu Pirea (NXP OSS) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) 1099b2f0ca00SRadu Pirea (NXP OSS) { 11006c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 1101514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1102b2f0ca00SRadu Pirea (NXP OSS) irqreturn_t ret = IRQ_NONE; 1103514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts; 1104b2f0ca00SRadu Pirea (NXP OSS) int irq; 1105b2f0ca00SRadu Pirea (NXP OSS) 1106b2f0ca00SRadu Pirea (NXP OSS) irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS); 1107b2f0ca00SRadu Pirea (NXP OSS) if (irq & PHY_IRQ_LINK_EVENT) { 1108b2f0ca00SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK, 1109b2f0ca00SRadu Pirea (NXP OSS) PHY_IRQ_LINK_EVENT); 1110b2f0ca00SRadu Pirea (NXP OSS) phy_trigger_machine(phydev); 1111b2f0ca00SRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 1112b2f0ca00SRadu Pirea (NXP OSS) } 1113b2f0ca00SRadu Pirea (NXP OSS) 1114514def5dSRadu Pirea (NXP OSS) /* There is no need for ACK. 1115514def5dSRadu Pirea (NXP OSS) * The irq signal will be asserted until the EGR TS FIFO will be 1116514def5dSRadu Pirea (NXP OSS) * emptied. 1117514def5dSRadu Pirea (NXP OSS) */ 11186c0c85daSRadu Pirea (NXP OSS) irq = nxp_c45_read_reg_field(phydev, &data->regmap->irq_egr_ts_status); 11196c0c85daSRadu Pirea (NXP OSS) if (irq) { 1120514def5dSRadu Pirea (NXP OSS) while (nxp_c45_get_hwtxts(priv, &hwts)) 1121514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts); 1122514def5dSRadu Pirea (NXP OSS) 1123514def5dSRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 1124514def5dSRadu Pirea (NXP OSS) } 1125514def5dSRadu Pirea (NXP OSS) 1126b2f0ca00SRadu Pirea (NXP OSS) return ret; 1127b2f0ca00SRadu Pirea (NXP OSS) } 1128b2f0ca00SRadu Pirea (NXP OSS) 1129b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev) 1130b050f2f1SRadu Pirea (NXP OSS) { 1131b050f2f1SRadu Pirea (NXP OSS) int ret; 1132b050f2f1SRadu Pirea (NXP OSS) 1133b050f2f1SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 1134b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_RESET); 1135b050f2f1SRadu Pirea (NXP OSS) if (ret) 1136b050f2f1SRadu Pirea (NXP OSS) return ret; 1137b050f2f1SRadu Pirea (NXP OSS) 1138b050f2f1SRadu Pirea (NXP OSS) return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 1139b050f2f1SRadu Pirea (NXP OSS) VEND1_DEVICE_CONTROL, ret, 1140b050f2f1SRadu Pirea (NXP OSS) !(ret & DEVICE_CONTROL_RESET), 20000, 1141b050f2f1SRadu Pirea (NXP OSS) 240000, false); 1142b050f2f1SRadu Pirea (NXP OSS) } 1143b050f2f1SRadu Pirea (NXP OSS) 1144b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev) 1145b050f2f1SRadu Pirea (NXP OSS) { 11466c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); 11476c0c85daSRadu Pirea (NXP OSS) 11486c0c85daSRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, 1149b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE | CABLE_TEST_START); 1150b050f2f1SRadu Pirea (NXP OSS) } 1151b050f2f1SRadu Pirea (NXP OSS) 1152b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev, 1153b050f2f1SRadu Pirea (NXP OSS) bool *finished) 1154b050f2f1SRadu Pirea (NXP OSS) { 11556c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev); 1156b050f2f1SRadu Pirea (NXP OSS) int ret; 1157b050f2f1SRadu Pirea (NXP OSS) u8 cable_test_result; 1158b050f2f1SRadu Pirea (NXP OSS) 11596c0c85daSRadu Pirea (NXP OSS) ret = nxp_c45_read_reg_field(phydev, ®map->cable_test_valid); 11606c0c85daSRadu Pirea (NXP OSS) if (!ret) { 1161b050f2f1SRadu Pirea (NXP OSS) *finished = false; 1162b050f2f1SRadu Pirea (NXP OSS) return 0; 1163b050f2f1SRadu Pirea (NXP OSS) } 1164b050f2f1SRadu Pirea (NXP OSS) 1165b050f2f1SRadu Pirea (NXP OSS) *finished = true; 11666c0c85daSRadu Pirea (NXP OSS) cable_test_result = nxp_c45_read_reg_field(phydev, 11676c0c85daSRadu Pirea (NXP OSS) ®map->cable_test_result); 1168b050f2f1SRadu Pirea (NXP OSS) 1169b050f2f1SRadu Pirea (NXP OSS) switch (cable_test_result) { 1170b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OK: 1171b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1172b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OK); 1173b050f2f1SRadu Pirea (NXP OSS) break; 1174b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_SHORTED: 1175b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1176b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT); 1177b050f2f1SRadu Pirea (NXP OSS) break; 1178b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OPEN: 1179b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1180b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OPEN); 1181b050f2f1SRadu Pirea (NXP OSS) break; 1182b050f2f1SRadu Pirea (NXP OSS) default: 1183b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1184b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC); 1185b050f2f1SRadu Pirea (NXP OSS) } 1186b050f2f1SRadu Pirea (NXP OSS) 11876c0c85daSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test, 1188b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE); 1189b050f2f1SRadu Pirea (NXP OSS) 1190b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 1191b050f2f1SRadu Pirea (NXP OSS) } 1192b050f2f1SRadu Pirea (NXP OSS) 1193b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev) 1194b050f2f1SRadu Pirea (NXP OSS) { 1195b050f2f1SRadu Pirea (NXP OSS) int reg; 1196b050f2f1SRadu Pirea (NXP OSS) 1197b050f2f1SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY); 1198b050f2f1SRadu Pirea (NXP OSS) if (!(reg & SQI_VALID)) 1199b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1200b050f2f1SRadu Pirea (NXP OSS) 1201b050f2f1SRadu Pirea (NXP OSS) reg &= SQI_MASK; 1202b050f2f1SRadu Pirea (NXP OSS) 1203b050f2f1SRadu Pirea (NXP OSS) return reg; 1204b050f2f1SRadu Pirea (NXP OSS) } 1205b050f2f1SRadu Pirea (NXP OSS) 1206b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev) 1207b050f2f1SRadu Pirea (NXP OSS) { 1208b050f2f1SRadu Pirea (NXP OSS) return MAX_SQI; 1209b050f2f1SRadu Pirea (NXP OSS) } 1210b050f2f1SRadu Pirea (NXP OSS) 1211b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay) 1212b050f2f1SRadu Pirea (NXP OSS) { 1213b050f2f1SRadu Pirea (NXP OSS) if (delay < MIN_ID_PS) { 1214b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS); 1215b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1216b050f2f1SRadu Pirea (NXP OSS) } 1217b050f2f1SRadu Pirea (NXP OSS) 1218b050f2f1SRadu Pirea (NXP OSS) if (delay > MAX_ID_PS) { 1219b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS); 1220b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1221b050f2f1SRadu Pirea (NXP OSS) } 1222b050f2f1SRadu Pirea (NXP OSS) 1223b050f2f1SRadu Pirea (NXP OSS) return 0; 1224b050f2f1SRadu Pirea (NXP OSS) } 1225b050f2f1SRadu Pirea (NXP OSS) 12266c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_counters_enable(struct phy_device *phydev) 12276c0c85daSRadu Pirea (NXP OSS) { 12286c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 12296c0c85daSRadu Pirea (NXP OSS) 12306c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER, 12316c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 12326c0c85daSRadu Pirea (NXP OSS) 12336c0c85daSRadu Pirea (NXP OSS) data->counters_enable(phydev); 12346c0c85daSRadu Pirea (NXP OSS) } 12356c0c85daSRadu Pirea (NXP OSS) 12366c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_ptp_init(struct phy_device *phydev) 12376c0c85daSRadu Pirea (NXP OSS) { 12386c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev); 12396c0c85daSRadu Pirea (NXP OSS) 12406c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 12416c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_ptp_clk_period, 12426c0c85daSRadu Pirea (NXP OSS) data->ptp_clk_period); 12436c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(phydev, &data->regmap->ltc_lock_ctrl); 12446c0c85daSRadu Pirea (NXP OSS) 12456c0c85daSRadu Pirea (NXP OSS) data->ptp_init(phydev); 12466c0c85daSRadu Pirea (NXP OSS) } 12476c0c85daSRadu Pirea (NXP OSS) 1248b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw) 1249b050f2f1SRadu Pirea (NXP OSS) { 1250b050f2f1SRadu Pirea (NXP OSS) /* The delay in degree phase is 73.8 + phase_offset_raw * 0.9. 1251b050f2f1SRadu Pirea (NXP OSS) * To avoid floating point operations we'll multiply by 10 1252b050f2f1SRadu Pirea (NXP OSS) * and get 1 decimal point precision. 1253b050f2f1SRadu Pirea (NXP OSS) */ 1254b050f2f1SRadu Pirea (NXP OSS) phase_offset_raw *= 10; 12556b3a6310SRadu Pirea (NXP OSS) phase_offset_raw -= 738; 1256b050f2f1SRadu Pirea (NXP OSS) return div_u64(phase_offset_raw, 9); 1257b050f2f1SRadu Pirea (NXP OSS) } 1258b050f2f1SRadu Pirea (NXP OSS) 1259b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev) 1260b050f2f1SRadu Pirea (NXP OSS) { 1261b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE); 1262b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE); 1263b050f2f1SRadu Pirea (NXP OSS) } 1264b050f2f1SRadu Pirea (NXP OSS) 1265b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev) 1266b050f2f1SRadu Pirea (NXP OSS) { 1267b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1268b050f2f1SRadu Pirea (NXP OSS) u64 tx_delay = priv->tx_delay; 1269b050f2f1SRadu Pirea (NXP OSS) u64 rx_delay = priv->rx_delay; 1270b050f2f1SRadu Pirea (NXP OSS) u64 degree; 1271b050f2f1SRadu Pirea (NXP OSS) 1272b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1273b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 1274b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(tx_delay, PS_PER_DEGREE); 1275b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 1276b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 1277b050f2f1SRadu Pirea (NXP OSS) } else { 1278b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 1279b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 1280b050f2f1SRadu Pirea (NXP OSS) } 1281b050f2f1SRadu Pirea (NXP OSS) 1282b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1283b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 1284b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(rx_delay, PS_PER_DEGREE); 1285b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 1286b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 1287b050f2f1SRadu Pirea (NXP OSS) } else { 1288b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 1289b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 1290b050f2f1SRadu Pirea (NXP OSS) } 1291b050f2f1SRadu Pirea (NXP OSS) } 1292b050f2f1SRadu Pirea (NXP OSS) 1293b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev) 1294b050f2f1SRadu Pirea (NXP OSS) { 1295b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1296b050f2f1SRadu Pirea (NXP OSS) int ret; 1297b050f2f1SRadu Pirea (NXP OSS) 1298b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1299b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 1300b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 1301b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps", 1302b050f2f1SRadu Pirea (NXP OSS) &priv->tx_delay); 1303b050f2f1SRadu Pirea (NXP OSS) if (ret) 1304b050f2f1SRadu Pirea (NXP OSS) priv->tx_delay = DEFAULT_ID_PS; 1305b050f2f1SRadu Pirea (NXP OSS) 1306b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->tx_delay); 1307b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1308b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 1309b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps invalid value\n"); 1310b050f2f1SRadu Pirea (NXP OSS) return ret; 1311b050f2f1SRadu Pirea (NXP OSS) } 1312b050f2f1SRadu Pirea (NXP OSS) } 1313b050f2f1SRadu Pirea (NXP OSS) 1314b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1315b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 1316b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 1317b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps", 1318b050f2f1SRadu Pirea (NXP OSS) &priv->rx_delay); 1319b050f2f1SRadu Pirea (NXP OSS) if (ret) 1320b050f2f1SRadu Pirea (NXP OSS) priv->rx_delay = DEFAULT_ID_PS; 1321b050f2f1SRadu Pirea (NXP OSS) 1322b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->rx_delay); 1323b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1324b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 1325b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps invalid value\n"); 1326b050f2f1SRadu Pirea (NXP OSS) return ret; 1327b050f2f1SRadu Pirea (NXP OSS) } 1328b050f2f1SRadu Pirea (NXP OSS) } 1329b050f2f1SRadu Pirea (NXP OSS) 1330b050f2f1SRadu Pirea (NXP OSS) return 0; 1331b050f2f1SRadu Pirea (NXP OSS) } 1332b050f2f1SRadu Pirea (NXP OSS) 1333b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev) 1334b050f2f1SRadu Pirea (NXP OSS) { 1335b050f2f1SRadu Pirea (NXP OSS) int ret; 1336b050f2f1SRadu Pirea (NXP OSS) 1337b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES); 1338b050f2f1SRadu Pirea (NXP OSS) phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret); 1339b050f2f1SRadu Pirea (NXP OSS) 1340b050f2f1SRadu Pirea (NXP OSS) switch (phydev->interface) { 1341b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII: 1342b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ABILITY)) { 1343b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii mode not supported\n"); 1344b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1345b050f2f1SRadu Pirea (NXP OSS) } 1346b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1347b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 1348b050f2f1SRadu Pirea (NXP OSS) nxp_c45_disable_delays(phydev); 1349b050f2f1SRadu Pirea (NXP OSS) break; 1350b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_ID: 1351b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_TXID: 1352b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_RXID: 1353b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ID_ABILITY)) { 1354b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n"); 1355b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1356b050f2f1SRadu Pirea (NXP OSS) } 1357b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1358b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 1359b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_get_delays(phydev); 1360b050f2f1SRadu Pirea (NXP OSS) if (ret) 1361b050f2f1SRadu Pirea (NXP OSS) return ret; 1362b050f2f1SRadu Pirea (NXP OSS) 1363b050f2f1SRadu Pirea (NXP OSS) nxp_c45_set_delays(phydev); 1364b050f2f1SRadu Pirea (NXP OSS) break; 1365b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_MII: 1366b050f2f1SRadu Pirea (NXP OSS) if (!(ret & MII_ABILITY)) { 1367b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "mii mode not supported\n"); 1368b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1369b050f2f1SRadu Pirea (NXP OSS) } 1370b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1371b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII); 1372b050f2f1SRadu Pirea (NXP OSS) break; 1373b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_REVMII: 1374b050f2f1SRadu Pirea (NXP OSS) if (!(ret & REVMII_ABILITY)) { 1375b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rev-mii mode not supported\n"); 1376b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1377b050f2f1SRadu Pirea (NXP OSS) } 1378b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1379b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII | MII_BASIC_CONFIG_REV); 1380b050f2f1SRadu Pirea (NXP OSS) break; 1381b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RMII: 1382b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RMII_ABILITY)) { 1383b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rmii mode not supported\n"); 1384b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1385b050f2f1SRadu Pirea (NXP OSS) } 1386b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1387b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RMII); 1388b050f2f1SRadu Pirea (NXP OSS) break; 1389b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_SGMII: 1390b050f2f1SRadu Pirea (NXP OSS) if (!(ret & SGMII_ABILITY)) { 1391b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "sgmii mode not supported\n"); 1392b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1393b050f2f1SRadu Pirea (NXP OSS) } 1394b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1395b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_SGMII); 1396b050f2f1SRadu Pirea (NXP OSS) break; 1397b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_INTERNAL: 1398b050f2f1SRadu Pirea (NXP OSS) break; 1399b050f2f1SRadu Pirea (NXP OSS) default: 1400b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1401b050f2f1SRadu Pirea (NXP OSS) } 1402b050f2f1SRadu Pirea (NXP OSS) 1403b050f2f1SRadu Pirea (NXP OSS) return 0; 1404b050f2f1SRadu Pirea (NXP OSS) } 1405b050f2f1SRadu Pirea (NXP OSS) 1406b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev) 1407b050f2f1SRadu Pirea (NXP OSS) { 1408b050f2f1SRadu Pirea (NXP OSS) int ret; 1409b050f2f1SRadu Pirea (NXP OSS) 1410b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_config_enable(phydev); 1411b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1412b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "Failed to enable config\n"); 1413b050f2f1SRadu Pirea (NXP OSS) return ret; 1414b050f2f1SRadu Pirea (NXP OSS) } 1415b050f2f1SRadu Pirea (NXP OSS) 14160b5f0f29SVladimir Oltean /* Bug workaround for SJA1110 rev B: enable write access 14170b5f0f29SVladimir Oltean * to MDIO_MMD_PMAPMD 14180b5f0f29SVladimir Oltean */ 14190b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1); 14200b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2); 14210b5f0f29SVladimir Oltean 1422b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG, 1423b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_AUTO); 1424b050f2f1SRadu Pirea (NXP OSS) 1425b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_set_phy_mode(phydev); 1426b050f2f1SRadu Pirea (NXP OSS) if (ret) 1427b050f2f1SRadu Pirea (NXP OSS) return ret; 1428b050f2f1SRadu Pirea (NXP OSS) 1429b050f2f1SRadu Pirea (NXP OSS) phydev->autoneg = AUTONEG_DISABLE; 1430b050f2f1SRadu Pirea (NXP OSS) 14316c0c85daSRadu Pirea (NXP OSS) nxp_c45_counters_enable(phydev); 14326c0c85daSRadu Pirea (NXP OSS) nxp_c45_ptp_init(phydev); 1433514def5dSRadu Pirea (NXP OSS) 1434b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 1435b050f2f1SRadu Pirea (NXP OSS) } 1436b050f2f1SRadu Pirea (NXP OSS) 1437369da333SRadu Pirea (NXP OSS) static int nxp_c45_get_features(struct phy_device *phydev) 1438369da333SRadu Pirea (NXP OSS) { 1439369da333SRadu Pirea (NXP OSS) linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported); 1440369da333SRadu Pirea (NXP OSS) linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported); 1441369da333SRadu Pirea (NXP OSS) 1442369da333SRadu Pirea (NXP OSS) return genphy_c45_pma_read_abilities(phydev); 1443369da333SRadu Pirea (NXP OSS) } 1444369da333SRadu Pirea (NXP OSS) 1445b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev) 1446b050f2f1SRadu Pirea (NXP OSS) { 1447b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv; 1448514def5dSRadu Pirea (NXP OSS) int ptp_ability; 1449514def5dSRadu Pirea (NXP OSS) int ret = 0; 1450b050f2f1SRadu Pirea (NXP OSS) 1451b050f2f1SRadu Pirea (NXP OSS) priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 1452b050f2f1SRadu Pirea (NXP OSS) if (!priv) 1453b050f2f1SRadu Pirea (NXP OSS) return -ENOMEM; 1454b050f2f1SRadu Pirea (NXP OSS) 1455514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->tx_queue); 1456514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->rx_queue); 1457514def5dSRadu Pirea (NXP OSS) 1458514def5dSRadu Pirea (NXP OSS) priv->phydev = phydev; 1459514def5dSRadu Pirea (NXP OSS) 1460b050f2f1SRadu Pirea (NXP OSS) phydev->priv = priv; 1461b050f2f1SRadu Pirea (NXP OSS) 1462514def5dSRadu Pirea (NXP OSS) mutex_init(&priv->ptp_lock); 1463514def5dSRadu Pirea (NXP OSS) 1464514def5dSRadu Pirea (NXP OSS) ptp_ability = phy_read_mmd(phydev, MDIO_MMD_VEND1, 1465514def5dSRadu Pirea (NXP OSS) VEND1_PORT_ABILITIES); 1466514def5dSRadu Pirea (NXP OSS) ptp_ability = !!(ptp_ability & PTP_ABILITY); 1467514def5dSRadu Pirea (NXP OSS) if (!ptp_ability) { 1468565c6d8cSVladimir Oltean phydev_dbg(phydev, "the phy does not support PTP"); 1469514def5dSRadu Pirea (NXP OSS) goto no_ptp_support; 1470514def5dSRadu Pirea (NXP OSS) } 1471514def5dSRadu Pirea (NXP OSS) 1472514def5dSRadu Pirea (NXP OSS) if (IS_ENABLED(CONFIG_PTP_1588_CLOCK) && 1473514def5dSRadu Pirea (NXP OSS) IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) { 1474514def5dSRadu Pirea (NXP OSS) priv->mii_ts.rxtstamp = nxp_c45_rxtstamp; 1475514def5dSRadu Pirea (NXP OSS) priv->mii_ts.txtstamp = nxp_c45_txtstamp; 1476514def5dSRadu Pirea (NXP OSS) priv->mii_ts.hwtstamp = nxp_c45_hwtstamp; 1477514def5dSRadu Pirea (NXP OSS) priv->mii_ts.ts_info = nxp_c45_ts_info; 1478514def5dSRadu Pirea (NXP OSS) phydev->mii_ts = &priv->mii_ts; 1479514def5dSRadu Pirea (NXP OSS) ret = nxp_c45_init_ptp_clock(priv); 1480514def5dSRadu Pirea (NXP OSS) } else { 1481514def5dSRadu Pirea (NXP OSS) phydev_dbg(phydev, "PTP support not enabled even if the phy supports it"); 1482514def5dSRadu Pirea (NXP OSS) } 1483514def5dSRadu Pirea (NXP OSS) 1484514def5dSRadu Pirea (NXP OSS) no_ptp_support: 1485514def5dSRadu Pirea (NXP OSS) 1486514def5dSRadu Pirea (NXP OSS) return ret; 1487b050f2f1SRadu Pirea (NXP OSS) } 1488b050f2f1SRadu Pirea (NXP OSS) 1489a4506722SRadu Pirea (OSS) static void nxp_c45_remove(struct phy_device *phydev) 1490a4506722SRadu Pirea (OSS) { 1491a4506722SRadu Pirea (OSS) struct nxp_c45_phy *priv = phydev->priv; 1492a4506722SRadu Pirea (OSS) 1493a4506722SRadu Pirea (OSS) if (priv->ptp_clock) 1494a4506722SRadu Pirea (OSS) ptp_clock_unregister(priv->ptp_clock); 1495a4506722SRadu Pirea (OSS) 1496a4506722SRadu Pirea (OSS) skb_queue_purge(&priv->tx_queue); 1497a4506722SRadu Pirea (OSS) skb_queue_purge(&priv->rx_queue); 1498a4506722SRadu Pirea (OSS) } 1499a4506722SRadu Pirea (OSS) 15006c0c85daSRadu Pirea (NXP OSS) static void tja1103_counters_enable(struct phy_device *phydev) 15016c0c85daSRadu Pirea (NXP OSS) { 15026c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT, 15036c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 15046c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT, 15056c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 15066c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH, 15076c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 15086c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH, 15096c0c85daSRadu Pirea (NXP OSS) COUNTER_EN); 15106c0c85daSRadu Pirea (NXP OSS) } 15116c0c85daSRadu Pirea (NXP OSS) 15126c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_init(struct phy_device *phydev) 15136c0c85daSRadu Pirea (NXP OSS) { 15146c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL, 15156c0c85daSRadu Pirea (NXP OSS) TJA1103_RX_TS_INSRT_MODE2); 15166c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES, 15176c0c85daSRadu Pirea (NXP OSS) PTP_ENABLE); 15186c0c85daSRadu Pirea (NXP OSS) } 15196c0c85daSRadu Pirea (NXP OSS) 15206c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_enable(struct phy_device *phydev, bool enable) 15216c0c85daSRadu Pirea (NXP OSS) { 15226c0c85daSRadu Pirea (NXP OSS) if (enable) 15236c0c85daSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 15246c0c85daSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL, 15256c0c85daSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS); 15266c0c85daSRadu Pirea (NXP OSS) else 15276c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 15286c0c85daSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL, 15296c0c85daSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS); 15306c0c85daSRadu Pirea (NXP OSS) } 15316c0c85daSRadu Pirea (NXP OSS) 15326c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1103_regmap = { 15336c0c85daSRadu Pirea (NXP OSS) .vend1_ptp_clk_period = 0x1104, 15346c0c85daSRadu Pirea (NXP OSS) .vend1_event_msg_filt = 0x1148, 15356c0c85daSRadu Pirea (NXP OSS) .pps_enable = 15366c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 3, 1), 15376c0c85daSRadu Pirea (NXP OSS) .pps_polarity = 15386c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 2, 1), 15396c0c85daSRadu Pirea (NXP OSS) .ltc_lock_ctrl = 15406c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1115, MDIO_MMD_VEND1, 0, 1), 15416c0c85daSRadu Pirea (NXP OSS) .ltc_read = 15426c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 2, 1), 15436c0c85daSRadu Pirea (NXP OSS) .ltc_write = 15446c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 0, 1), 15456c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_0 = 0x1106, 15466c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_1 = 0x1107, 15476c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_0 = 0x1108, 15486c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_1 = 0x1109, 15496c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_0 = 0x110A, 15506c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_1 = 0x110B, 15516c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_0 = 0x110C, 15526c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_1 = 0x110D, 15536c0c85daSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_0 = 0x110F, 15546c0c85daSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_1 = 0x1110, 15556c0c85daSRadu Pirea (NXP OSS) .irq_egr_ts_en = 15566c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1131, MDIO_MMD_VEND1, 0, 1), 15576c0c85daSRadu Pirea (NXP OSS) .irq_egr_ts_status = 15586c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1132, MDIO_MMD_VEND1, 0, 1), 15596c0c85daSRadu Pirea (NXP OSS) .domain_number = 15606c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 0, 8), 15616c0c85daSRadu Pirea (NXP OSS) .msg_type = 15626c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 8, 4), 15636c0c85daSRadu Pirea (NXP OSS) .sequence_id = 15646c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114F, MDIO_MMD_VEND1, 0, 16), 15656c0c85daSRadu Pirea (NXP OSS) .sec_1_0 = 15666c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 14, 2), 15676c0c85daSRadu Pirea (NXP OSS) .sec_4_2 = 15686c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 12, 3), 15696c0c85daSRadu Pirea (NXP OSS) .nsec_15_0 = 15706c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1150, MDIO_MMD_VEND1, 0, 16), 15716c0c85daSRadu Pirea (NXP OSS) .nsec_29_16 = 15726c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 0, 14), 15736c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_0 = 0x1121, 15746c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_1 = 0x1122, 15756c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_2 = 0x1123, 15766c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_3 = 0x1124, 15776c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_ctrl = 0x1126, 15786c0c85daSRadu Pirea (NXP OSS) .cable_test = 0x8330, 15796c0c85daSRadu Pirea (NXP OSS) .cable_test_valid = 15806c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 13, 1), 15816c0c85daSRadu Pirea (NXP OSS) .cable_test_result = 15826c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 0, 3), 15836c0c85daSRadu Pirea (NXP OSS) }; 15846c0c85daSRadu Pirea (NXP OSS) 15856c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1103_phy_data = { 15866c0c85daSRadu Pirea (NXP OSS) .regmap = &tja1103_regmap, 15876c0c85daSRadu Pirea (NXP OSS) .stats = tja1103_hw_stats, 15886c0c85daSRadu Pirea (NXP OSS) .n_stats = ARRAY_SIZE(tja1103_hw_stats), 15896c0c85daSRadu Pirea (NXP OSS) .ptp_clk_period = PTP_CLK_PERIOD_100BT1, 1590*b0b2247dSRadu Pirea (NXP OSS) .ext_ts_both_edges = false, 15916c0c85daSRadu Pirea (NXP OSS) .counters_enable = tja1103_counters_enable, 15926c0c85daSRadu Pirea (NXP OSS) .ptp_init = tja1103_ptp_init, 15936c0c85daSRadu Pirea (NXP OSS) .ptp_enable = tja1103_ptp_enable, 15946c0c85daSRadu Pirea (NXP OSS) }; 15956c0c85daSRadu Pirea (NXP OSS) 1596f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_counters_enable(struct phy_device *phydev) 1597f1fe5dffSRadu Pirea (NXP OSS) { 1598f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_SYMBOL_ERROR_CNT_XTD, 1599f1fe5dffSRadu Pirea (NXP OSS) EXTENDED_CNT_EN); 1600f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_STATUS, 1601f1fe5dffSRadu Pirea (NXP OSS) MONITOR_RESET); 1602f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_CONFIG, 1603f1fe5dffSRadu Pirea (NXP OSS) ALL_FRAMES_CNT_EN | LOST_FRAMES_CNT_EN); 1604f1fe5dffSRadu Pirea (NXP OSS) } 1605f1fe5dffSRadu Pirea (NXP OSS) 1606f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_init(struct phy_device *phydev) 1607f1fe5dffSRadu Pirea (NXP OSS) { 1608f1fe5dffSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_RX_TS_INSRT_CTRL, 1609f1fe5dffSRadu Pirea (NXP OSS) TJA1120_RX_TS_INSRT_EN | TJA1120_TS_INSRT_MODE); 1610f1fe5dffSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_VEND1_EXT_TS_MODE, 1611f1fe5dffSRadu Pirea (NXP OSS) TJA1120_TS_INSRT_MODE); 1612f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONFIG, 1613f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1614f1fe5dffSRadu Pirea (NXP OSS) } 1615f1fe5dffSRadu Pirea (NXP OSS) 1616f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_enable(struct phy_device *phydev, bool enable) 1617f1fe5dffSRadu Pirea (NXP OSS) { 1618f1fe5dffSRadu Pirea (NXP OSS) if (enable) 1619f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 1620f1fe5dffSRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, 1621f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1622f1fe5dffSRadu Pirea (NXP OSS) else 1623f1fe5dffSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 1624f1fe5dffSRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, 1625f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE); 1626f1fe5dffSRadu Pirea (NXP OSS) } 1627f1fe5dffSRadu Pirea (NXP OSS) 1628f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1120_regmap = { 1629f1fe5dffSRadu Pirea (NXP OSS) .vend1_ptp_clk_period = 0x1020, 1630f1fe5dffSRadu Pirea (NXP OSS) .vend1_event_msg_filt = 0x9010, 1631f1fe5dffSRadu Pirea (NXP OSS) .pps_enable = 1632f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 4, 1), 1633f1fe5dffSRadu Pirea (NXP OSS) .pps_polarity = 1634f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 5, 1), 1635f1fe5dffSRadu Pirea (NXP OSS) .ltc_lock_ctrl = 1636f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 2, 1), 1637f1fe5dffSRadu Pirea (NXP OSS) .ltc_read = 1638f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 1, 1), 1639f1fe5dffSRadu Pirea (NXP OSS) .ltc_write = 1640f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 2, 1), 1641f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_0 = 0x1040, 1642f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_1 = 0x1041, 1643f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_0 = 0x1042, 1644f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_1 = 0x1043, 1645f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_0 = 0x1048, 1646f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_1 = 0x1049, 1647f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_0 = 0x104A, 1648f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_1 = 0x104B, 1649f1fe5dffSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_0 = 0x1030, 1650f1fe5dffSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_1 = 0x1031, 1651f1fe5dffSRadu Pirea (NXP OSS) .irq_egr_ts_en = 1652f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x900A, MDIO_MMD_VEND1, 1, 1), 1653f1fe5dffSRadu Pirea (NXP OSS) .irq_egr_ts_status = 1654f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x900C, MDIO_MMD_VEND1, 1, 1), 1655f1fe5dffSRadu Pirea (NXP OSS) .domain_number = 1656f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 8, 8), 1657f1fe5dffSRadu Pirea (NXP OSS) .msg_type = 1658f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 4, 4), 1659f1fe5dffSRadu Pirea (NXP OSS) .sequence_id = 1660f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9062, MDIO_MMD_VEND1, 0, 16), 1661f1fe5dffSRadu Pirea (NXP OSS) .sec_1_0 = 1662f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 0, 2), 1663f1fe5dffSRadu Pirea (NXP OSS) .sec_4_2 = 1664f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 2, 3), 1665f1fe5dffSRadu Pirea (NXP OSS) .nsec_15_0 = 1666f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9063, MDIO_MMD_VEND1, 0, 16), 1667f1fe5dffSRadu Pirea (NXP OSS) .nsec_29_16 = 1668f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9064, MDIO_MMD_VEND1, 0, 14), 1669f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_0 = 0x1071, 1670f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_1 = 0x1072, 1671f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_2 = 0x1073, 1672f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_3 = 0x1074, 1673f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_ctrl = 0x1075, 1674f1fe5dffSRadu Pirea (NXP OSS) .cable_test = 0x8360, 1675f1fe5dffSRadu Pirea (NXP OSS) .cable_test_valid = 1676f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 15, 1), 1677f1fe5dffSRadu Pirea (NXP OSS) .cable_test_result = 1678f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 0, 3), 1679f1fe5dffSRadu Pirea (NXP OSS) }; 1680f1fe5dffSRadu Pirea (NXP OSS) 1681f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1120_phy_data = { 1682f1fe5dffSRadu Pirea (NXP OSS) .regmap = &tja1120_regmap, 1683f1fe5dffSRadu Pirea (NXP OSS) .stats = tja1120_hw_stats, 1684f1fe5dffSRadu Pirea (NXP OSS) .n_stats = ARRAY_SIZE(tja1120_hw_stats), 1685f1fe5dffSRadu Pirea (NXP OSS) .ptp_clk_period = PTP_CLK_PERIOD_1000BT1, 1686*b0b2247dSRadu Pirea (NXP OSS) .ext_ts_both_edges = true, 1687f1fe5dffSRadu Pirea (NXP OSS) .counters_enable = tja1120_counters_enable, 1688f1fe5dffSRadu Pirea (NXP OSS) .ptp_init = tja1120_ptp_init, 1689f1fe5dffSRadu Pirea (NXP OSS) .ptp_enable = tja1120_ptp_enable, 1690f1fe5dffSRadu Pirea (NXP OSS) }; 1691f1fe5dffSRadu Pirea (NXP OSS) 1692b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = { 1693b050f2f1SRadu Pirea (NXP OSS) { 1694b050f2f1SRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), 1695b050f2f1SRadu Pirea (NXP OSS) .name = "NXP C45 TJA1103", 1696369da333SRadu Pirea (NXP OSS) .get_features = nxp_c45_get_features, 16976c0c85daSRadu Pirea (NXP OSS) .driver_data = &tja1103_phy_data, 1698b050f2f1SRadu Pirea (NXP OSS) .probe = nxp_c45_probe, 1699b050f2f1SRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset, 1700ac0687e8SRadu Pirea (NXP OSS) .config_aneg = genphy_c45_config_aneg, 1701b050f2f1SRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init, 1702b2f0ca00SRadu Pirea (NXP OSS) .config_intr = nxp_c45_config_intr, 1703b2f0ca00SRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt, 1704ac0687e8SRadu Pirea (NXP OSS) .read_status = genphy_c45_read_status, 1705b050f2f1SRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend, 1706b050f2f1SRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume, 1707b050f2f1SRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count, 1708b050f2f1SRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings, 1709b050f2f1SRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats, 1710b050f2f1SRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start, 1711b050f2f1SRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status, 1712b050f2f1SRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback, 1713b050f2f1SRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi, 1714b050f2f1SRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max, 1715a4506722SRadu Pirea (OSS) .remove = nxp_c45_remove, 1716b050f2f1SRadu Pirea (NXP OSS) }, 1717f1fe5dffSRadu Pirea (NXP OSS) { 1718f1fe5dffSRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120), 1719f1fe5dffSRadu Pirea (NXP OSS) .name = "NXP C45 TJA1120", 1720f1fe5dffSRadu Pirea (NXP OSS) .get_features = nxp_c45_get_features, 1721f1fe5dffSRadu Pirea (NXP OSS) .driver_data = &tja1120_phy_data, 1722f1fe5dffSRadu Pirea (NXP OSS) .probe = nxp_c45_probe, 1723f1fe5dffSRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset, 1724f1fe5dffSRadu Pirea (NXP OSS) .config_aneg = genphy_c45_config_aneg, 1725f1fe5dffSRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init, 1726f1fe5dffSRadu Pirea (NXP OSS) .config_intr = nxp_c45_config_intr, 1727f1fe5dffSRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt, 1728f1fe5dffSRadu Pirea (NXP OSS) .read_status = genphy_c45_read_status, 1729f1fe5dffSRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend, 1730f1fe5dffSRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume, 1731f1fe5dffSRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count, 1732f1fe5dffSRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings, 1733f1fe5dffSRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats, 1734f1fe5dffSRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start, 1735f1fe5dffSRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status, 1736f1fe5dffSRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback, 1737f1fe5dffSRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi, 1738f1fe5dffSRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max, 1739f1fe5dffSRadu Pirea (NXP OSS) .remove = nxp_c45_remove, 1740f1fe5dffSRadu Pirea (NXP OSS) }, 1741b050f2f1SRadu Pirea (NXP OSS) }; 1742b050f2f1SRadu Pirea (NXP OSS) 1743b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver); 1744b050f2f1SRadu Pirea (NXP OSS) 1745b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = { 1746b050f2f1SRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) }, 1747f1fe5dffSRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120) }, 1748b050f2f1SRadu Pirea (NXP OSS) { /*sentinel*/ }, 1749b050f2f1SRadu Pirea (NXP OSS) }; 1750b050f2f1SRadu Pirea (NXP OSS) 1751b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl); 1752b050f2f1SRadu Pirea (NXP OSS) 1753b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>"); 1754b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver"); 1755b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2"); 1756