Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: dsa: microchip: ptp: add the posix clock support

This patch implement routines (adjfine, adjtime, gettime and settime)
for manipulating the chip's PTP clock. It registers the ptp caps
to posix clock register.

Signed-off-by: Christian Eggers <ceggers@arri.de>
Co-developed-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com> # mostly api
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Christian Eggers and committed by
David S. Miller
eac1ea20 72863e08

+374 -1
+11
drivers/net/dsa/microchip/Kconfig
··· 11 11 config NET_DSA_MICROCHIP_KSZ9477_I2C 12 12 tristate "KSZ series I2C connected switch driver" 13 13 depends on NET_DSA_MICROCHIP_KSZ_COMMON && I2C 14 + depends on PTP_1588_CLOCK_OPTIONAL 14 15 select REGMAP_I2C 15 16 help 16 17 Select to enable support for registering switches configured through I2C. ··· 19 18 config NET_DSA_MICROCHIP_KSZ_SPI 20 19 tristate "KSZ series SPI connected switch driver" 21 20 depends on NET_DSA_MICROCHIP_KSZ_COMMON && SPI 21 + depends on PTP_1588_CLOCK_OPTIONAL 22 22 select REGMAP_SPI 23 23 help 24 24 Select to enable support for registering switches configured through SPI. 25 + 26 + config NET_DSA_MICROCHIP_KSZ_PTP 27 + bool "Support for the PTP clock on the KSZ9563/LAN937x Ethernet Switch" 28 + depends on NET_DSA_MICROCHIP_KSZ_COMMON && PTP_1588_CLOCK 29 + help 30 + Select to enable support for timestamping & PTP clock manipulation in 31 + KSZ8563/KSZ9563/LAN937x series of switches. KSZ9563/KSZ8563 supports 32 + only one step timestamping. LAN937x switch supports both one step and 33 + two step timestamping. 25 34 26 35 config NET_DSA_MICROCHIP_KSZ8863_SMI 27 36 tristate "KSZ series SMI connected switch driver"
+5
drivers/net/dsa/microchip/Makefile
··· 4 4 ksz_switch-objs += ksz9477.o 5 5 ksz_switch-objs += ksz8795.o 6 6 ksz_switch-objs += lan937x_main.o 7 + 8 + ifdef CONFIG_NET_DSA_MICROCHIP_KSZ_PTP 9 + ksz_switch-objs += ksz_ptp.o 10 + endif 11 + 7 12 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C) += ksz9477_i2c.o 8 13 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_SPI) += ksz_spi.o 9 14 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI) += ksz8863_smi.o
+12 -1
drivers/net/dsa/microchip/ksz_common.c
··· 25 25 #include <net/switchdev.h> 26 26 27 27 #include "ksz_common.h" 28 + #include "ksz_ptp.h" 28 29 #include "ksz8.h" 29 30 #include "ksz9477.h" 30 31 #include "lan937x.h" ··· 2103 2102 } 2104 2103 } 2105 2104 2105 + ret = ksz_ptp_clock_register(ds); 2106 + if (ret) { 2107 + dev_err(dev->dev, "Failed to register PTP clock: %d\n", ret); 2108 + goto out_pirq; 2109 + } 2110 + 2106 2111 ret = ksz_mdio_register(dev); 2107 2112 if (ret < 0) { 2108 2113 dev_err(dev->dev, "failed to register the mdio"); 2109 - goto out_pirq; 2114 + goto out_ptp_clock_unregister; 2110 2115 } 2111 2116 2112 2117 /* start switch */ ··· 2121 2114 2122 2115 return 0; 2123 2116 2117 + out_ptp_clock_unregister: 2118 + ksz_ptp_clock_unregister(ds); 2124 2119 out_pirq: 2125 2120 if (dev->irq > 0) 2126 2121 dsa_switch_for_each_user_port(dp, dev->ds) ··· 2138 2129 { 2139 2130 struct ksz_device *dev = ds->priv; 2140 2131 struct dsa_port *dp; 2132 + 2133 + ksz_ptp_clock_unregister(ds); 2141 2134 2142 2135 if (dev->irq > 0) { 2143 2136 dsa_switch_for_each_user_port(dp, dev->ds)
+16
drivers/net/dsa/microchip/ksz_common.h
··· 15 15 #include <net/dsa.h> 16 16 #include <linux/irq.h> 17 17 18 + #include "ksz_ptp.h" 19 + 18 20 #define KSZ_MAX_NUM_PORTS 8 19 21 20 22 struct ksz_device; ··· 142 140 u16 port_mask; 143 141 struct mutex lock_irq; /* IRQ Access */ 144 142 struct ksz_irq girq; 143 + struct ksz_ptp_data ptp_data; 145 144 }; 146 145 147 146 /* List of supported models */ ··· 441 438 ret = regmap_write(dev->regmap[2], reg, value); 442 439 if (ret) 443 440 dev_err(dev->dev, "can't write 32bit reg: 0x%x %pe\n", reg, 441 + ERR_PTR(ret)); 442 + 443 + return ret; 444 + } 445 + 446 + static inline int ksz_rmw16(struct ksz_device *dev, u32 reg, u16 mask, 447 + u16 value) 448 + { 449 + int ret; 450 + 451 + ret = regmap_update_bits(dev->regmap[1], reg, mask, value); 452 + if (ret) 453 + dev_err(dev->dev, "can't rmw 16bit reg 0x%x: %pe\n", reg, 444 454 ERR_PTR(ret)); 445 455 446 456 return ret;
+236
drivers/net/dsa/microchip/ksz_ptp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Microchip KSZ PTP Implementation 3 + * 4 + * Copyright (C) 2020 ARRI Lighting 5 + * Copyright (C) 2022 Microchip Technology Inc. 6 + */ 7 + 8 + #include <linux/kernel.h> 9 + #include <linux/ptp_classify.h> 10 + #include <linux/ptp_clock_kernel.h> 11 + 12 + #include "ksz_common.h" 13 + #include "ksz_ptp.h" 14 + #include "ksz_ptp_reg.h" 15 + 16 + #define ptp_caps_to_data(d) container_of((d), struct ksz_ptp_data, caps) 17 + #define ptp_data_to_ksz_dev(d) container_of((d), struct ksz_device, ptp_data) 18 + 19 + /* Sub-nanoseconds-adj,max * sub-nanoseconds / 40ns * 1ns 20 + * = (2^30-1) * (2 ^ 32) / 40 ns * 1 ns = 6249999 21 + */ 22 + #define KSZ_MAX_DRIFT_CORR 6249999 23 + 24 + #define KSZ_PTP_INC_NS 40ULL /* HW clock is incremented every 40 ns (by 40) */ 25 + #define KSZ_PTP_SUBNS_BITS 32 26 + 27 + static int _ksz_ptp_gettime(struct ksz_device *dev, struct timespec64 *ts) 28 + { 29 + u32 nanoseconds; 30 + u32 seconds; 31 + u8 phase; 32 + int ret; 33 + 34 + /* Copy current PTP clock into shadow registers and read */ 35 + ret = ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_READ_TIME, PTP_READ_TIME); 36 + if (ret) 37 + return ret; 38 + 39 + ret = ksz_read8(dev, REG_PTP_RTC_SUB_NANOSEC__2, &phase); 40 + if (ret) 41 + return ret; 42 + 43 + ret = ksz_read32(dev, REG_PTP_RTC_NANOSEC, &nanoseconds); 44 + if (ret) 45 + return ret; 46 + 47 + ret = ksz_read32(dev, REG_PTP_RTC_SEC, &seconds); 48 + if (ret) 49 + return ret; 50 + 51 + ts->tv_sec = seconds; 52 + ts->tv_nsec = nanoseconds + phase * 8; 53 + 54 + return 0; 55 + } 56 + 57 + static int ksz_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) 58 + { 59 + struct ksz_ptp_data *ptp_data = ptp_caps_to_data(ptp); 60 + struct ksz_device *dev = ptp_data_to_ksz_dev(ptp_data); 61 + int ret; 62 + 63 + mutex_lock(&ptp_data->lock); 64 + ret = _ksz_ptp_gettime(dev, ts); 65 + mutex_unlock(&ptp_data->lock); 66 + 67 + return ret; 68 + } 69 + 70 + static int ksz_ptp_settime(struct ptp_clock_info *ptp, 71 + const struct timespec64 *ts) 72 + { 73 + struct ksz_ptp_data *ptp_data = ptp_caps_to_data(ptp); 74 + struct ksz_device *dev = ptp_data_to_ksz_dev(ptp_data); 75 + int ret; 76 + 77 + mutex_lock(&ptp_data->lock); 78 + 79 + /* Write to shadow registers and Load PTP clock */ 80 + ret = ksz_write16(dev, REG_PTP_RTC_SUB_NANOSEC__2, PTP_RTC_0NS); 81 + if (ret) 82 + goto unlock; 83 + 84 + ret = ksz_write32(dev, REG_PTP_RTC_NANOSEC, ts->tv_nsec); 85 + if (ret) 86 + goto unlock; 87 + 88 + ret = ksz_write32(dev, REG_PTP_RTC_SEC, ts->tv_sec); 89 + if (ret) 90 + goto unlock; 91 + 92 + ret = ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_LOAD_TIME, PTP_LOAD_TIME); 93 + 94 + unlock: 95 + mutex_unlock(&ptp_data->lock); 96 + 97 + return ret; 98 + } 99 + 100 + static int ksz_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 101 + { 102 + struct ksz_ptp_data *ptp_data = ptp_caps_to_data(ptp); 103 + struct ksz_device *dev = ptp_data_to_ksz_dev(ptp_data); 104 + u64 base, adj; 105 + bool negative; 106 + u32 data32; 107 + int ret; 108 + 109 + mutex_lock(&ptp_data->lock); 110 + 111 + if (scaled_ppm) { 112 + base = KSZ_PTP_INC_NS << KSZ_PTP_SUBNS_BITS; 113 + negative = diff_by_scaled_ppm(base, scaled_ppm, &adj); 114 + 115 + data32 = (u32)adj; 116 + data32 &= PTP_SUBNANOSEC_M; 117 + if (!negative) 118 + data32 |= PTP_RATE_DIR; 119 + 120 + ret = ksz_write32(dev, REG_PTP_SUBNANOSEC_RATE, data32); 121 + if (ret) 122 + goto unlock; 123 + 124 + ret = ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_CLK_ADJ_ENABLE, 125 + PTP_CLK_ADJ_ENABLE); 126 + if (ret) 127 + goto unlock; 128 + } else { 129 + ret = ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_CLK_ADJ_ENABLE, 0); 130 + if (ret) 131 + goto unlock; 132 + } 133 + 134 + unlock: 135 + mutex_unlock(&ptp_data->lock); 136 + return ret; 137 + } 138 + 139 + static int ksz_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) 140 + { 141 + struct ksz_ptp_data *ptp_data = ptp_caps_to_data(ptp); 142 + struct ksz_device *dev = ptp_data_to_ksz_dev(ptp_data); 143 + s32 sec, nsec; 144 + u16 data16; 145 + int ret; 146 + 147 + mutex_lock(&ptp_data->lock); 148 + 149 + /* do not use ns_to_timespec64(), 150 + * both sec and nsec are subtracted by hw 151 + */ 152 + sec = div_s64_rem(delta, NSEC_PER_SEC, &nsec); 153 + 154 + ret = ksz_write32(dev, REG_PTP_RTC_NANOSEC, abs(nsec)); 155 + if (ret) 156 + goto unlock; 157 + 158 + ret = ksz_write32(dev, REG_PTP_RTC_SEC, abs(sec)); 159 + if (ret) 160 + goto unlock; 161 + 162 + ret = ksz_read16(dev, REG_PTP_CLK_CTRL, &data16); 163 + if (ret) 164 + goto unlock; 165 + 166 + data16 |= PTP_STEP_ADJ; 167 + 168 + /* PTP_STEP_DIR -- 0: subtract, 1: add */ 169 + if (delta < 0) 170 + data16 &= ~PTP_STEP_DIR; 171 + else 172 + data16 |= PTP_STEP_DIR; 173 + 174 + ret = ksz_write16(dev, REG_PTP_CLK_CTRL, data16); 175 + 176 + unlock: 177 + mutex_unlock(&ptp_data->lock); 178 + return ret; 179 + } 180 + 181 + static int ksz_ptp_start_clock(struct ksz_device *dev) 182 + { 183 + return ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_CLK_ENABLE, PTP_CLK_ENABLE); 184 + } 185 + 186 + int ksz_ptp_clock_register(struct dsa_switch *ds) 187 + { 188 + struct ksz_device *dev = ds->priv; 189 + struct ksz_ptp_data *ptp_data; 190 + int ret; 191 + 192 + ptp_data = &dev->ptp_data; 193 + mutex_init(&ptp_data->lock); 194 + 195 + ptp_data->caps.owner = THIS_MODULE; 196 + snprintf(ptp_data->caps.name, 16, "Microchip Clock"); 197 + ptp_data->caps.max_adj = KSZ_MAX_DRIFT_CORR; 198 + ptp_data->caps.gettime64 = ksz_ptp_gettime; 199 + ptp_data->caps.settime64 = ksz_ptp_settime; 200 + ptp_data->caps.adjfine = ksz_ptp_adjfine; 201 + ptp_data->caps.adjtime = ksz_ptp_adjtime; 202 + 203 + ret = ksz_ptp_start_clock(dev); 204 + if (ret) 205 + return ret; 206 + 207 + /* Currently only P2P mode is supported. When 802_1AS bit is set, it 208 + * forwards all PTP packets to host port and none to other ports. 209 + */ 210 + ret = ksz_rmw16(dev, REG_PTP_MSG_CONF1, PTP_TC_P2P | PTP_802_1AS, 211 + PTP_TC_P2P | PTP_802_1AS); 212 + if (ret) 213 + return ret; 214 + 215 + ptp_data->clock = ptp_clock_register(&ptp_data->caps, dev->dev); 216 + if (IS_ERR_OR_NULL(ptp_data->clock)) 217 + return PTR_ERR(ptp_data->clock); 218 + 219 + return 0; 220 + } 221 + 222 + void ksz_ptp_clock_unregister(struct dsa_switch *ds) 223 + { 224 + struct ksz_device *dev = ds->priv; 225 + struct ksz_ptp_data *ptp_data; 226 + 227 + ptp_data = &dev->ptp_data; 228 + 229 + if (ptp_data->clock) 230 + ptp_clock_unregister(ptp_data->clock); 231 + } 232 + 233 + MODULE_AUTHOR("Christian Eggers <ceggers@arri.de>"); 234 + MODULE_AUTHOR("Arun Ramadoss <arun.ramadoss@microchip.com>"); 235 + MODULE_DESCRIPTION("PTP support for KSZ switch"); 236 + MODULE_LICENSE("GPL");
+42
drivers/net/dsa/microchip/ksz_ptp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Microchip KSZ PTP Implementation 3 + * 4 + * Copyright (C) 2020 ARRI Lighting 5 + * Copyright (C) 2022 Microchip Technology Inc. 6 + */ 7 + 8 + #ifndef _NET_DSA_DRIVERS_KSZ_PTP_H 9 + #define _NET_DSA_DRIVERS_KSZ_PTP_H 10 + 11 + #if IS_ENABLED(CONFIG_NET_DSA_MICROCHIP_KSZ_PTP) 12 + 13 + #include <linux/ptp_clock_kernel.h> 14 + 15 + struct ksz_ptp_data { 16 + struct ptp_clock_info caps; 17 + struct ptp_clock *clock; 18 + /* Serializes all operations on the PTP hardware clock */ 19 + struct mutex lock; 20 + }; 21 + 22 + int ksz_ptp_clock_register(struct dsa_switch *ds); 23 + 24 + void ksz_ptp_clock_unregister(struct dsa_switch *ds); 25 + 26 + #else 27 + 28 + struct ksz_ptp_data { 29 + /* Serializes all operations on the PTP hardware clock */ 30 + struct mutex lock; 31 + }; 32 + 33 + static inline int ksz_ptp_clock_register(struct dsa_switch *ds) 34 + { 35 + return 0; 36 + } 37 + 38 + static inline void ksz_ptp_clock_unregister(struct dsa_switch *ds) { } 39 + 40 + #endif /* End of CONFIG_NET_DSA_MICROCHIP_KSZ_PTP */ 41 + 42 + #endif
+52
drivers/net/dsa/microchip/ksz_ptp_reg.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Microchip KSZ PTP register definitions 3 + * Copyright (C) 2022 Microchip Technology Inc. 4 + */ 5 + 6 + #ifndef __KSZ_PTP_REGS_H 7 + #define __KSZ_PTP_REGS_H 8 + 9 + /* 5 - PTP Clock */ 10 + #define REG_PTP_CLK_CTRL 0x0500 11 + 12 + #define PTP_STEP_ADJ BIT(6) 13 + #define PTP_STEP_DIR BIT(5) 14 + #define PTP_READ_TIME BIT(4) 15 + #define PTP_LOAD_TIME BIT(3) 16 + #define PTP_CLK_ADJ_ENABLE BIT(2) 17 + #define PTP_CLK_ENABLE BIT(1) 18 + #define PTP_CLK_RESET BIT(0) 19 + 20 + #define REG_PTP_RTC_SUB_NANOSEC__2 0x0502 21 + 22 + #define PTP_RTC_SUB_NANOSEC_M 0x0007 23 + #define PTP_RTC_0NS 0x00 24 + 25 + #define REG_PTP_RTC_NANOSEC 0x0504 26 + 27 + #define REG_PTP_RTC_SEC 0x0508 28 + 29 + #define REG_PTP_SUBNANOSEC_RATE 0x050C 30 + 31 + #define PTP_SUBNANOSEC_M 0x3FFFFFFF 32 + #define PTP_RATE_DIR BIT(31) 33 + #define PTP_TMP_RATE_ENABLE BIT(30) 34 + 35 + #define REG_PTP_SUBNANOSEC_RATE_L 0x050E 36 + 37 + #define REG_PTP_RATE_DURATION 0x0510 38 + #define REG_PTP_RATE_DURATION_H 0x0510 39 + #define REG_PTP_RATE_DURATION_L 0x0512 40 + 41 + #define REG_PTP_MSG_CONF1 0x0514 42 + 43 + #define PTP_802_1AS BIT(7) 44 + #define PTP_ENABLE BIT(6) 45 + #define PTP_ETH_ENABLE BIT(5) 46 + #define PTP_IPV4_UDP_ENABLE BIT(4) 47 + #define PTP_IPV6_UDP_ENABLE BIT(3) 48 + #define PTP_TC_P2P BIT(2) 49 + #define PTP_MASTER BIT(1) 50 + #define PTP_1STEP BIT(0) 51 + 52 + #endif