157a10d8cSMin Li // SPDX-License-Identifier: GPL-2.0 257a10d8cSMin Li // 357a10d8cSMin Li // Copyright (C) 2018 Integrated Device Technology, Inc 457a10d8cSMin Li // 557a10d8cSMin Li 657a10d8cSMin Li #define pr_fmt(fmt) "IDT_82p33xxx: " fmt 757a10d8cSMin Li 857a10d8cSMin Li #include <linux/firmware.h> 9013a3e7cSMin Li #include <linux/platform_device.h> 1057a10d8cSMin Li #include <linux/module.h> 1157a10d8cSMin Li #include <linux/ptp_clock_kernel.h> 1257a10d8cSMin Li #include <linux/delay.h> 13013a3e7cSMin Li #include <linux/jiffies.h> 1457a10d8cSMin Li #include <linux/kernel.h> 1557a10d8cSMin Li #include <linux/timekeeping.h> 1657a10d8cSMin Li #include <linux/bitops.h> 17013a3e7cSMin Li #include <linux/of.h> 18013a3e7cSMin Li #include <linux/mfd/rsmu.h> 19013a3e7cSMin Li #include <linux/mfd/idt82p33_reg.h> 2057a10d8cSMin Li 2157a10d8cSMin Li #include "ptp_private.h" 2257a10d8cSMin Li #include "ptp_idt82p33.h" 2357a10d8cSMin Li 2457a10d8cSMin Li MODULE_DESCRIPTION("Driver for IDT 82p33xxx clock devices"); 2557a10d8cSMin Li MODULE_AUTHOR("IDT support-1588 <IDT-support-1588@lm.renesas.com>"); 2657a10d8cSMin Li MODULE_VERSION("1.0"); 2757a10d8cSMin Li MODULE_LICENSE("GPL"); 28e014ae39SMin Li MODULE_FIRMWARE(FW_FILENAME); 2957a10d8cSMin Li 30*ad3cc776SMin Li #define EXTTS_PERIOD_MS (95) 31*ad3cc776SMin Li 3257a10d8cSMin Li /* Module Parameters */ 33d30e1c3dSYueHaibing static u32 phase_snap_threshold = SNAP_THRESHOLD_NS; 3457a10d8cSMin Li module_param(phase_snap_threshold, uint, 0); 3557a10d8cSMin Li MODULE_PARM_DESC(phase_snap_threshold, 36013a3e7cSMin Li "threshold (10000ns by default) below which adjtime would use double dco"); 37013a3e7cSMin Li 38013a3e7cSMin Li static char *firmware; 39013a3e7cSMin Li module_param(firmware, charp, 0); 40013a3e7cSMin Li 41*ad3cc776SMin Li static struct ptp_pin_desc pin_config[MAX_PHC_PLL][MAX_TRIG_CLK]; 42*ad3cc776SMin Li 43013a3e7cSMin Li static inline int idt82p33_read(struct idt82p33 *idt82p33, u16 regaddr, 44013a3e7cSMin Li u8 *buf, u16 count) 45013a3e7cSMin Li { 46013a3e7cSMin Li return regmap_bulk_read(idt82p33->regmap, regaddr, buf, count); 47013a3e7cSMin Li } 48013a3e7cSMin Li 49013a3e7cSMin Li static inline int idt82p33_write(struct idt82p33 *idt82p33, u16 regaddr, 50013a3e7cSMin Li u8 *buf, u16 count) 51013a3e7cSMin Li { 52013a3e7cSMin Li return regmap_bulk_write(idt82p33->regmap, regaddr, buf, count); 53013a3e7cSMin Li } 5457a10d8cSMin Li 5557a10d8cSMin Li static void idt82p33_byte_array_to_timespec(struct timespec64 *ts, 5657a10d8cSMin Li u8 buf[TOD_BYTE_COUNT]) 5757a10d8cSMin Li { 5857a10d8cSMin Li time64_t sec; 5957a10d8cSMin Li s32 nsec; 6057a10d8cSMin Li u8 i; 6157a10d8cSMin Li 6257a10d8cSMin Li nsec = buf[3]; 6357a10d8cSMin Li for (i = 0; i < 3; i++) { 6457a10d8cSMin Li nsec <<= 8; 6557a10d8cSMin Li nsec |= buf[2 - i]; 6657a10d8cSMin Li } 6757a10d8cSMin Li 6857a10d8cSMin Li sec = buf[9]; 6957a10d8cSMin Li for (i = 0; i < 5; i++) { 7057a10d8cSMin Li sec <<= 8; 7157a10d8cSMin Li sec |= buf[8 - i]; 7257a10d8cSMin Li } 7357a10d8cSMin Li 7457a10d8cSMin Li ts->tv_sec = sec; 7557a10d8cSMin Li ts->tv_nsec = nsec; 7657a10d8cSMin Li } 7757a10d8cSMin Li 7857a10d8cSMin Li static void idt82p33_timespec_to_byte_array(struct timespec64 const *ts, 7957a10d8cSMin Li u8 buf[TOD_BYTE_COUNT]) 8057a10d8cSMin Li { 8157a10d8cSMin Li time64_t sec; 8257a10d8cSMin Li s32 nsec; 8357a10d8cSMin Li u8 i; 8457a10d8cSMin Li 8557a10d8cSMin Li nsec = ts->tv_nsec; 8657a10d8cSMin Li sec = ts->tv_sec; 8757a10d8cSMin Li 8857a10d8cSMin Li for (i = 0; i < 4; i++) { 8957a10d8cSMin Li buf[i] = nsec & 0xff; 9057a10d8cSMin Li nsec >>= 8; 9157a10d8cSMin Li } 9257a10d8cSMin Li 9357a10d8cSMin Li for (i = 4; i < TOD_BYTE_COUNT; i++) { 9457a10d8cSMin Li buf[i] = sec & 0xff; 9557a10d8cSMin Li sec >>= 8; 9657a10d8cSMin Li } 9757a10d8cSMin Li } 9857a10d8cSMin Li 9957a10d8cSMin Li static int idt82p33_dpll_set_mode(struct idt82p33_channel *channel, 10057a10d8cSMin Li enum pll_mode mode) 10157a10d8cSMin Li { 10257a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 10357a10d8cSMin Li u8 dpll_mode; 10457a10d8cSMin Li int err; 10557a10d8cSMin Li 10657a10d8cSMin Li if (channel->pll_mode == mode) 10757a10d8cSMin Li return 0; 10857a10d8cSMin Li 10957a10d8cSMin Li err = idt82p33_read(idt82p33, channel->dpll_mode_cnfg, 11057a10d8cSMin Li &dpll_mode, sizeof(dpll_mode)); 11157a10d8cSMin Li if (err) 11257a10d8cSMin Li return err; 11357a10d8cSMin Li 11457a10d8cSMin Li dpll_mode &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT); 11557a10d8cSMin Li 11657a10d8cSMin Li dpll_mode |= (mode << PLL_MODE_SHIFT); 11757a10d8cSMin Li 11857a10d8cSMin Li err = idt82p33_write(idt82p33, channel->dpll_mode_cnfg, 11957a10d8cSMin Li &dpll_mode, sizeof(dpll_mode)); 12057a10d8cSMin Li if (err) 12157a10d8cSMin Li return err; 12257a10d8cSMin Li 123013a3e7cSMin Li channel->pll_mode = mode; 12457a10d8cSMin Li 12557a10d8cSMin Li return 0; 12657a10d8cSMin Li } 12757a10d8cSMin Li 128*ad3cc776SMin Li static int idt82p33_set_tod_trigger(struct idt82p33_channel *channel, 129*ad3cc776SMin Li u8 trigger, bool write) 130*ad3cc776SMin Li { 131*ad3cc776SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 132*ad3cc776SMin Li int err; 133*ad3cc776SMin Li u8 cfg; 134*ad3cc776SMin Li 135*ad3cc776SMin Li if (trigger > WR_TRIG_SEL_MAX) 136*ad3cc776SMin Li return -EINVAL; 137*ad3cc776SMin Li 138*ad3cc776SMin Li err = idt82p33_read(idt82p33, channel->dpll_tod_trigger, 139*ad3cc776SMin Li &cfg, sizeof(cfg)); 140*ad3cc776SMin Li 141*ad3cc776SMin Li if (err) 142*ad3cc776SMin Li return err; 143*ad3cc776SMin Li 144*ad3cc776SMin Li if (write == true) 145*ad3cc776SMin Li trigger = (trigger << WRITE_TRIGGER_SHIFT) | 146*ad3cc776SMin Li (cfg & READ_TRIGGER_MASK); 147*ad3cc776SMin Li else 148*ad3cc776SMin Li trigger = (trigger << READ_TRIGGER_SHIFT) | 149*ad3cc776SMin Li (cfg & WRITE_TRIGGER_MASK); 150*ad3cc776SMin Li 151*ad3cc776SMin Li return idt82p33_write(idt82p33, channel->dpll_tod_trigger, 152*ad3cc776SMin Li &trigger, sizeof(trigger)); 153*ad3cc776SMin Li } 154*ad3cc776SMin Li 155*ad3cc776SMin Li static int idt82p33_get_extts(struct idt82p33_channel *channel, 15657a10d8cSMin Li struct timespec64 *ts) 15757a10d8cSMin Li { 15857a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 15957a10d8cSMin Li u8 buf[TOD_BYTE_COUNT]; 16057a10d8cSMin Li int err; 16157a10d8cSMin Li 162*ad3cc776SMin Li err = idt82p33_read(idt82p33, channel->dpll_tod_sts, buf, sizeof(buf)); 16357a10d8cSMin Li 16457a10d8cSMin Li if (err) 16557a10d8cSMin Li return err; 16657a10d8cSMin Li 167*ad3cc776SMin Li /* Since trigger is not self clearing itself, we have to poll tod_sts */ 168*ad3cc776SMin Li if (memcmp(buf, channel->extts_tod_sts, TOD_BYTE_COUNT) == 0) 169*ad3cc776SMin Li return -EAGAIN; 170*ad3cc776SMin Li 171*ad3cc776SMin Li memcpy(channel->extts_tod_sts, buf, TOD_BYTE_COUNT); 172*ad3cc776SMin Li 173*ad3cc776SMin Li idt82p33_byte_array_to_timespec(ts, buf); 174*ad3cc776SMin Li 175*ad3cc776SMin Li if (channel->discard_next_extts) { 176*ad3cc776SMin Li channel->discard_next_extts = false; 177*ad3cc776SMin Li return -EAGAIN; 178*ad3cc776SMin Li } 179*ad3cc776SMin Li 180*ad3cc776SMin Li return 0; 181*ad3cc776SMin Li } 182*ad3cc776SMin Li 183*ad3cc776SMin Li static int map_ref_to_tod_trig_sel(int ref, u8 *trigger) 184*ad3cc776SMin Li { 185*ad3cc776SMin Li int err = 0; 186*ad3cc776SMin Li 187*ad3cc776SMin Li switch (ref) { 188*ad3cc776SMin Li case 0: 189*ad3cc776SMin Li *trigger = HW_TOD_TRIG_SEL_IN12; 190*ad3cc776SMin Li break; 191*ad3cc776SMin Li case 1: 192*ad3cc776SMin Li *trigger = HW_TOD_TRIG_SEL_IN13; 193*ad3cc776SMin Li break; 194*ad3cc776SMin Li case 2: 195*ad3cc776SMin Li *trigger = HW_TOD_TRIG_SEL_IN14; 196*ad3cc776SMin Li break; 197*ad3cc776SMin Li default: 198*ad3cc776SMin Li err = -EINVAL; 199*ad3cc776SMin Li } 200*ad3cc776SMin Li 201*ad3cc776SMin Li return err; 202*ad3cc776SMin Li } 203*ad3cc776SMin Li 204*ad3cc776SMin Li static bool is_one_shot(u8 mask) 205*ad3cc776SMin Li { 206*ad3cc776SMin Li /* Treat single bit PLL masks as continuous trigger */ 207*ad3cc776SMin Li if ((mask == 1) || (mask == 2)) 208*ad3cc776SMin Li return false; 209*ad3cc776SMin Li else 210*ad3cc776SMin Li return true; 211*ad3cc776SMin Li } 212*ad3cc776SMin Li 213*ad3cc776SMin Li static int arm_tod_read_with_trigger(struct idt82p33_channel *channel, u8 trigger) 214*ad3cc776SMin Li { 215*ad3cc776SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 216*ad3cc776SMin Li u8 buf[TOD_BYTE_COUNT]; 217*ad3cc776SMin Li int err; 218*ad3cc776SMin Li 219*ad3cc776SMin Li /* Remember the current tod_sts before setting the trigger */ 220*ad3cc776SMin Li err = idt82p33_read(idt82p33, channel->dpll_tod_sts, buf, sizeof(buf)); 221*ad3cc776SMin Li 222*ad3cc776SMin Li if (err) 223*ad3cc776SMin Li return err; 224*ad3cc776SMin Li 225*ad3cc776SMin Li memcpy(channel->extts_tod_sts, buf, TOD_BYTE_COUNT); 226*ad3cc776SMin Li 227*ad3cc776SMin Li err = idt82p33_set_tod_trigger(channel, trigger, false); 228*ad3cc776SMin Li 229*ad3cc776SMin Li if (err) 230*ad3cc776SMin Li dev_err(idt82p33->dev, "%s: err = %d", __func__, err); 231*ad3cc776SMin Li 232*ad3cc776SMin Li return err; 233*ad3cc776SMin Li } 234*ad3cc776SMin Li 235*ad3cc776SMin Li static int idt82p33_extts_enable(struct idt82p33_channel *channel, 236*ad3cc776SMin Li struct ptp_clock_request *rq, int on) 237*ad3cc776SMin Li { 238*ad3cc776SMin Li u8 index = rq->extts.index; 239*ad3cc776SMin Li struct idt82p33 *idt82p33; 240*ad3cc776SMin Li u8 mask = 1 << index; 241*ad3cc776SMin Li int err = 0; 242*ad3cc776SMin Li u8 old_mask; 243*ad3cc776SMin Li u8 trigger; 244*ad3cc776SMin Li int ref; 245*ad3cc776SMin Li 246*ad3cc776SMin Li idt82p33 = channel->idt82p33; 247*ad3cc776SMin Li old_mask = idt82p33->extts_mask; 248*ad3cc776SMin Li 249*ad3cc776SMin Li /* Reject requests with unsupported flags */ 250*ad3cc776SMin Li if (rq->extts.flags & ~(PTP_ENABLE_FEATURE | 251*ad3cc776SMin Li PTP_RISING_EDGE | 252*ad3cc776SMin Li PTP_FALLING_EDGE | 253*ad3cc776SMin Li PTP_STRICT_FLAGS)) 254*ad3cc776SMin Li return -EOPNOTSUPP; 255*ad3cc776SMin Li 256*ad3cc776SMin Li /* Reject requests to enable time stamping on falling edge */ 257*ad3cc776SMin Li if ((rq->extts.flags & PTP_ENABLE_FEATURE) && 258*ad3cc776SMin Li (rq->extts.flags & PTP_FALLING_EDGE)) 259*ad3cc776SMin Li return -EOPNOTSUPP; 260*ad3cc776SMin Li 261*ad3cc776SMin Li if (index >= MAX_PHC_PLL) 262*ad3cc776SMin Li return -EINVAL; 263*ad3cc776SMin Li 264*ad3cc776SMin Li if (on) { 265*ad3cc776SMin Li /* Return if it was already enabled */ 266*ad3cc776SMin Li if (idt82p33->extts_mask & mask) 267*ad3cc776SMin Li return 0; 268*ad3cc776SMin Li 269*ad3cc776SMin Li /* Use the pin configured for the channel */ 270*ad3cc776SMin Li ref = ptp_find_pin(channel->ptp_clock, PTP_PF_EXTTS, channel->plln); 271*ad3cc776SMin Li 272*ad3cc776SMin Li if (ref < 0) { 273*ad3cc776SMin Li dev_err(idt82p33->dev, "%s: No valid pin found for Pll%d!\n", 274*ad3cc776SMin Li __func__, channel->plln); 275*ad3cc776SMin Li return -EBUSY; 276*ad3cc776SMin Li } 277*ad3cc776SMin Li 278*ad3cc776SMin Li err = map_ref_to_tod_trig_sel(ref, &trigger); 279*ad3cc776SMin Li 280*ad3cc776SMin Li if (err) { 281*ad3cc776SMin Li dev_err(idt82p33->dev, 282*ad3cc776SMin Li "%s: Unsupported ref %d!\n", __func__, ref); 283*ad3cc776SMin Li return err; 284*ad3cc776SMin Li } 285*ad3cc776SMin Li 286*ad3cc776SMin Li err = arm_tod_read_with_trigger(&idt82p33->channel[index], trigger); 287*ad3cc776SMin Li 288*ad3cc776SMin Li if (err == 0) { 289*ad3cc776SMin Li idt82p33->extts_mask |= mask; 290*ad3cc776SMin Li idt82p33->channel[index].tod_trigger = trigger; 291*ad3cc776SMin Li idt82p33->event_channel[index] = channel; 292*ad3cc776SMin Li idt82p33->extts_single_shot = is_one_shot(idt82p33->extts_mask); 293*ad3cc776SMin Li 294*ad3cc776SMin Li if (old_mask) 295*ad3cc776SMin Li return 0; 296*ad3cc776SMin Li 297*ad3cc776SMin Li schedule_delayed_work(&idt82p33->extts_work, 298*ad3cc776SMin Li msecs_to_jiffies(EXTTS_PERIOD_MS)); 299*ad3cc776SMin Li } 300*ad3cc776SMin Li } else { 301*ad3cc776SMin Li idt82p33->extts_mask &= ~mask; 302*ad3cc776SMin Li idt82p33->extts_single_shot = is_one_shot(idt82p33->extts_mask); 303*ad3cc776SMin Li 304*ad3cc776SMin Li if (idt82p33->extts_mask == 0) 305*ad3cc776SMin Li cancel_delayed_work(&idt82p33->extts_work); 306*ad3cc776SMin Li } 307*ad3cc776SMin Li 308*ad3cc776SMin Li return err; 309*ad3cc776SMin Li } 310*ad3cc776SMin Li 311*ad3cc776SMin Li static int idt82p33_extts_check_channel(struct idt82p33 *idt82p33, u8 todn) 312*ad3cc776SMin Li { 313*ad3cc776SMin Li struct idt82p33_channel *event_channel; 314*ad3cc776SMin Li struct ptp_clock_event event; 315*ad3cc776SMin Li struct timespec64 ts; 316*ad3cc776SMin Li int err; 317*ad3cc776SMin Li 318*ad3cc776SMin Li err = idt82p33_get_extts(&idt82p33->channel[todn], &ts); 319*ad3cc776SMin Li if (err == 0) { 320*ad3cc776SMin Li event_channel = idt82p33->event_channel[todn]; 321*ad3cc776SMin Li event.type = PTP_CLOCK_EXTTS; 322*ad3cc776SMin Li event.index = todn; 323*ad3cc776SMin Li event.timestamp = timespec64_to_ns(&ts); 324*ad3cc776SMin Li ptp_clock_event(event_channel->ptp_clock, 325*ad3cc776SMin Li &event); 326*ad3cc776SMin Li } 327*ad3cc776SMin Li return err; 328*ad3cc776SMin Li } 329*ad3cc776SMin Li 330*ad3cc776SMin Li static u8 idt82p33_extts_enable_mask(struct idt82p33_channel *channel, 331*ad3cc776SMin Li u8 extts_mask, bool enable) 332*ad3cc776SMin Li { 333*ad3cc776SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 334*ad3cc776SMin Li u8 trigger = channel->tod_trigger; 335*ad3cc776SMin Li u8 mask; 336*ad3cc776SMin Li int err; 337*ad3cc776SMin Li int i; 338*ad3cc776SMin Li 339*ad3cc776SMin Li if (extts_mask == 0) 340*ad3cc776SMin Li return 0; 341*ad3cc776SMin Li 342*ad3cc776SMin Li if (enable == false) 343*ad3cc776SMin Li cancel_delayed_work_sync(&idt82p33->extts_work); 344*ad3cc776SMin Li 345*ad3cc776SMin Li for (i = 0; i < MAX_PHC_PLL; i++) { 346*ad3cc776SMin Li mask = 1 << i; 347*ad3cc776SMin Li 348*ad3cc776SMin Li if ((extts_mask & mask) == 0) 349*ad3cc776SMin Li continue; 350*ad3cc776SMin Li 351*ad3cc776SMin Li if (enable) { 352*ad3cc776SMin Li err = arm_tod_read_with_trigger(&idt82p33->channel[i], trigger); 353*ad3cc776SMin Li if (err) 354*ad3cc776SMin Li dev_err(idt82p33->dev, 355*ad3cc776SMin Li "%s: Arm ToD read trigger failed, err = %d", 356*ad3cc776SMin Li __func__, err); 357*ad3cc776SMin Li } else { 358*ad3cc776SMin Li err = idt82p33_extts_check_channel(idt82p33, i); 359*ad3cc776SMin Li if (err == 0 && idt82p33->extts_single_shot) 360*ad3cc776SMin Li /* trigger happened so we won't re-enable it */ 361*ad3cc776SMin Li extts_mask &= ~mask; 362*ad3cc776SMin Li } 363*ad3cc776SMin Li } 364*ad3cc776SMin Li 365*ad3cc776SMin Li if (enable) 366*ad3cc776SMin Li schedule_delayed_work(&idt82p33->extts_work, 367*ad3cc776SMin Li msecs_to_jiffies(EXTTS_PERIOD_MS)); 368*ad3cc776SMin Li 369*ad3cc776SMin Li return extts_mask; 370*ad3cc776SMin Li } 371*ad3cc776SMin Li 372*ad3cc776SMin Li static int _idt82p33_gettime(struct idt82p33_channel *channel, 373*ad3cc776SMin Li struct timespec64 *ts) 374*ad3cc776SMin Li { 375*ad3cc776SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 376*ad3cc776SMin Li u8 old_mask = idt82p33->extts_mask; 377*ad3cc776SMin Li u8 buf[TOD_BYTE_COUNT]; 378*ad3cc776SMin Li u8 new_mask = 0; 379*ad3cc776SMin Li int err; 380*ad3cc776SMin Li 381*ad3cc776SMin Li /* Disable extts */ 382*ad3cc776SMin Li if (old_mask) 383*ad3cc776SMin Li new_mask = idt82p33_extts_enable_mask(channel, old_mask, false); 384*ad3cc776SMin Li 385*ad3cc776SMin Li err = idt82p33_set_tod_trigger(channel, HW_TOD_RD_TRIG_SEL_LSB_TOD_STS, 386*ad3cc776SMin Li false); 387*ad3cc776SMin Li if (err) 388*ad3cc776SMin Li return err; 389*ad3cc776SMin Li 390*ad3cc776SMin Li channel->discard_next_extts = true; 391*ad3cc776SMin Li 39257a10d8cSMin Li if (idt82p33->calculate_overhead_flag) 39357a10d8cSMin Li idt82p33->start_time = ktime_get_raw(); 39457a10d8cSMin Li 39557a10d8cSMin Li err = idt82p33_read(idt82p33, channel->dpll_tod_sts, buf, sizeof(buf)); 39657a10d8cSMin Li 39757a10d8cSMin Li if (err) 39857a10d8cSMin Li return err; 39957a10d8cSMin Li 400*ad3cc776SMin Li /* Re-enable extts */ 401*ad3cc776SMin Li if (new_mask) 402*ad3cc776SMin Li idt82p33_extts_enable_mask(channel, new_mask, true); 403*ad3cc776SMin Li 40457a10d8cSMin Li idt82p33_byte_array_to_timespec(ts, buf); 40557a10d8cSMin Li 40657a10d8cSMin Li return 0; 40757a10d8cSMin Li } 40857a10d8cSMin Li 40957a10d8cSMin Li /* 41057a10d8cSMin Li * TOD Trigger: 41157a10d8cSMin Li * Bits[7:4] Write 0x9, MSB write 41257a10d8cSMin Li * Bits[3:0] Read 0x9, LSB read 41357a10d8cSMin Li */ 41457a10d8cSMin Li 41557a10d8cSMin Li static int _idt82p33_settime(struct idt82p33_channel *channel, 41657a10d8cSMin Li struct timespec64 const *ts) 41757a10d8cSMin Li { 41857a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 41957a10d8cSMin Li struct timespec64 local_ts = *ts; 42057a10d8cSMin Li char buf[TOD_BYTE_COUNT]; 42157a10d8cSMin Li s64 dynamic_overhead_ns; 42257a10d8cSMin Li int err; 42357a10d8cSMin Li u8 i; 42457a10d8cSMin Li 425*ad3cc776SMin Li err = idt82p33_set_tod_trigger(channel, HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG, 426*ad3cc776SMin Li true); 42757a10d8cSMin Li if (err) 42857a10d8cSMin Li return err; 42957a10d8cSMin Li 430*ad3cc776SMin Li channel->discard_next_extts = true; 431*ad3cc776SMin Li 43257a10d8cSMin Li if (idt82p33->calculate_overhead_flag) { 43357a10d8cSMin Li dynamic_overhead_ns = ktime_to_ns(ktime_get_raw()) 43457a10d8cSMin Li - ktime_to_ns(idt82p33->start_time); 43557a10d8cSMin Li 43657a10d8cSMin Li timespec64_add_ns(&local_ts, dynamic_overhead_ns); 43757a10d8cSMin Li 43857a10d8cSMin Li idt82p33->calculate_overhead_flag = 0; 43957a10d8cSMin Li } 44057a10d8cSMin Li 44157a10d8cSMin Li idt82p33_timespec_to_byte_array(&local_ts, buf); 44257a10d8cSMin Li 44357a10d8cSMin Li /* 44457a10d8cSMin Li * Store the new time value. 44557a10d8cSMin Li */ 44657a10d8cSMin Li for (i = 0; i < TOD_BYTE_COUNT; i++) { 44757a10d8cSMin Li err = idt82p33_write(idt82p33, channel->dpll_tod_cnfg + i, 44857a10d8cSMin Li &buf[i], sizeof(buf[i])); 44957a10d8cSMin Li if (err) 45057a10d8cSMin Li return err; 45157a10d8cSMin Li } 45257a10d8cSMin Li 45357a10d8cSMin Li return err; 45457a10d8cSMin Li } 45557a10d8cSMin Li 456*ad3cc776SMin Li static int _idt82p33_adjtime_immediate(struct idt82p33_channel *channel, 457*ad3cc776SMin Li s64 delta_ns) 45857a10d8cSMin Li { 45957a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 46057a10d8cSMin Li struct timespec64 ts; 46157a10d8cSMin Li s64 now_ns; 46257a10d8cSMin Li int err; 46357a10d8cSMin Li 46457a10d8cSMin Li idt82p33->calculate_overhead_flag = 1; 46557a10d8cSMin Li 46657a10d8cSMin Li err = _idt82p33_gettime(channel, &ts); 46757a10d8cSMin Li 46857a10d8cSMin Li if (err) 46957a10d8cSMin Li return err; 47057a10d8cSMin Li 47157a10d8cSMin Li now_ns = timespec64_to_ns(&ts); 47257a10d8cSMin Li now_ns += delta_ns + idt82p33->tod_write_overhead_ns; 47357a10d8cSMin Li 47457a10d8cSMin Li ts = ns_to_timespec64(now_ns); 47557a10d8cSMin Li 47657a10d8cSMin Li err = _idt82p33_settime(channel, &ts); 47757a10d8cSMin Li 47857a10d8cSMin Li return err; 47957a10d8cSMin Li } 48057a10d8cSMin Li 481*ad3cc776SMin Li static int _idt82p33_adjtime_internal_triggered(struct idt82p33_channel *channel, 482*ad3cc776SMin Li s64 delta_ns) 483*ad3cc776SMin Li { 484*ad3cc776SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 485*ad3cc776SMin Li char buf[TOD_BYTE_COUNT]; 486*ad3cc776SMin Li struct timespec64 ts; 487*ad3cc776SMin Li const u8 delay_ns = 32; 488*ad3cc776SMin Li s32 remainder; 489*ad3cc776SMin Li s64 ns; 490*ad3cc776SMin Li int err; 491*ad3cc776SMin Li 492*ad3cc776SMin Li err = _idt82p33_gettime(channel, &ts); 493*ad3cc776SMin Li 494*ad3cc776SMin Li if (err) 495*ad3cc776SMin Li return err; 496*ad3cc776SMin Li 497*ad3cc776SMin Li if (ts.tv_nsec > (NSEC_PER_SEC - 5 * NSEC_PER_MSEC)) { 498*ad3cc776SMin Li /* Too close to miss next trigger, so skip it */ 499*ad3cc776SMin Li mdelay(6); 500*ad3cc776SMin Li ns = (ts.tv_sec + 2) * NSEC_PER_SEC + delta_ns + delay_ns; 501*ad3cc776SMin Li } else 502*ad3cc776SMin Li ns = (ts.tv_sec + 1) * NSEC_PER_SEC + delta_ns + delay_ns; 503*ad3cc776SMin Li 504*ad3cc776SMin Li ts = ns_to_timespec64(ns); 505*ad3cc776SMin Li idt82p33_timespec_to_byte_array(&ts, buf); 506*ad3cc776SMin Li 507*ad3cc776SMin Li /* 508*ad3cc776SMin Li * Store the new time value. 509*ad3cc776SMin Li */ 510*ad3cc776SMin Li err = idt82p33_write(idt82p33, channel->dpll_tod_cnfg, buf, sizeof(buf)); 511*ad3cc776SMin Li if (err) 512*ad3cc776SMin Li return err; 513*ad3cc776SMin Li 514*ad3cc776SMin Li /* Schedule to implement the workaround in one second */ 515*ad3cc776SMin Li (void)div_s64_rem(delta_ns, NSEC_PER_SEC, &remainder); 516*ad3cc776SMin Li if (remainder != 0) 517*ad3cc776SMin Li schedule_delayed_work(&channel->adjtime_work, HZ); 518*ad3cc776SMin Li 519*ad3cc776SMin Li return idt82p33_set_tod_trigger(channel, HW_TOD_TRIG_SEL_TOD_PPS, true); 520*ad3cc776SMin Li } 521*ad3cc776SMin Li 522*ad3cc776SMin Li static void idt82p33_adjtime_workaround(struct work_struct *work) 523*ad3cc776SMin Li { 524*ad3cc776SMin Li struct idt82p33_channel *channel = container_of(work, 525*ad3cc776SMin Li struct idt82p33_channel, 526*ad3cc776SMin Li adjtime_work.work); 527*ad3cc776SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 528*ad3cc776SMin Li 529*ad3cc776SMin Li mutex_lock(idt82p33->lock); 530*ad3cc776SMin Li /* Workaround for TOD-to-output alignment issue */ 531*ad3cc776SMin Li _idt82p33_adjtime_internal_triggered(channel, 0); 532*ad3cc776SMin Li mutex_unlock(idt82p33->lock); 533*ad3cc776SMin Li } 534*ad3cc776SMin Li 53557a10d8cSMin Li static int _idt82p33_adjfine(struct idt82p33_channel *channel, long scaled_ppm) 53657a10d8cSMin Li { 53757a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 53857a10d8cSMin Li unsigned char buf[5] = {0}; 53957a10d8cSMin Li int err, i; 54057a10d8cSMin Li s64 fcw; 54157a10d8cSMin Li 54257a10d8cSMin Li /* 543*ad3cc776SMin Li * Frequency Control Word unit is: 1.6861512 * 10^-10 ppm 54457a10d8cSMin Li * 54557a10d8cSMin Li * adjfreq: 546*ad3cc776SMin Li * ppb * 10^14 547*ad3cc776SMin Li * FCW = ----------- 548*ad3cc776SMin Li * 16861512 54957a10d8cSMin Li * 55057a10d8cSMin Li * adjfine: 551*ad3cc776SMin Li * scaled_ppm * 5^12 * 10^5 552*ad3cc776SMin Li * FCW = ------------------------ 553*ad3cc776SMin Li * 16861512 * 2^4 55457a10d8cSMin Li */ 55557a10d8cSMin Li 556*ad3cc776SMin Li fcw = scaled_ppm * 762939453125ULL; 557*ad3cc776SMin Li fcw = div_s64(fcw, 8430756LL); 55857a10d8cSMin Li 55957a10d8cSMin Li for (i = 0; i < 5; i++) { 56057a10d8cSMin Li buf[i] = fcw & 0xff; 56157a10d8cSMin Li fcw >>= 8; 56257a10d8cSMin Li } 56357a10d8cSMin Li 56457a10d8cSMin Li err = idt82p33_dpll_set_mode(channel, PLL_MODE_DCO); 56557a10d8cSMin Li 56657a10d8cSMin Li if (err) 56757a10d8cSMin Li return err; 56857a10d8cSMin Li 56957a10d8cSMin Li err = idt82p33_write(idt82p33, channel->dpll_freq_cnfg, 57057a10d8cSMin Li buf, sizeof(buf)); 57157a10d8cSMin Li 57257a10d8cSMin Li return err; 57357a10d8cSMin Li } 57457a10d8cSMin Li 575*ad3cc776SMin Li /* ppb = scaled_ppm * 125 / 2^13 */ 576*ad3cc776SMin Li static s32 idt82p33_ddco_scaled_ppm(long current_ppm, s32 ddco_ppb) 577*ad3cc776SMin Li { 578*ad3cc776SMin Li s64 scaled_ppm = div_s64(((s64)ddco_ppb << 13), 125); 579*ad3cc776SMin Li s64 max_scaled_ppm = div_s64(((s64)DCO_MAX_PPB << 13), 125); 580*ad3cc776SMin Li 581*ad3cc776SMin Li current_ppm += scaled_ppm; 582*ad3cc776SMin Li 583*ad3cc776SMin Li if (current_ppm > max_scaled_ppm) 584*ad3cc776SMin Li current_ppm = max_scaled_ppm; 585*ad3cc776SMin Li else if (current_ppm < -max_scaled_ppm) 586*ad3cc776SMin Li current_ppm = -max_scaled_ppm; 587*ad3cc776SMin Li 588*ad3cc776SMin Li return (s32)current_ppm; 589*ad3cc776SMin Li } 590*ad3cc776SMin Li 591*ad3cc776SMin Li static int idt82p33_stop_ddco(struct idt82p33_channel *channel) 592*ad3cc776SMin Li { 593*ad3cc776SMin Li int err; 594*ad3cc776SMin Li 595*ad3cc776SMin Li err = _idt82p33_adjfine(channel, channel->current_freq); 596*ad3cc776SMin Li if (err) 597*ad3cc776SMin Li return err; 598*ad3cc776SMin Li 599*ad3cc776SMin Li channel->ddco = false; 600*ad3cc776SMin Li 601*ad3cc776SMin Li return 0; 602*ad3cc776SMin Li } 603*ad3cc776SMin Li 604*ad3cc776SMin Li static int idt82p33_start_ddco(struct idt82p33_channel *channel, s32 delta_ns) 605*ad3cc776SMin Li { 606*ad3cc776SMin Li s32 current_ppm = channel->current_freq; 607*ad3cc776SMin Li u32 duration_ms = MSEC_PER_SEC; 608*ad3cc776SMin Li s32 ppb; 609*ad3cc776SMin Li int err; 610*ad3cc776SMin Li 611*ad3cc776SMin Li /* If the ToD correction is less than 5 nanoseconds, then skip it. 612*ad3cc776SMin Li * The error introduced by the ToD adjustment procedure would be bigger 613*ad3cc776SMin Li * than the required ToD correction 614*ad3cc776SMin Li */ 615*ad3cc776SMin Li if (abs(delta_ns) < DDCO_THRESHOLD_NS) 616*ad3cc776SMin Li return 0; 617*ad3cc776SMin Li 618*ad3cc776SMin Li /* For most cases, keep ddco duration 1 second */ 619*ad3cc776SMin Li ppb = delta_ns; 620*ad3cc776SMin Li while (abs(ppb) > DCO_MAX_PPB) { 621*ad3cc776SMin Li duration_ms *= 2; 622*ad3cc776SMin Li ppb /= 2; 623*ad3cc776SMin Li } 624*ad3cc776SMin Li 625*ad3cc776SMin Li err = _idt82p33_adjfine(channel, 626*ad3cc776SMin Li idt82p33_ddco_scaled_ppm(current_ppm, ppb)); 627*ad3cc776SMin Li if (err) 628*ad3cc776SMin Li return err; 629*ad3cc776SMin Li 630*ad3cc776SMin Li /* schedule the worker to cancel ddco */ 631*ad3cc776SMin Li ptp_schedule_worker(channel->ptp_clock, 632*ad3cc776SMin Li msecs_to_jiffies(duration_ms) - 1); 633*ad3cc776SMin Li channel->ddco = true; 634*ad3cc776SMin Li 635*ad3cc776SMin Li return 0; 636*ad3cc776SMin Li } 637*ad3cc776SMin Li 63857a10d8cSMin Li static int idt82p33_measure_one_byte_write_overhead( 63957a10d8cSMin Li struct idt82p33_channel *channel, s64 *overhead_ns) 64057a10d8cSMin Li { 64157a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 64257a10d8cSMin Li ktime_t start, stop; 643*ad3cc776SMin Li u8 trigger = 0; 64457a10d8cSMin Li s64 total_ns; 64557a10d8cSMin Li int err; 64657a10d8cSMin Li u8 i; 64757a10d8cSMin Li 64857a10d8cSMin Li total_ns = 0; 64957a10d8cSMin Li *overhead_ns = 0; 65057a10d8cSMin Li 65157a10d8cSMin Li for (i = 0; i < MAX_MEASURMENT_COUNT; i++) { 65257a10d8cSMin Li 65357a10d8cSMin Li start = ktime_get_raw(); 65457a10d8cSMin Li 65557a10d8cSMin Li err = idt82p33_write(idt82p33, channel->dpll_tod_trigger, 65657a10d8cSMin Li &trigger, sizeof(trigger)); 65757a10d8cSMin Li 65857a10d8cSMin Li stop = ktime_get_raw(); 65957a10d8cSMin Li 66057a10d8cSMin Li if (err) 66157a10d8cSMin Li return err; 66257a10d8cSMin Li 66357a10d8cSMin Li total_ns += ktime_to_ns(stop) - ktime_to_ns(start); 66457a10d8cSMin Li } 66557a10d8cSMin Li 66657a10d8cSMin Li *overhead_ns = div_s64(total_ns, MAX_MEASURMENT_COUNT); 66757a10d8cSMin Li 66857a10d8cSMin Li return err; 66957a10d8cSMin Li } 67057a10d8cSMin Li 671*ad3cc776SMin Li static int idt82p33_measure_one_byte_read_overhead( 672*ad3cc776SMin Li struct idt82p33_channel *channel, s64 *overhead_ns) 673*ad3cc776SMin Li { 674*ad3cc776SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 675*ad3cc776SMin Li ktime_t start, stop; 676*ad3cc776SMin Li u8 trigger = 0; 677*ad3cc776SMin Li s64 total_ns; 678*ad3cc776SMin Li int err; 679*ad3cc776SMin Li u8 i; 680*ad3cc776SMin Li 681*ad3cc776SMin Li total_ns = 0; 682*ad3cc776SMin Li *overhead_ns = 0; 683*ad3cc776SMin Li 684*ad3cc776SMin Li for (i = 0; i < MAX_MEASURMENT_COUNT; i++) { 685*ad3cc776SMin Li 686*ad3cc776SMin Li start = ktime_get_raw(); 687*ad3cc776SMin Li 688*ad3cc776SMin Li err = idt82p33_read(idt82p33, channel->dpll_tod_trigger, 689*ad3cc776SMin Li &trigger, sizeof(trigger)); 690*ad3cc776SMin Li 691*ad3cc776SMin Li stop = ktime_get_raw(); 692*ad3cc776SMin Li 693*ad3cc776SMin Li if (err) 694*ad3cc776SMin Li return err; 695*ad3cc776SMin Li 696*ad3cc776SMin Li total_ns += ktime_to_ns(stop) - ktime_to_ns(start); 697*ad3cc776SMin Li } 698*ad3cc776SMin Li 699*ad3cc776SMin Li *overhead_ns = div_s64(total_ns, MAX_MEASURMENT_COUNT); 700*ad3cc776SMin Li 701*ad3cc776SMin Li return err; 702*ad3cc776SMin Li } 703*ad3cc776SMin Li 70457a10d8cSMin Li static int idt82p33_measure_tod_write_9_byte_overhead( 70557a10d8cSMin Li struct idt82p33_channel *channel) 70657a10d8cSMin Li { 70757a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 70857a10d8cSMin Li u8 buf[TOD_BYTE_COUNT]; 70957a10d8cSMin Li ktime_t start, stop; 71057a10d8cSMin Li s64 total_ns; 71157a10d8cSMin Li int err = 0; 71257a10d8cSMin Li u8 i, j; 71357a10d8cSMin Li 71457a10d8cSMin Li total_ns = 0; 71557a10d8cSMin Li idt82p33->tod_write_overhead_ns = 0; 71657a10d8cSMin Li 71757a10d8cSMin Li for (i = 0; i < MAX_MEASURMENT_COUNT; i++) { 71857a10d8cSMin Li 71957a10d8cSMin Li start = ktime_get_raw(); 72057a10d8cSMin Li 72157a10d8cSMin Li /* Need one less byte for applicable overhead */ 72257a10d8cSMin Li for (j = 0; j < (TOD_BYTE_COUNT - 1); j++) { 72357a10d8cSMin Li err = idt82p33_write(idt82p33, 72457a10d8cSMin Li channel->dpll_tod_cnfg + i, 72557a10d8cSMin Li &buf[i], sizeof(buf[i])); 72657a10d8cSMin Li if (err) 72757a10d8cSMin Li return err; 72857a10d8cSMin Li } 72957a10d8cSMin Li 73057a10d8cSMin Li stop = ktime_get_raw(); 73157a10d8cSMin Li 73257a10d8cSMin Li total_ns += ktime_to_ns(stop) - ktime_to_ns(start); 73357a10d8cSMin Li } 73457a10d8cSMin Li 73557a10d8cSMin Li idt82p33->tod_write_overhead_ns = div_s64(total_ns, 73657a10d8cSMin Li MAX_MEASURMENT_COUNT); 73757a10d8cSMin Li 73857a10d8cSMin Li return err; 73957a10d8cSMin Li } 74057a10d8cSMin Li 74157a10d8cSMin Li static int idt82p33_measure_settime_gettime_gap_overhead( 74257a10d8cSMin Li struct idt82p33_channel *channel, s64 *overhead_ns) 74357a10d8cSMin Li { 74457a10d8cSMin Li struct timespec64 ts1 = {0, 0}; 74557a10d8cSMin Li struct timespec64 ts2; 74657a10d8cSMin Li int err; 74757a10d8cSMin Li 74857a10d8cSMin Li *overhead_ns = 0; 74957a10d8cSMin Li 75057a10d8cSMin Li err = _idt82p33_settime(channel, &ts1); 75157a10d8cSMin Li 75257a10d8cSMin Li if (err) 75357a10d8cSMin Li return err; 75457a10d8cSMin Li 75557a10d8cSMin Li err = _idt82p33_gettime(channel, &ts2); 75657a10d8cSMin Li 75757a10d8cSMin Li if (!err) 75857a10d8cSMin Li *overhead_ns = timespec64_to_ns(&ts2) - timespec64_to_ns(&ts1); 75957a10d8cSMin Li 76057a10d8cSMin Li return err; 76157a10d8cSMin Li } 76257a10d8cSMin Li 76357a10d8cSMin Li static int idt82p33_measure_tod_write_overhead(struct idt82p33_channel *channel) 76457a10d8cSMin Li { 765*ad3cc776SMin Li s64 trailing_overhead_ns, one_byte_write_ns, gap_ns, one_byte_read_ns; 76657a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 76757a10d8cSMin Li int err; 76857a10d8cSMin Li 76957a10d8cSMin Li idt82p33->tod_write_overhead_ns = 0; 77057a10d8cSMin Li 77157a10d8cSMin Li err = idt82p33_measure_settime_gettime_gap_overhead(channel, &gap_ns); 77257a10d8cSMin Li 773e014ae39SMin Li if (err) { 774013a3e7cSMin Li dev_err(idt82p33->dev, 775e014ae39SMin Li "Failed in %s with err %d!\n", __func__, err); 77657a10d8cSMin Li return err; 777e014ae39SMin Li } 77857a10d8cSMin Li 77957a10d8cSMin Li err = idt82p33_measure_one_byte_write_overhead(channel, 78057a10d8cSMin Li &one_byte_write_ns); 78157a10d8cSMin Li 78257a10d8cSMin Li if (err) 78357a10d8cSMin Li return err; 78457a10d8cSMin Li 785*ad3cc776SMin Li err = idt82p33_measure_one_byte_read_overhead(channel, 786*ad3cc776SMin Li &one_byte_read_ns); 787*ad3cc776SMin Li 788*ad3cc776SMin Li if (err) 789*ad3cc776SMin Li return err; 790*ad3cc776SMin Li 79157a10d8cSMin Li err = idt82p33_measure_tod_write_9_byte_overhead(channel); 79257a10d8cSMin Li 79357a10d8cSMin Li if (err) 79457a10d8cSMin Li return err; 79557a10d8cSMin Li 796*ad3cc776SMin Li trailing_overhead_ns = gap_ns - 2 * one_byte_write_ns 797*ad3cc776SMin Li - one_byte_read_ns; 79857a10d8cSMin Li 79957a10d8cSMin Li idt82p33->tod_write_overhead_ns -= trailing_overhead_ns; 80057a10d8cSMin Li 80157a10d8cSMin Li return err; 80257a10d8cSMin Li } 80357a10d8cSMin Li 80457a10d8cSMin Li static int idt82p33_check_and_set_masks(struct idt82p33 *idt82p33, 80557a10d8cSMin Li u8 page, 80657a10d8cSMin Li u8 offset, 80757a10d8cSMin Li u8 val) 80857a10d8cSMin Li { 80957a10d8cSMin Li int err = 0; 81057a10d8cSMin Li 81157a10d8cSMin Li if (page == PLLMASK_ADDR_HI && offset == PLLMASK_ADDR_LO) { 81257a10d8cSMin Li if ((val & 0xfc) || !(val & 0x3)) { 813013a3e7cSMin Li dev_err(idt82p33->dev, 814013a3e7cSMin Li "Invalid PLL mask 0x%x\n", val); 81557a10d8cSMin Li err = -EINVAL; 81657a10d8cSMin Li } else { 81757a10d8cSMin Li idt82p33->pll_mask = val; 81857a10d8cSMin Li } 81957a10d8cSMin Li } else if (page == PLL0_OUTMASK_ADDR_HI && 82057a10d8cSMin Li offset == PLL0_OUTMASK_ADDR_LO) { 82157a10d8cSMin Li idt82p33->channel[0].output_mask = val; 82257a10d8cSMin Li } else if (page == PLL1_OUTMASK_ADDR_HI && 82357a10d8cSMin Li offset == PLL1_OUTMASK_ADDR_LO) { 82457a10d8cSMin Li idt82p33->channel[1].output_mask = val; 82557a10d8cSMin Li } 82657a10d8cSMin Li 82757a10d8cSMin Li return err; 82857a10d8cSMin Li } 82957a10d8cSMin Li 83057a10d8cSMin Li static void idt82p33_display_masks(struct idt82p33 *idt82p33) 83157a10d8cSMin Li { 83257a10d8cSMin Li u8 mask, i; 83357a10d8cSMin Li 834013a3e7cSMin Li dev_info(idt82p33->dev, 83557a10d8cSMin Li "pllmask = 0x%02x\n", idt82p33->pll_mask); 83657a10d8cSMin Li 83757a10d8cSMin Li for (i = 0; i < MAX_PHC_PLL; i++) { 83857a10d8cSMin Li mask = 1 << i; 83957a10d8cSMin Li 84057a10d8cSMin Li if (mask & idt82p33->pll_mask) 841013a3e7cSMin Li dev_info(idt82p33->dev, 84257a10d8cSMin Li "PLL%d output_mask = 0x%04x\n", 84357a10d8cSMin Li i, idt82p33->channel[i].output_mask); 84457a10d8cSMin Li } 84557a10d8cSMin Li } 84657a10d8cSMin Li 84757a10d8cSMin Li static int idt82p33_sync_tod(struct idt82p33_channel *channel, bool enable) 84857a10d8cSMin Li { 84957a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 85057a10d8cSMin Li u8 sync_cnfg; 85157a10d8cSMin Li int err; 85257a10d8cSMin Li 85357a10d8cSMin Li err = idt82p33_read(idt82p33, channel->dpll_sync_cnfg, 85457a10d8cSMin Li &sync_cnfg, sizeof(sync_cnfg)); 85557a10d8cSMin Li if (err) 85657a10d8cSMin Li return err; 85757a10d8cSMin Li 85857a10d8cSMin Li sync_cnfg &= ~SYNC_TOD; 85957a10d8cSMin Li if (enable) 86057a10d8cSMin Li sync_cnfg |= SYNC_TOD; 86157a10d8cSMin Li 862e014ae39SMin Li return idt82p33_write(idt82p33, channel->dpll_sync_cnfg, 86357a10d8cSMin Li &sync_cnfg, sizeof(sync_cnfg)); 86457a10d8cSMin Li } 86557a10d8cSMin Li 866*ad3cc776SMin Li static long idt82p33_work_handler(struct ptp_clock_info *ptp) 867*ad3cc776SMin Li { 868*ad3cc776SMin Li struct idt82p33_channel *channel = 869*ad3cc776SMin Li container_of(ptp, struct idt82p33_channel, caps); 870*ad3cc776SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 871*ad3cc776SMin Li 872*ad3cc776SMin Li mutex_lock(idt82p33->lock); 873*ad3cc776SMin Li (void)idt82p33_stop_ddco(channel); 874*ad3cc776SMin Li mutex_unlock(idt82p33->lock); 875*ad3cc776SMin Li 876*ad3cc776SMin Li /* Return a negative value here to not reschedule */ 877*ad3cc776SMin Li return -1; 878*ad3cc776SMin Li } 879*ad3cc776SMin Li 880e014ae39SMin Li static int idt82p33_output_enable(struct idt82p33_channel *channel, 881e014ae39SMin Li bool enable, unsigned int outn) 88257a10d8cSMin Li { 88357a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 88457a10d8cSMin Li int err; 885e014ae39SMin Li u8 val; 886e014ae39SMin Li 887e014ae39SMin Li err = idt82p33_read(idt82p33, OUT_MUX_CNFG(outn), &val, sizeof(val)); 888e014ae39SMin Li if (err) 889e014ae39SMin Li return err; 890e014ae39SMin Li if (enable) 891e014ae39SMin Li val &= ~SQUELCH_ENABLE; 892e014ae39SMin Li else 893e014ae39SMin Li val |= SQUELCH_ENABLE; 894e014ae39SMin Li 895e014ae39SMin Li return idt82p33_write(idt82p33, OUT_MUX_CNFG(outn), &val, sizeof(val)); 896e014ae39SMin Li } 897e014ae39SMin Li 898e014ae39SMin Li static int idt82p33_output_mask_enable(struct idt82p33_channel *channel, 899e014ae39SMin Li bool enable) 900e014ae39SMin Li { 901e014ae39SMin Li u16 mask; 902e014ae39SMin Li int err; 903e014ae39SMin Li u8 outn; 90457a10d8cSMin Li 90557a10d8cSMin Li mask = channel->output_mask; 90657a10d8cSMin Li outn = 0; 90757a10d8cSMin Li 90857a10d8cSMin Li while (mask) { 90957a10d8cSMin Li if (mask & 0x1) { 910e014ae39SMin Li err = idt82p33_output_enable(channel, enable, outn); 91157a10d8cSMin Li if (err) 91257a10d8cSMin Li return err; 91357a10d8cSMin Li } 914e014ae39SMin Li 91557a10d8cSMin Li mask >>= 0x1; 91657a10d8cSMin Li outn++; 91757a10d8cSMin Li } 91857a10d8cSMin Li 91957a10d8cSMin Li return 0; 92057a10d8cSMin Li } 92157a10d8cSMin Li 922e014ae39SMin Li static int idt82p33_perout_enable(struct idt82p33_channel *channel, 923e014ae39SMin Li bool enable, 924e014ae39SMin Li struct ptp_perout_request *perout) 925e014ae39SMin Li { 926e014ae39SMin Li unsigned int flags = perout->flags; 927e014ae39SMin Li 928e014ae39SMin Li /* Enable/disable output based on output_mask */ 929e014ae39SMin Li if (flags == PEROUT_ENABLE_OUTPUT_MASK) 930e014ae39SMin Li return idt82p33_output_mask_enable(channel, enable); 931e014ae39SMin Li 932e014ae39SMin Li /* Enable/disable individual output instead */ 933e014ae39SMin Li return idt82p33_output_enable(channel, enable, perout->index); 934e014ae39SMin Li } 935e014ae39SMin Li 93657a10d8cSMin Li static int idt82p33_enable_tod(struct idt82p33_channel *channel) 93757a10d8cSMin Li { 93857a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 93957a10d8cSMin Li struct timespec64 ts = {0, 0}; 94057a10d8cSMin Li int err; 94157a10d8cSMin Li 942*ad3cc776SMin Li /* STEELAI-366 - Temporary workaround for ts2phc compatibility */ 943*ad3cc776SMin Li if (0) 944*ad3cc776SMin Li err = idt82p33_output_mask_enable(channel, false); 945*ad3cc776SMin Li 94657a10d8cSMin Li err = idt82p33_measure_tod_write_overhead(channel); 94757a10d8cSMin Li 948e014ae39SMin Li if (err) { 949013a3e7cSMin Li dev_err(idt82p33->dev, 950e014ae39SMin Li "Failed in %s with err %d!\n", __func__, err); 95157a10d8cSMin Li return err; 952e014ae39SMin Li } 95357a10d8cSMin Li 95457a10d8cSMin Li err = _idt82p33_settime(channel, &ts); 95557a10d8cSMin Li 95657a10d8cSMin Li if (err) 95757a10d8cSMin Li return err; 95857a10d8cSMin Li 95957a10d8cSMin Li return idt82p33_sync_tod(channel, true); 96057a10d8cSMin Li } 96157a10d8cSMin Li 96257a10d8cSMin Li static void idt82p33_ptp_clock_unregister_all(struct idt82p33 *idt82p33) 96357a10d8cSMin Li { 96457a10d8cSMin Li struct idt82p33_channel *channel; 96557a10d8cSMin Li u8 i; 96657a10d8cSMin Li 96757a10d8cSMin Li for (i = 0; i < MAX_PHC_PLL; i++) { 96857a10d8cSMin Li channel = &idt82p33->channel[i]; 969*ad3cc776SMin Li cancel_delayed_work_sync(&channel->adjtime_work); 970e014ae39SMin Li if (channel->ptp_clock) 97157a10d8cSMin Li ptp_clock_unregister(channel->ptp_clock); 97257a10d8cSMin Li } 97357a10d8cSMin Li } 97457a10d8cSMin Li 975*ad3cc776SMin Li 976*ad3cc776SMin Li 97757a10d8cSMin Li static int idt82p33_enable(struct ptp_clock_info *ptp, 97857a10d8cSMin Li struct ptp_clock_request *rq, int on) 97957a10d8cSMin Li { 98057a10d8cSMin Li struct idt82p33_channel *channel = 98157a10d8cSMin Li container_of(ptp, struct idt82p33_channel, caps); 98257a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 983013a3e7cSMin Li int err = -EOPNOTSUPP; 98457a10d8cSMin Li 985013a3e7cSMin Li mutex_lock(idt82p33->lock); 98657a10d8cSMin Li 987*ad3cc776SMin Li switch (rq->type) { 988*ad3cc776SMin Li case PTP_CLK_REQ_PEROUT: 98957a10d8cSMin Li if (!on) 990e014ae39SMin Li err = idt82p33_perout_enable(channel, false, 991e014ae39SMin Li &rq->perout); 99257a10d8cSMin Li /* Only accept a 1-PPS aligned to the second. */ 99357a10d8cSMin Li else if (rq->perout.start.nsec || rq->perout.period.sec != 1 || 994013a3e7cSMin Li rq->perout.period.nsec) 99557a10d8cSMin Li err = -ERANGE; 996013a3e7cSMin Li else 997e014ae39SMin Li err = idt82p33_perout_enable(channel, true, 998e014ae39SMin Li &rq->perout); 999*ad3cc776SMin Li break; 1000*ad3cc776SMin Li case PTP_CLK_REQ_EXTTS: 1001*ad3cc776SMin Li err = idt82p33_extts_enable(channel, rq, on); 1002*ad3cc776SMin Li break; 1003*ad3cc776SMin Li default: 1004*ad3cc776SMin Li break; 100557a10d8cSMin Li } 100657a10d8cSMin Li 1007013a3e7cSMin Li mutex_unlock(idt82p33->lock); 100857a10d8cSMin Li 1009013a3e7cSMin Li if (err) 1010013a3e7cSMin Li dev_err(idt82p33->dev, 1011013a3e7cSMin Li "Failed in %s with err %d!\n", __func__, err); 101257a10d8cSMin Li return err; 101357a10d8cSMin Li } 101457a10d8cSMin Li 1015e014ae39SMin Li static int idt82p33_adjwritephase(struct ptp_clock_info *ptp, s32 offset_ns) 1016e014ae39SMin Li { 1017e014ae39SMin Li struct idt82p33_channel *channel = 1018e014ae39SMin Li container_of(ptp, struct idt82p33_channel, caps); 1019e014ae39SMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 1020e014ae39SMin Li s64 offset_regval, offset_fs; 1021e014ae39SMin Li u8 val[4] = {0}; 1022e014ae39SMin Li int err; 1023e014ae39SMin Li 1024e014ae39SMin Li offset_fs = (s64)(-offset_ns) * 1000000; 1025e014ae39SMin Li 1026e014ae39SMin Li if (offset_fs > WRITE_PHASE_OFFSET_LIMIT) 1027e014ae39SMin Li offset_fs = WRITE_PHASE_OFFSET_LIMIT; 1028e014ae39SMin Li else if (offset_fs < -WRITE_PHASE_OFFSET_LIMIT) 1029e014ae39SMin Li offset_fs = -WRITE_PHASE_OFFSET_LIMIT; 1030e014ae39SMin Li 1031e014ae39SMin Li /* Convert from phaseoffset_fs to register value */ 1032e014ae39SMin Li offset_regval = div_s64(offset_fs * 1000, IDT_T0DPLL_PHASE_RESOL); 1033e014ae39SMin Li 1034e014ae39SMin Li val[0] = offset_regval & 0xFF; 1035e014ae39SMin Li val[1] = (offset_regval >> 8) & 0xFF; 1036e014ae39SMin Li val[2] = (offset_regval >> 16) & 0xFF; 1037e014ae39SMin Li val[3] = (offset_regval >> 24) & 0x1F; 1038e014ae39SMin Li val[3] |= PH_OFFSET_EN; 1039e014ae39SMin Li 1040013a3e7cSMin Li mutex_lock(idt82p33->lock); 1041e014ae39SMin Li 1042e014ae39SMin Li err = idt82p33_dpll_set_mode(channel, PLL_MODE_WPH); 1043e014ae39SMin Li if (err) { 1044013a3e7cSMin Li dev_err(idt82p33->dev, 1045e014ae39SMin Li "Failed in %s with err %d!\n", __func__, err); 1046e014ae39SMin Li goto out; 1047e014ae39SMin Li } 1048e014ae39SMin Li 1049e014ae39SMin Li err = idt82p33_write(idt82p33, channel->dpll_phase_cnfg, val, 1050e014ae39SMin Li sizeof(val)); 1051e014ae39SMin Li 1052e014ae39SMin Li out: 1053013a3e7cSMin Li mutex_unlock(idt82p33->lock); 1054e014ae39SMin Li return err; 1055e014ae39SMin Li } 1056e014ae39SMin Li 105757a10d8cSMin Li static int idt82p33_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 105857a10d8cSMin Li { 105957a10d8cSMin Li struct idt82p33_channel *channel = 106057a10d8cSMin Li container_of(ptp, struct idt82p33_channel, caps); 106157a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 106257a10d8cSMin Li int err; 106357a10d8cSMin Li 1064*ad3cc776SMin Li if (channel->ddco == true) 1065*ad3cc776SMin Li return 0; 1066*ad3cc776SMin Li 1067*ad3cc776SMin Li if (scaled_ppm == channel->current_freq) 1068*ad3cc776SMin Li return 0; 1069*ad3cc776SMin Li 1070013a3e7cSMin Li mutex_lock(idt82p33->lock); 107157a10d8cSMin Li err = _idt82p33_adjfine(channel, scaled_ppm); 1072*ad3cc776SMin Li 1073*ad3cc776SMin Li if (err == 0) 1074*ad3cc776SMin Li channel->current_freq = scaled_ppm; 1075013a3e7cSMin Li mutex_unlock(idt82p33->lock); 1076*ad3cc776SMin Li 1077e014ae39SMin Li if (err) 1078013a3e7cSMin Li dev_err(idt82p33->dev, 1079e014ae39SMin Li "Failed in %s with err %d!\n", __func__, err); 108057a10d8cSMin Li return err; 108157a10d8cSMin Li } 108257a10d8cSMin Li 108357a10d8cSMin Li static int idt82p33_adjtime(struct ptp_clock_info *ptp, s64 delta_ns) 108457a10d8cSMin Li { 108557a10d8cSMin Li struct idt82p33_channel *channel = 108657a10d8cSMin Li container_of(ptp, struct idt82p33_channel, caps); 108757a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 108857a10d8cSMin Li int err; 108957a10d8cSMin Li 1090*ad3cc776SMin Li if (channel->ddco == true) 1091*ad3cc776SMin Li return -EBUSY; 1092*ad3cc776SMin Li 1093013a3e7cSMin Li mutex_lock(idt82p33->lock); 109457a10d8cSMin Li 109557a10d8cSMin Li if (abs(delta_ns) < phase_snap_threshold) { 1096*ad3cc776SMin Li err = idt82p33_start_ddco(channel, delta_ns); 1097013a3e7cSMin Li mutex_unlock(idt82p33->lock); 1098*ad3cc776SMin Li return err; 109957a10d8cSMin Li } 110057a10d8cSMin Li 1101*ad3cc776SMin Li /* Use more accurate internal 1pps triggered write first */ 1102*ad3cc776SMin Li err = _idt82p33_adjtime_internal_triggered(channel, delta_ns); 1103*ad3cc776SMin Li if (err && delta_ns > IMMEDIATE_SNAP_THRESHOLD_NS) 1104*ad3cc776SMin Li err = _idt82p33_adjtime_immediate(channel, delta_ns); 110557a10d8cSMin Li 1106013a3e7cSMin Li mutex_unlock(idt82p33->lock); 110757a10d8cSMin Li 1108e014ae39SMin Li if (err) 1109013a3e7cSMin Li dev_err(idt82p33->dev, 1110013a3e7cSMin Li "Failed in %s with err %d!\n", __func__, err); 111157a10d8cSMin Li return err; 111257a10d8cSMin Li } 111357a10d8cSMin Li 111457a10d8cSMin Li static int idt82p33_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) 111557a10d8cSMin Li { 111657a10d8cSMin Li struct idt82p33_channel *channel = 111757a10d8cSMin Li container_of(ptp, struct idt82p33_channel, caps); 111857a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 111957a10d8cSMin Li int err; 112057a10d8cSMin Li 1121013a3e7cSMin Li mutex_lock(idt82p33->lock); 112257a10d8cSMin Li err = _idt82p33_gettime(channel, ts); 1123013a3e7cSMin Li mutex_unlock(idt82p33->lock); 112457a10d8cSMin Li 1125013a3e7cSMin Li if (err) 1126013a3e7cSMin Li dev_err(idt82p33->dev, 1127013a3e7cSMin Li "Failed in %s with err %d!\n", __func__, err); 112857a10d8cSMin Li return err; 112957a10d8cSMin Li } 113057a10d8cSMin Li 113157a10d8cSMin Li static int idt82p33_settime(struct ptp_clock_info *ptp, 113257a10d8cSMin Li const struct timespec64 *ts) 113357a10d8cSMin Li { 113457a10d8cSMin Li struct idt82p33_channel *channel = 113557a10d8cSMin Li container_of(ptp, struct idt82p33_channel, caps); 113657a10d8cSMin Li struct idt82p33 *idt82p33 = channel->idt82p33; 113757a10d8cSMin Li int err; 113857a10d8cSMin Li 1139013a3e7cSMin Li mutex_lock(idt82p33->lock); 114057a10d8cSMin Li err = _idt82p33_settime(channel, ts); 1141013a3e7cSMin Li mutex_unlock(idt82p33->lock); 114257a10d8cSMin Li 1143013a3e7cSMin Li if (err) 1144013a3e7cSMin Li dev_err(idt82p33->dev, 1145013a3e7cSMin Li "Failed in %s with err %d!\n", __func__, err); 114657a10d8cSMin Li return err; 114757a10d8cSMin Li } 114857a10d8cSMin Li 1149*ad3cc776SMin Li static int idt82p33_channel_init(struct idt82p33 *idt82p33, u32 index) 115057a10d8cSMin Li { 1151*ad3cc776SMin Li struct idt82p33_channel *channel = &idt82p33->channel[index]; 1152*ad3cc776SMin Li 115357a10d8cSMin Li switch (index) { 115457a10d8cSMin Li case 0: 115557a10d8cSMin Li channel->dpll_tod_cnfg = DPLL1_TOD_CNFG; 115657a10d8cSMin Li channel->dpll_tod_trigger = DPLL1_TOD_TRIGGER; 115757a10d8cSMin Li channel->dpll_tod_sts = DPLL1_TOD_STS; 115857a10d8cSMin Li channel->dpll_mode_cnfg = DPLL1_OPERATING_MODE_CNFG; 115957a10d8cSMin Li channel->dpll_freq_cnfg = DPLL1_HOLDOVER_FREQ_CNFG; 116057a10d8cSMin Li channel->dpll_phase_cnfg = DPLL1_PHASE_OFFSET_CNFG; 116157a10d8cSMin Li channel->dpll_sync_cnfg = DPLL1_SYNC_EDGE_CNFG; 116257a10d8cSMin Li channel->dpll_input_mode_cnfg = DPLL1_INPUT_MODE_CNFG; 116357a10d8cSMin Li break; 116457a10d8cSMin Li case 1: 116557a10d8cSMin Li channel->dpll_tod_cnfg = DPLL2_TOD_CNFG; 116657a10d8cSMin Li channel->dpll_tod_trigger = DPLL2_TOD_TRIGGER; 116757a10d8cSMin Li channel->dpll_tod_sts = DPLL2_TOD_STS; 116857a10d8cSMin Li channel->dpll_mode_cnfg = DPLL2_OPERATING_MODE_CNFG; 116957a10d8cSMin Li channel->dpll_freq_cnfg = DPLL2_HOLDOVER_FREQ_CNFG; 117057a10d8cSMin Li channel->dpll_phase_cnfg = DPLL2_PHASE_OFFSET_CNFG; 117157a10d8cSMin Li channel->dpll_sync_cnfg = DPLL2_SYNC_EDGE_CNFG; 117257a10d8cSMin Li channel->dpll_input_mode_cnfg = DPLL2_INPUT_MODE_CNFG; 117357a10d8cSMin Li break; 117457a10d8cSMin Li default: 117557a10d8cSMin Li return -EINVAL; 117657a10d8cSMin Li } 117757a10d8cSMin Li 1178*ad3cc776SMin Li channel->plln = index; 1179*ad3cc776SMin Li channel->current_freq = 0; 1180*ad3cc776SMin Li channel->idt82p33 = idt82p33; 1181*ad3cc776SMin Li INIT_DELAYED_WORK(&channel->adjtime_work, idt82p33_adjtime_workaround); 118257a10d8cSMin Li 118357a10d8cSMin Li return 0; 118457a10d8cSMin Li } 118557a10d8cSMin Li 1186*ad3cc776SMin Li static int idt82p33_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, 1187*ad3cc776SMin Li enum ptp_pin_function func, unsigned int chan) 118857a10d8cSMin Li { 1189*ad3cc776SMin Li switch (func) { 1190*ad3cc776SMin Li case PTP_PF_NONE: 1191*ad3cc776SMin Li case PTP_PF_EXTTS: 1192*ad3cc776SMin Li break; 1193*ad3cc776SMin Li case PTP_PF_PEROUT: 1194*ad3cc776SMin Li case PTP_PF_PHYSYNC: 1195*ad3cc776SMin Li return -1; 1196*ad3cc776SMin Li } 1197*ad3cc776SMin Li return 0; 1198*ad3cc776SMin Li } 1199*ad3cc776SMin Li 1200*ad3cc776SMin Li static void idt82p33_caps_init(u32 index, struct ptp_clock_info *caps, 1201*ad3cc776SMin Li struct ptp_pin_desc *pin_cfg, u8 max_pins) 1202*ad3cc776SMin Li { 1203*ad3cc776SMin Li struct ptp_pin_desc *ppd; 1204*ad3cc776SMin Li int i; 1205*ad3cc776SMin Li 120657a10d8cSMin Li caps->owner = THIS_MODULE; 1207013a3e7cSMin Li caps->max_adj = DCO_MAX_PPB; 1208*ad3cc776SMin Li caps->n_per_out = MAX_PER_OUT; 1209*ad3cc776SMin Li caps->n_ext_ts = MAX_PHC_PLL, 1210*ad3cc776SMin Li caps->n_pins = max_pins, 1211*ad3cc776SMin Li caps->adjphase = idt82p33_adjwritephase, 121257a10d8cSMin Li caps->adjfine = idt82p33_adjfine; 121357a10d8cSMin Li caps->adjtime = idt82p33_adjtime; 121457a10d8cSMin Li caps->gettime64 = idt82p33_gettime; 121557a10d8cSMin Li caps->settime64 = idt82p33_settime; 121657a10d8cSMin Li caps->enable = idt82p33_enable; 1217*ad3cc776SMin Li caps->verify = idt82p33_verify_pin; 1218*ad3cc776SMin Li caps->do_aux_work = idt82p33_work_handler; 1219*ad3cc776SMin Li 1220*ad3cc776SMin Li snprintf(caps->name, sizeof(caps->name), "IDT 82P33 PLL%u", index); 1221*ad3cc776SMin Li 1222*ad3cc776SMin Li caps->pin_config = pin_cfg; 1223*ad3cc776SMin Li 1224*ad3cc776SMin Li for (i = 0; i < max_pins; ++i) { 1225*ad3cc776SMin Li ppd = &pin_cfg[i]; 1226*ad3cc776SMin Li 1227*ad3cc776SMin Li ppd->index = i; 1228*ad3cc776SMin Li ppd->func = PTP_PF_NONE; 1229*ad3cc776SMin Li ppd->chan = index; 1230*ad3cc776SMin Li snprintf(ppd->name, sizeof(ppd->name), "in%d", 12 + i); 1231*ad3cc776SMin Li } 123257a10d8cSMin Li } 123357a10d8cSMin Li 123457a10d8cSMin Li static int idt82p33_enable_channel(struct idt82p33 *idt82p33, u32 index) 123557a10d8cSMin Li { 123657a10d8cSMin Li struct idt82p33_channel *channel; 123757a10d8cSMin Li int err; 123857a10d8cSMin Li 123957a10d8cSMin Li if (!(index < MAX_PHC_PLL)) 124057a10d8cSMin Li return -EINVAL; 124157a10d8cSMin Li 124257a10d8cSMin Li channel = &idt82p33->channel[index]; 124357a10d8cSMin Li 1244*ad3cc776SMin Li err = idt82p33_channel_init(idt82p33, index); 1245e014ae39SMin Li if (err) { 1246013a3e7cSMin Li dev_err(idt82p33->dev, 1247e014ae39SMin Li "Channel_init failed in %s with err %d!\n", 1248e014ae39SMin Li __func__, err); 124957a10d8cSMin Li return err; 1250e014ae39SMin Li } 125157a10d8cSMin Li 1252*ad3cc776SMin Li idt82p33_caps_init(index, &channel->caps, 1253*ad3cc776SMin Li pin_config[index], MAX_TRIG_CLK); 125457a10d8cSMin Li 125557a10d8cSMin Li channel->ptp_clock = ptp_clock_register(&channel->caps, NULL); 125657a10d8cSMin Li 125757a10d8cSMin Li if (IS_ERR(channel->ptp_clock)) { 125857a10d8cSMin Li err = PTR_ERR(channel->ptp_clock); 125957a10d8cSMin Li channel->ptp_clock = NULL; 126057a10d8cSMin Li return err; 126157a10d8cSMin Li } 126257a10d8cSMin Li 126357a10d8cSMin Li if (!channel->ptp_clock) 126457a10d8cSMin Li return -ENOTSUPP; 126557a10d8cSMin Li 1266e014ae39SMin Li err = idt82p33_dpll_set_mode(channel, PLL_MODE_DCO); 1267e014ae39SMin Li if (err) { 1268013a3e7cSMin Li dev_err(idt82p33->dev, 1269e014ae39SMin Li "Dpll_set_mode failed in %s with err %d!\n", 1270e014ae39SMin Li __func__, err); 1271e014ae39SMin Li return err; 1272e014ae39SMin Li } 1273e014ae39SMin Li 1274e014ae39SMin Li err = idt82p33_enable_tod(channel); 1275e014ae39SMin Li if (err) { 1276013a3e7cSMin Li dev_err(idt82p33->dev, 1277e014ae39SMin Li "Enable_tod failed in %s with err %d!\n", 1278e014ae39SMin Li __func__, err); 1279e014ae39SMin Li return err; 1280e014ae39SMin Li } 1281e014ae39SMin Li 1282013a3e7cSMin Li dev_info(idt82p33->dev, "PLL%d registered as ptp%d\n", 128357a10d8cSMin Li index, channel->ptp_clock->index); 128457a10d8cSMin Li 128557a10d8cSMin Li return 0; 128657a10d8cSMin Li } 128757a10d8cSMin Li 1288*ad3cc776SMin Li static int idt82p33_reset(struct idt82p33 *idt82p33, bool cold) 1289*ad3cc776SMin Li { 1290*ad3cc776SMin Li int err; 1291*ad3cc776SMin Li u8 cfg = SOFT_RESET_EN; 1292*ad3cc776SMin Li 1293*ad3cc776SMin Li if (cold == true) 1294*ad3cc776SMin Li goto cold_reset; 1295*ad3cc776SMin Li 1296*ad3cc776SMin Li err = idt82p33_read(idt82p33, REG_SOFT_RESET, &cfg, sizeof(cfg)); 1297*ad3cc776SMin Li if (err) { 1298*ad3cc776SMin Li dev_err(idt82p33->dev, 1299*ad3cc776SMin Li "Soft reset failed with err %d!\n", err); 1300*ad3cc776SMin Li return err; 1301*ad3cc776SMin Li } 1302*ad3cc776SMin Li 1303*ad3cc776SMin Li cfg |= SOFT_RESET_EN; 1304*ad3cc776SMin Li 1305*ad3cc776SMin Li cold_reset: 1306*ad3cc776SMin Li err = idt82p33_write(idt82p33, REG_SOFT_RESET, &cfg, sizeof(cfg)); 1307*ad3cc776SMin Li if (err) 1308*ad3cc776SMin Li dev_err(idt82p33->dev, 1309*ad3cc776SMin Li "Cold reset failed with err %d!\n", err); 1310*ad3cc776SMin Li return err; 1311*ad3cc776SMin Li } 1312*ad3cc776SMin Li 131357a10d8cSMin Li static int idt82p33_load_firmware(struct idt82p33 *idt82p33) 131457a10d8cSMin Li { 1315*ad3cc776SMin Li char fname[128] = FW_FILENAME; 131657a10d8cSMin Li const struct firmware *fw; 131757a10d8cSMin Li struct idt82p33_fwrc *rec; 131857a10d8cSMin Li u8 loaddr, page, val; 131957a10d8cSMin Li int err; 132057a10d8cSMin Li s32 len; 132157a10d8cSMin Li 1322*ad3cc776SMin Li if (firmware) /* module parameter */ 1323*ad3cc776SMin Li snprintf(fname, sizeof(fname), "%s", firmware); 132457a10d8cSMin Li 1325*ad3cc776SMin Li dev_info(idt82p33->dev, "requesting firmware '%s'\n", fname); 1326*ad3cc776SMin Li 1327*ad3cc776SMin Li err = request_firmware(&fw, fname, idt82p33->dev); 132857a10d8cSMin Li 1329e014ae39SMin Li if (err) { 1330013a3e7cSMin Li dev_err(idt82p33->dev, 1331e014ae39SMin Li "Failed in %s with err %d!\n", __func__, err); 133257a10d8cSMin Li return err; 1333e014ae39SMin Li } 133457a10d8cSMin Li 1335013a3e7cSMin Li dev_dbg(idt82p33->dev, "firmware size %zu bytes\n", fw->size); 133657a10d8cSMin Li 133757a10d8cSMin Li rec = (struct idt82p33_fwrc *) fw->data; 133857a10d8cSMin Li 133957a10d8cSMin Li for (len = fw->size; len > 0; len -= sizeof(*rec)) { 134057a10d8cSMin Li 134157a10d8cSMin Li if (rec->reserved) { 1342013a3e7cSMin Li dev_err(idt82p33->dev, 134357a10d8cSMin Li "bad firmware, reserved field non-zero\n"); 134457a10d8cSMin Li err = -EINVAL; 134557a10d8cSMin Li } else { 134657a10d8cSMin Li val = rec->value; 134757a10d8cSMin Li loaddr = rec->loaddr; 134857a10d8cSMin Li page = rec->hiaddr; 134957a10d8cSMin Li 135057a10d8cSMin Li rec++; 135157a10d8cSMin Li 135257a10d8cSMin Li err = idt82p33_check_and_set_masks(idt82p33, page, 135357a10d8cSMin Li loaddr, val); 135457a10d8cSMin Li } 135557a10d8cSMin Li 135657a10d8cSMin Li if (err == 0) { 135757a10d8cSMin Li /* Page size 128, last 4 bytes of page skipped */ 1358013a3e7cSMin Li if (loaddr > 0x7b) 135957a10d8cSMin Li continue; 136057a10d8cSMin Li 1361013a3e7cSMin Li err = idt82p33_write(idt82p33, REG_ADDR(page, loaddr), 136257a10d8cSMin Li &val, sizeof(val)); 136357a10d8cSMin Li } 136457a10d8cSMin Li 136557a10d8cSMin Li if (err) 136657a10d8cSMin Li goto out; 136757a10d8cSMin Li } 136857a10d8cSMin Li 136957a10d8cSMin Li idt82p33_display_masks(idt82p33); 137057a10d8cSMin Li out: 137157a10d8cSMin Li release_firmware(fw); 137257a10d8cSMin Li return err; 137357a10d8cSMin Li } 137457a10d8cSMin Li 1375*ad3cc776SMin Li static void idt82p33_extts_check(struct work_struct *work) 1376*ad3cc776SMin Li { 1377*ad3cc776SMin Li struct idt82p33 *idt82p33 = container_of(work, struct idt82p33, 1378*ad3cc776SMin Li extts_work.work); 1379*ad3cc776SMin Li struct idt82p33_channel *channel; 1380*ad3cc776SMin Li int err; 1381*ad3cc776SMin Li u8 mask; 1382*ad3cc776SMin Li int i; 1383*ad3cc776SMin Li 1384*ad3cc776SMin Li if (idt82p33->extts_mask == 0) 1385*ad3cc776SMin Li return; 1386*ad3cc776SMin Li 1387*ad3cc776SMin Li mutex_lock(idt82p33->lock); 1388*ad3cc776SMin Li 1389*ad3cc776SMin Li for (i = 0; i < MAX_PHC_PLL; i++) { 1390*ad3cc776SMin Li mask = 1 << i; 1391*ad3cc776SMin Li 1392*ad3cc776SMin Li if ((idt82p33->extts_mask & mask) == 0) 1393*ad3cc776SMin Li continue; 1394*ad3cc776SMin Li 1395*ad3cc776SMin Li err = idt82p33_extts_check_channel(idt82p33, i); 1396*ad3cc776SMin Li 1397*ad3cc776SMin Li if (err == 0) { 1398*ad3cc776SMin Li /* trigger clears itself, so clear the mask */ 1399*ad3cc776SMin Li if (idt82p33->extts_single_shot) { 1400*ad3cc776SMin Li idt82p33->extts_mask &= ~mask; 1401*ad3cc776SMin Li } else { 1402*ad3cc776SMin Li /* Re-arm */ 1403*ad3cc776SMin Li channel = &idt82p33->channel[i]; 1404*ad3cc776SMin Li arm_tod_read_with_trigger(channel, channel->tod_trigger); 1405*ad3cc776SMin Li } 1406*ad3cc776SMin Li } 1407*ad3cc776SMin Li } 1408*ad3cc776SMin Li 1409*ad3cc776SMin Li if (idt82p33->extts_mask) 1410*ad3cc776SMin Li schedule_delayed_work(&idt82p33->extts_work, 1411*ad3cc776SMin Li msecs_to_jiffies(EXTTS_PERIOD_MS)); 1412*ad3cc776SMin Li 1413*ad3cc776SMin Li mutex_unlock(idt82p33->lock); 1414*ad3cc776SMin Li } 141557a10d8cSMin Li 1416013a3e7cSMin Li static int idt82p33_probe(struct platform_device *pdev) 141757a10d8cSMin Li { 1418013a3e7cSMin Li struct rsmu_ddata *ddata = dev_get_drvdata(pdev->dev.parent); 141957a10d8cSMin Li struct idt82p33 *idt82p33; 142057a10d8cSMin Li int err; 142157a10d8cSMin Li u8 i; 142257a10d8cSMin Li 1423013a3e7cSMin Li idt82p33 = devm_kzalloc(&pdev->dev, 142457a10d8cSMin Li sizeof(struct idt82p33), GFP_KERNEL); 142557a10d8cSMin Li if (!idt82p33) 142657a10d8cSMin Li return -ENOMEM; 142757a10d8cSMin Li 1428013a3e7cSMin Li idt82p33->dev = &pdev->dev; 1429013a3e7cSMin Li idt82p33->mfd = pdev->dev.parent; 1430013a3e7cSMin Li idt82p33->lock = &ddata->lock; 1431013a3e7cSMin Li idt82p33->regmap = ddata->regmap; 143257a10d8cSMin Li idt82p33->tod_write_overhead_ns = 0; 143357a10d8cSMin Li idt82p33->calculate_overhead_flag = 0; 143457a10d8cSMin Li idt82p33->pll_mask = DEFAULT_PLL_MASK; 143557a10d8cSMin Li idt82p33->channel[0].output_mask = DEFAULT_OUTPUT_MASK_PLL0; 143657a10d8cSMin Li idt82p33->channel[1].output_mask = DEFAULT_OUTPUT_MASK_PLL1; 1437*ad3cc776SMin Li idt82p33->extts_mask = 0; 1438*ad3cc776SMin Li INIT_DELAYED_WORK(&idt82p33->extts_work, idt82p33_extts_check); 143957a10d8cSMin Li 1440013a3e7cSMin Li mutex_lock(idt82p33->lock); 144157a10d8cSMin Li 1442*ad3cc776SMin Li /* cold reset before loading firmware */ 1443*ad3cc776SMin Li idt82p33_reset(idt82p33, true); 144457a10d8cSMin Li 1445*ad3cc776SMin Li err = idt82p33_load_firmware(idt82p33); 144657a10d8cSMin Li if (err) 1447013a3e7cSMin Li dev_warn(idt82p33->dev, 144857a10d8cSMin Li "loading firmware failed with %d\n", err); 144957a10d8cSMin Li 1450*ad3cc776SMin Li /* soft reset after loading firmware */ 1451*ad3cc776SMin Li idt82p33_reset(idt82p33, false); 1452*ad3cc776SMin Li 145357a10d8cSMin Li if (idt82p33->pll_mask) { 145457a10d8cSMin Li for (i = 0; i < MAX_PHC_PLL; i++) { 1455*ad3cc776SMin Li if (idt82p33->pll_mask & (1 << i)) 145657a10d8cSMin Li err = idt82p33_enable_channel(idt82p33, i); 1457*ad3cc776SMin Li else 1458*ad3cc776SMin Li err = idt82p33_channel_init(idt82p33, i); 1459e014ae39SMin Li if (err) { 1460013a3e7cSMin Li dev_err(idt82p33->dev, 1461e014ae39SMin Li "Failed in %s with err %d!\n", 1462e014ae39SMin Li __func__, err); 146357a10d8cSMin Li break; 146457a10d8cSMin Li } 146557a10d8cSMin Li } 146657a10d8cSMin Li } else { 1467013a3e7cSMin Li dev_err(idt82p33->dev, 146857a10d8cSMin Li "no PLLs flagged as PHCs, nothing to do\n"); 146957a10d8cSMin Li err = -ENODEV; 147057a10d8cSMin Li } 147157a10d8cSMin Li 1472013a3e7cSMin Li mutex_unlock(idt82p33->lock); 147357a10d8cSMin Li 147457a10d8cSMin Li if (err) { 147557a10d8cSMin Li idt82p33_ptp_clock_unregister_all(idt82p33); 147657a10d8cSMin Li return err; 147757a10d8cSMin Li } 147857a10d8cSMin Li 1479013a3e7cSMin Li platform_set_drvdata(pdev, idt82p33); 148057a10d8cSMin Li 148157a10d8cSMin Li return 0; 148257a10d8cSMin Li } 148357a10d8cSMin Li 1484013a3e7cSMin Li static int idt82p33_remove(struct platform_device *pdev) 148557a10d8cSMin Li { 1486013a3e7cSMin Li struct idt82p33 *idt82p33 = platform_get_drvdata(pdev); 148757a10d8cSMin Li 1488*ad3cc776SMin Li cancel_delayed_work_sync(&idt82p33->extts_work); 1489*ad3cc776SMin Li 149057a10d8cSMin Li idt82p33_ptp_clock_unregister_all(idt82p33); 149157a10d8cSMin Li 149257a10d8cSMin Li return 0; 149357a10d8cSMin Li } 149457a10d8cSMin Li 1495013a3e7cSMin Li static struct platform_driver idt82p33_driver = { 149657a10d8cSMin Li .driver = { 1497013a3e7cSMin Li .name = "82p33x1x-phc", 149857a10d8cSMin Li }, 149957a10d8cSMin Li .probe = idt82p33_probe, 150057a10d8cSMin Li .remove = idt82p33_remove, 150157a10d8cSMin Li }; 150257a10d8cSMin Li 1503013a3e7cSMin Li module_platform_driver(idt82p33_driver); 1504