1 // SPDX-License-Identifier: GPL-2.0 2 /* Renesas R-Car Gen4 gPTP device driver 3 * 4 * Copyright (C) 2022 Renesas Electronics Corporation 5 */ 6 7 #include <linux/err.h> 8 #include <linux/etherdevice.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/slab.h> 13 14 #include "rcar_gen4_ptp.h" 15 #define ptp_to_priv(ptp) container_of(ptp, struct rcar_gen4_ptp_private, info) 16 17 static const struct rcar_gen4_ptp_reg_offset gen4_offs = { 18 .enable = PTPTMEC, 19 .disable = PTPTMDC, 20 .increment = PTPTIVC0, 21 .config_t0 = PTPTOVC00, 22 .config_t1 = PTPTOVC10, 23 .config_t2 = PTPTOVC20, 24 .monitor_t0 = PTPGPTPTM00, 25 .monitor_t1 = PTPGPTPTM10, 26 .monitor_t2 = PTPGPTPTM20, 27 }; 28 29 static int rcar_gen4_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 30 { 31 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp); 32 bool neg_adj = scaled_ppm < 0 ? true : false; 33 s64 addend = ptp_priv->default_addend; 34 s64 diff; 35 36 if (neg_adj) 37 scaled_ppm = -scaled_ppm; 38 diff = div_s64(addend * scaled_ppm_to_ppb(scaled_ppm), NSEC_PER_SEC); 39 addend = neg_adj ? addend - diff : addend + diff; 40 41 iowrite32(addend, ptp_priv->addr + ptp_priv->offs->increment); 42 43 return 0; 44 } 45 46 /* Caller must hold the lock */ 47 static void _rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp, 48 struct timespec64 *ts) 49 { 50 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp); 51 52 ts->tv_nsec = ioread32(ptp_priv->addr + ptp_priv->offs->monitor_t0); 53 ts->tv_sec = ioread32(ptp_priv->addr + ptp_priv->offs->monitor_t1) | 54 ((s64)ioread32(ptp_priv->addr + ptp_priv->offs->monitor_t2) << 32); 55 } 56 57 static int rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp, 58 struct timespec64 *ts) 59 { 60 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp); 61 unsigned long flags; 62 63 spin_lock_irqsave(&ptp_priv->lock, flags); 64 _rcar_gen4_ptp_gettime(ptp, ts); 65 spin_unlock_irqrestore(&ptp_priv->lock, flags); 66 67 return 0; 68 } 69 70 /* Caller must hold the lock */ 71 static void _rcar_gen4_ptp_settime(struct ptp_clock_info *ptp, 72 const struct timespec64 *ts) 73 { 74 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp); 75 76 iowrite32(1, ptp_priv->addr + ptp_priv->offs->disable); 77 iowrite32(0, ptp_priv->addr + ptp_priv->offs->config_t2); 78 iowrite32(0, ptp_priv->addr + ptp_priv->offs->config_t1); 79 iowrite32(0, ptp_priv->addr + ptp_priv->offs->config_t0); 80 iowrite32(1, ptp_priv->addr + ptp_priv->offs->enable); 81 iowrite32(ts->tv_sec >> 32, ptp_priv->addr + ptp_priv->offs->config_t2); 82 iowrite32(ts->tv_sec, ptp_priv->addr + ptp_priv->offs->config_t1); 83 iowrite32(ts->tv_nsec, ptp_priv->addr + ptp_priv->offs->config_t0); 84 } 85 86 static int rcar_gen4_ptp_settime(struct ptp_clock_info *ptp, 87 const struct timespec64 *ts) 88 { 89 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp); 90 unsigned long flags; 91 92 spin_lock_irqsave(&ptp_priv->lock, flags); 93 _rcar_gen4_ptp_settime(ptp, ts); 94 spin_unlock_irqrestore(&ptp_priv->lock, flags); 95 96 return 0; 97 } 98 99 static int rcar_gen4_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) 100 { 101 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp); 102 struct timespec64 ts; 103 unsigned long flags; 104 s64 now; 105 106 spin_lock_irqsave(&ptp_priv->lock, flags); 107 _rcar_gen4_ptp_gettime(ptp, &ts); 108 now = ktime_to_ns(timespec64_to_ktime(ts)); 109 ts = ns_to_timespec64(now + delta); 110 _rcar_gen4_ptp_settime(ptp, &ts); 111 spin_unlock_irqrestore(&ptp_priv->lock, flags); 112 113 return 0; 114 } 115 116 static int rcar_gen4_ptp_enable(struct ptp_clock_info *ptp, 117 struct ptp_clock_request *rq, int on) 118 { 119 return -EOPNOTSUPP; 120 } 121 122 static struct ptp_clock_info rcar_gen4_ptp_info = { 123 .owner = THIS_MODULE, 124 .name = "rcar_gen4_ptp", 125 .max_adj = 50000000, 126 .adjfine = rcar_gen4_ptp_adjfine, 127 .adjtime = rcar_gen4_ptp_adjtime, 128 .gettime64 = rcar_gen4_ptp_gettime, 129 .settime64 = rcar_gen4_ptp_settime, 130 .enable = rcar_gen4_ptp_enable, 131 }; 132 133 static int rcar_gen4_ptp_set_offs(struct rcar_gen4_ptp_private *ptp_priv, 134 enum rcar_gen4_ptp_reg_layout layout) 135 { 136 if (layout != RCAR_GEN4_PTP_REG_LAYOUT) 137 return -EINVAL; 138 139 ptp_priv->offs = &gen4_offs; 140 141 return 0; 142 } 143 144 static s64 rcar_gen4_ptp_rate_to_increment(u32 rate) 145 { 146 /* Timer increment in ns. 147 * bit[31:27] - integer 148 * bit[26:0] - decimal 149 * increment[ns] = perid[ns] * 2^27 => (1ns * 2^27) / rate[hz] 150 */ 151 return div_s64(1000000000LL << 27, rate); 152 } 153 154 int rcar_gen4_ptp_register(struct rcar_gen4_ptp_private *ptp_priv, 155 enum rcar_gen4_ptp_reg_layout layout, u32 rate) 156 { 157 int ret; 158 159 if (ptp_priv->initialized) 160 return 0; 161 162 spin_lock_init(&ptp_priv->lock); 163 164 ret = rcar_gen4_ptp_set_offs(ptp_priv, layout); 165 if (ret) 166 return ret; 167 168 ptp_priv->default_addend = rcar_gen4_ptp_rate_to_increment(rate); 169 iowrite32(ptp_priv->default_addend, ptp_priv->addr + ptp_priv->offs->increment); 170 ptp_priv->clock = ptp_clock_register(&ptp_priv->info, NULL); 171 if (IS_ERR(ptp_priv->clock)) 172 return PTR_ERR(ptp_priv->clock); 173 174 iowrite32(0x01, ptp_priv->addr + ptp_priv->offs->enable); 175 ptp_priv->initialized = true; 176 177 return 0; 178 } 179 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_register); 180 181 int rcar_gen4_ptp_unregister(struct rcar_gen4_ptp_private *ptp_priv) 182 { 183 iowrite32(1, ptp_priv->addr + ptp_priv->offs->disable); 184 185 return ptp_clock_unregister(ptp_priv->clock); 186 } 187 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_unregister); 188 189 struct rcar_gen4_ptp_private *rcar_gen4_ptp_alloc(struct platform_device *pdev) 190 { 191 struct rcar_gen4_ptp_private *ptp; 192 193 ptp = devm_kzalloc(&pdev->dev, sizeof(*ptp), GFP_KERNEL); 194 if (!ptp) 195 return NULL; 196 197 ptp->info = rcar_gen4_ptp_info; 198 199 return ptp; 200 } 201 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_alloc); 202 203 MODULE_AUTHOR("Yoshihiro Shimoda"); 204 MODULE_DESCRIPTION("Renesas R-Car Gen4 gPTP driver"); 205 MODULE_LICENSE("GPL"); 206