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.

Merge branch 'dpll-zl3073x-add-misc-features'

Ivan Vecera says:

====================
dpll: zl3073x: Add misc features

Add several new features missing in initial submission:

* Embedded sync for both pin types
* Phase offset reporting for connected input pin
* Selectable phase offset monitoring (aka all inputs phase monitor)
* Phase adjustments for both pin types
* Fractional frequency offset reporting for input pins

Everything was tested on Microchip EVB-LAN9668 EDS2 development board.
====================

Link: https://patch.msgid.link/20250715144633.149156-1-ivecera@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

Paolo Abeni e0c7e315 44eb62e1

+1062 -2
+171
drivers/dpll/zl3073x/core.c
··· 669 669 return rc; 670 670 } 671 671 672 + /** 673 + * zl3073x_ref_phase_offsets_update - update reference phase offsets 674 + * @zldev: pointer to zl3073x_dev structure 675 + * @channel: DPLL channel number or -1 676 + * 677 + * The function asks device to update phase offsets latch registers with 678 + * the latest measured values. There are 2 sets of latch registers: 679 + * 680 + * 1) Up to 5 DPLL-to-connected-ref registers that contain phase offset 681 + * values between particular DPLL channel and its *connected* input 682 + * reference. 683 + * 684 + * 2) 10 selected-DPLL-to-all-ref registers that contain phase offset values 685 + * between selected DPLL channel and all input references. 686 + * 687 + * If the caller is interested in 2) then it has to pass DPLL channel number 688 + * in @channel parameter. If it is interested only in 1) then it should pass 689 + * @channel parameter with value of -1. 690 + * 691 + * Return: 0 on success, <0 on error 692 + */ 693 + int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel) 694 + { 695 + int rc; 696 + 697 + /* Per datasheet we have to wait for 'dpll_ref_phase_err_rqst_rd' 698 + * to be zero to ensure that the measured data are coherent. 699 + */ 700 + rc = zl3073x_poll_zero_u8(zldev, ZL_REG_REF_PHASE_ERR_READ_RQST, 701 + ZL_REF_PHASE_ERR_READ_RQST_RD); 702 + if (rc) 703 + return rc; 704 + 705 + /* Select DPLL channel if it is specified */ 706 + if (channel != -1) { 707 + rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_IDX, channel); 708 + if (rc) 709 + return rc; 710 + } 711 + 712 + /* Request to update phase offsets measurement values */ 713 + rc = zl3073x_write_u8(zldev, ZL_REG_REF_PHASE_ERR_READ_RQST, 714 + ZL_REF_PHASE_ERR_READ_RQST_RD); 715 + if (rc) 716 + return rc; 717 + 718 + /* Wait for finish */ 719 + return zl3073x_poll_zero_u8(zldev, ZL_REG_REF_PHASE_ERR_READ_RQST, 720 + ZL_REF_PHASE_ERR_READ_RQST_RD); 721 + } 722 + 723 + /** 724 + * zl3073x_ref_ffo_update - update reference fractional frequency offsets 725 + * @zldev: pointer to zl3073x_dev structure 726 + * 727 + * The function asks device to update fractional frequency offsets latch 728 + * registers the latest measured values, reads and stores them into 729 + * 730 + * Return: 0 on success, <0 on error 731 + */ 732 + static int 733 + zl3073x_ref_ffo_update(struct zl3073x_dev *zldev) 734 + { 735 + int i, rc; 736 + 737 + /* Per datasheet we have to wait for 'ref_freq_meas_ctrl' to be zero 738 + * to ensure that the measured data are coherent. 739 + */ 740 + rc = zl3073x_poll_zero_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL, 741 + ZL_REF_FREQ_MEAS_CTRL); 742 + if (rc) 743 + return rc; 744 + 745 + /* Select all references for measurement */ 746 + rc = zl3073x_write_u8(zldev, ZL_REG_REF_FREQ_MEAS_MASK_3_0, 747 + GENMASK(7, 0)); /* REF0P..REF3N */ 748 + if (rc) 749 + return rc; 750 + rc = zl3073x_write_u8(zldev, ZL_REG_REF_FREQ_MEAS_MASK_4, 751 + GENMASK(1, 0)); /* REF4P..REF4N */ 752 + if (rc) 753 + return rc; 754 + 755 + /* Request frequency offset measurement */ 756 + rc = zl3073x_write_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL, 757 + ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF); 758 + if (rc) 759 + return rc; 760 + 761 + /* Wait for finish */ 762 + rc = zl3073x_poll_zero_u8(zldev, ZL_REG_REF_FREQ_MEAS_CTRL, 763 + ZL_REF_FREQ_MEAS_CTRL); 764 + if (rc) 765 + return rc; 766 + 767 + /* Read DPLL-to-REFx frequency offset measurements */ 768 + for (i = 0; i < ZL3073X_NUM_REFS; i++) { 769 + s32 value; 770 + 771 + /* Read value stored in units of 2^-32 signed */ 772 + rc = zl3073x_read_u32(zldev, ZL_REG_REF_FREQ(i), &value); 773 + if (rc) 774 + return rc; 775 + 776 + /* Convert to ppm -> ffo = (10^6 * value) / 2^32 */ 777 + zldev->ref[i].ffo = mul_s64_u64_shr(value, 1000000, 32); 778 + } 779 + 780 + return 0; 781 + } 782 + 672 783 static void 673 784 zl3073x_dev_periodic_work(struct kthread_work *work) 674 785 { 675 786 struct zl3073x_dev *zldev = container_of(work, struct zl3073x_dev, 676 787 work.work); 677 788 struct zl3073x_dpll *zldpll; 789 + int rc; 790 + 791 + /* Update DPLL-to-connected-ref phase offsets registers */ 792 + rc = zl3073x_ref_phase_offsets_update(zldev, -1); 793 + if (rc) 794 + dev_warn(zldev->dev, "Failed to update phase offsets: %pe\n", 795 + ERR_PTR(rc)); 796 + 797 + /* Update references' fractional frequency offsets */ 798 + rc = zl3073x_ref_ffo_update(zldev); 799 + if (rc) 800 + dev_warn(zldev->dev, 801 + "Failed to update fractional frequency offsets: %pe\n", 802 + ERR_PTR(rc)); 678 803 679 804 list_for_each_entry(zldpll, &zldev->dplls, list) 680 805 zl3073x_dpll_changes_check(zldpll); ··· 893 768 } 894 769 895 770 /** 771 + * zl3073x_dev_phase_meas_setup - setup phase offset measurement 772 + * @zldev: pointer to zl3073x_dev structure 773 + * @num_channels: number of DPLL channels 774 + * 775 + * Enable phase offset measurement block, set measurement averaging factor 776 + * and enable DPLL-to-its-ref phase measurement for all DPLLs. 777 + * 778 + * Returns: 0 on success, <0 on error 779 + */ 780 + static int 781 + zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev, int num_channels) 782 + { 783 + u8 dpll_meas_ctrl, mask; 784 + int i, rc; 785 + 786 + /* Read DPLL phase measurement control register */ 787 + rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl); 788 + if (rc) 789 + return rc; 790 + 791 + /* Setup phase measurement averaging factor */ 792 + dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR; 793 + dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, 3); 794 + 795 + /* Enable DPLL measurement block */ 796 + dpll_meas_ctrl |= ZL_DPLL_MEAS_CTRL_EN; 797 + 798 + /* Update phase measurement control register */ 799 + rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl); 800 + if (rc) 801 + return rc; 802 + 803 + /* Enable DPLL-to-connected-ref measurement for each channel */ 804 + for (i = 0, mask = 0; i < num_channels; i++) 805 + mask |= BIT(i); 806 + 807 + return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask); 808 + } 809 + 810 + /** 896 811 * zl3073x_dev_probe - initialize zl3073x device 897 812 * @zldev: pointer to zl3073x device 898 813 * @chip_info: chip info based on compatible ··· 1003 838 rc = zl3073x_dev_state_fetch(zldev); 1004 839 if (rc) 1005 840 return rc; 841 + 842 + /* Setup phase offset measurement block */ 843 + rc = zl3073x_dev_phase_meas_setup(zldev, chip_info->num_channels); 844 + if (rc) 845 + return dev_err_probe(zldev->dev, rc, 846 + "Failed to setup phase measurement\n"); 1006 847 1007 848 /* Register DPLL channels */ 1008 849 rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels);
+16
drivers/dpll/zl3073x/core.h
··· 30 30 * struct zl3073x_ref - input reference invariant info 31 31 * @enabled: input reference is enabled or disabled 32 32 * @diff: true if input reference is differential 33 + * @ffo: current fractional frequency offset 33 34 */ 34 35 struct zl3073x_ref { 35 36 bool enabled; 36 37 bool diff; 38 + s64 ffo; 37 39 }; 38 40 39 41 /** ··· 132 130 *****************/ 133 131 134 132 int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult); 133 + int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel); 135 134 136 135 static inline bool 137 136 zl3073x_is_n_pin(u8 id) ··· 170 167 { 171 168 /* Output pin pair shares the single output */ 172 169 return id / 2; 170 + } 171 + 172 + /** 173 + * zl3073x_ref_ffo_get - get current fractional frequency offset 174 + * @zldev: pointer to zl3073x device 175 + * @index: input reference index 176 + * 177 + * Return: the latest measured fractional frequency offset 178 + */ 179 + static inline s64 180 + zl3073x_ref_ffo_get(struct zl3073x_dev *zldev, u8 index) 181 + { 182 + return zldev->ref[index].ffo; 173 183 } 174 184 175 185 /**
+816 -2
drivers/dpll/zl3073x/dpll.c
··· 34 34 * @id: pin id 35 35 * @prio: pin priority <0, 14> 36 36 * @selectable: pin is selectable in automatic mode 37 + * @esync_control: embedded sync is controllable 37 38 * @pin_state: last saved pin state 39 + * @phase_offset: last saved pin phase offset 40 + * @freq_offset: last saved fractional frequency offset 38 41 */ 39 42 struct zl3073x_dpll_pin { 40 43 struct list_head list; ··· 48 45 u8 id; 49 46 u8 prio; 50 47 bool selectable; 48 + bool esync_control; 51 49 enum dpll_pin_state pin_state; 50 + s64 phase_offset; 51 + s64 freq_offset; 52 + }; 53 + 54 + /* 55 + * Supported esync ranges for input and for output per output pair type 56 + */ 57 + static const struct dpll_pin_frequency esync_freq_ranges[] = { 58 + DPLL_PIN_FREQUENCY_RANGE(0, 1), 52 59 }; 53 60 54 61 /** ··· 150 137 *frequency = mul_u64_u32_div(base * mult, num, denom); 151 138 152 139 return rc; 140 + } 141 + 142 + static int 143 + zl3073x_dpll_input_pin_esync_get(const struct dpll_pin *dpll_pin, 144 + void *pin_priv, 145 + const struct dpll_device *dpll, 146 + void *dpll_priv, 147 + struct dpll_pin_esync *esync, 148 + struct netlink_ext_ack *extack) 149 + { 150 + struct zl3073x_dpll *zldpll = dpll_priv; 151 + struct zl3073x_dev *zldev = zldpll->dev; 152 + struct zl3073x_dpll_pin *pin = pin_priv; 153 + u8 ref, ref_sync_ctrl, sync_mode; 154 + u32 esync_div, ref_freq; 155 + int rc; 156 + 157 + /* Get reference frequency */ 158 + ref = zl3073x_input_pin_ref_get(pin->id); 159 + rc = zl3073x_dpll_input_ref_frequency_get(zldpll, pin->id, &ref_freq); 160 + if (rc) 161 + return rc; 162 + 163 + guard(mutex)(&zldev->multiop_lock); 164 + 165 + /* Read reference configuration into mailbox */ 166 + rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD, 167 + ZL_REG_REF_MB_MASK, BIT(ref)); 168 + if (rc) 169 + return rc; 170 + 171 + /* Get ref sync mode */ 172 + rc = zl3073x_read_u8(zldev, ZL_REG_REF_SYNC_CTRL, &ref_sync_ctrl); 173 + if (rc) 174 + return rc; 175 + 176 + /* Get esync divisor */ 177 + rc = zl3073x_read_u32(zldev, ZL_REG_REF_ESYNC_DIV, &esync_div); 178 + if (rc) 179 + return rc; 180 + 181 + sync_mode = FIELD_GET(ZL_REF_SYNC_CTRL_MODE, ref_sync_ctrl); 182 + 183 + switch (sync_mode) { 184 + case ZL_REF_SYNC_CTRL_MODE_50_50_ESYNC_25_75: 185 + esync->freq = (esync_div == ZL_REF_ESYNC_DIV_1HZ) ? 1 : 0; 186 + esync->pulse = 25; 187 + break; 188 + default: 189 + esync->freq = 0; 190 + esync->pulse = 0; 191 + break; 192 + } 193 + 194 + /* If the pin supports esync control expose its range but only 195 + * if the current reference frequency is > 1 Hz. 196 + */ 197 + if (pin->esync_control && ref_freq > 1) { 198 + esync->range = esync_freq_ranges; 199 + esync->range_num = ARRAY_SIZE(esync_freq_ranges); 200 + } else { 201 + esync->range = NULL; 202 + esync->range_num = 0; 203 + } 204 + 205 + return rc; 206 + } 207 + 208 + static int 209 + zl3073x_dpll_input_pin_esync_set(const struct dpll_pin *dpll_pin, 210 + void *pin_priv, 211 + const struct dpll_device *dpll, 212 + void *dpll_priv, u64 freq, 213 + struct netlink_ext_ack *extack) 214 + { 215 + struct zl3073x_dpll *zldpll = dpll_priv; 216 + struct zl3073x_dev *zldev = zldpll->dev; 217 + struct zl3073x_dpll_pin *pin = pin_priv; 218 + u8 ref, ref_sync_ctrl, sync_mode; 219 + int rc; 220 + 221 + guard(mutex)(&zldev->multiop_lock); 222 + 223 + /* Read reference configuration into mailbox */ 224 + ref = zl3073x_input_pin_ref_get(pin->id); 225 + rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD, 226 + ZL_REG_REF_MB_MASK, BIT(ref)); 227 + if (rc) 228 + return rc; 229 + 230 + /* Get ref sync mode */ 231 + rc = zl3073x_read_u8(zldev, ZL_REG_REF_SYNC_CTRL, &ref_sync_ctrl); 232 + if (rc) 233 + return rc; 234 + 235 + /* Use freq == 0 to disable esync */ 236 + if (!freq) 237 + sync_mode = ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR_OFF; 238 + else 239 + sync_mode = ZL_REF_SYNC_CTRL_MODE_50_50_ESYNC_25_75; 240 + 241 + ref_sync_ctrl &= ~ZL_REF_SYNC_CTRL_MODE; 242 + ref_sync_ctrl |= FIELD_PREP(ZL_REF_SYNC_CTRL_MODE, sync_mode); 243 + 244 + /* Update ref sync control register */ 245 + rc = zl3073x_write_u8(zldev, ZL_REG_REF_SYNC_CTRL, ref_sync_ctrl); 246 + if (rc) 247 + return rc; 248 + 249 + if (freq) { 250 + /* 1 Hz is only supported frequnecy currently */ 251 + rc = zl3073x_write_u32(zldev, ZL_REG_REF_ESYNC_DIV, 252 + ZL_REF_ESYNC_DIV_1HZ); 253 + if (rc) 254 + return rc; 255 + } 256 + 257 + /* Commit reference configuration */ 258 + return zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_WR, 259 + ZL_REG_REF_MB_MASK, BIT(ref)); 260 + } 261 + 262 + static int 263 + zl3073x_dpll_input_pin_ffo_get(const struct dpll_pin *dpll_pin, void *pin_priv, 264 + const struct dpll_device *dpll, void *dpll_priv, 265 + s64 *ffo, struct netlink_ext_ack *extack) 266 + { 267 + struct zl3073x_dpll_pin *pin = pin_priv; 268 + 269 + *ffo = pin->freq_offset; 270 + 271 + return 0; 153 272 } 154 273 155 274 static int ··· 510 365 } 511 366 512 367 return 0; 368 + } 369 + 370 + static int 371 + zl3073x_dpll_input_pin_phase_offset_get(const struct dpll_pin *dpll_pin, 372 + void *pin_priv, 373 + const struct dpll_device *dpll, 374 + void *dpll_priv, s64 *phase_offset, 375 + struct netlink_ext_ack *extack) 376 + { 377 + struct zl3073x_dpll *zldpll = dpll_priv; 378 + struct zl3073x_dev *zldev = zldpll->dev; 379 + struct zl3073x_dpll_pin *pin = pin_priv; 380 + u8 conn_ref, ref, ref_status; 381 + s64 ref_phase; 382 + int rc; 383 + 384 + /* Get currently connected reference */ 385 + rc = zl3073x_dpll_connected_ref_get(zldpll, &conn_ref); 386 + if (rc) 387 + return rc; 388 + 389 + /* Report phase offset only for currently connected pin if the phase 390 + * monitor feature is disabled. 391 + */ 392 + ref = zl3073x_input_pin_ref_get(pin->id); 393 + if (!zldpll->phase_monitor && ref != conn_ref) { 394 + *phase_offset = 0; 395 + 396 + return 0; 397 + } 398 + 399 + /* Get this pin monitor status */ 400 + rc = zl3073x_read_u8(zldev, ZL_REG_REF_MON_STATUS(ref), &ref_status); 401 + if (rc) 402 + return rc; 403 + 404 + /* Report phase offset only if the input pin signal is present */ 405 + if (ref_status != ZL_REF_MON_STATUS_OK) { 406 + *phase_offset = 0; 407 + 408 + return 0; 409 + } 410 + 411 + ref_phase = pin->phase_offset; 412 + 413 + /* The DPLL being locked to a higher freq than the current ref 414 + * the phase offset is modded to the period of the signal 415 + * the dpll is locked to. 416 + */ 417 + if (ZL3073X_DPLL_REF_IS_VALID(conn_ref) && conn_ref != ref) { 418 + u32 conn_freq, ref_freq; 419 + 420 + /* Get frequency of connected ref */ 421 + rc = zl3073x_dpll_input_ref_frequency_get(zldpll, conn_ref, 422 + &conn_freq); 423 + if (rc) 424 + return rc; 425 + 426 + /* Get frequency of given ref */ 427 + rc = zl3073x_dpll_input_ref_frequency_get(zldpll, ref, 428 + &ref_freq); 429 + if (rc) 430 + return rc; 431 + 432 + if (conn_freq > ref_freq) { 433 + s64 conn_period, div_factor; 434 + 435 + conn_period = div_s64(PSEC_PER_SEC, conn_freq); 436 + div_factor = div64_s64(ref_phase, conn_period); 437 + ref_phase -= conn_period * div_factor; 438 + } 439 + } 440 + 441 + *phase_offset = ref_phase * DPLL_PHASE_OFFSET_DIVIDER; 442 + 443 + return rc; 444 + } 445 + 446 + static int 447 + zl3073x_dpll_input_pin_phase_adjust_get(const struct dpll_pin *dpll_pin, 448 + void *pin_priv, 449 + const struct dpll_device *dpll, 450 + void *dpll_priv, 451 + s32 *phase_adjust, 452 + struct netlink_ext_ack *extack) 453 + { 454 + struct zl3073x_dpll *zldpll = dpll_priv; 455 + struct zl3073x_dev *zldev = zldpll->dev; 456 + struct zl3073x_dpll_pin *pin = pin_priv; 457 + s64 phase_comp; 458 + u8 ref; 459 + int rc; 460 + 461 + guard(mutex)(&zldev->multiop_lock); 462 + 463 + /* Read reference configuration */ 464 + ref = zl3073x_input_pin_ref_get(pin->id); 465 + rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD, 466 + ZL_REG_REF_MB_MASK, BIT(ref)); 467 + if (rc) 468 + return rc; 469 + 470 + /* Read current phase offset compensation */ 471 + rc = zl3073x_read_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP, &phase_comp); 472 + if (rc) 473 + return rc; 474 + 475 + /* Perform sign extension for 48bit signed value */ 476 + phase_comp = sign_extend64(phase_comp, 47); 477 + 478 + /* Reverse two's complement negation applied during set and convert 479 + * to 32bit signed int 480 + */ 481 + *phase_adjust = (s32)-phase_comp; 482 + 483 + return rc; 484 + } 485 + 486 + static int 487 + zl3073x_dpll_input_pin_phase_adjust_set(const struct dpll_pin *dpll_pin, 488 + void *pin_priv, 489 + const struct dpll_device *dpll, 490 + void *dpll_priv, 491 + s32 phase_adjust, 492 + struct netlink_ext_ack *extack) 493 + { 494 + struct zl3073x_dpll *zldpll = dpll_priv; 495 + struct zl3073x_dev *zldev = zldpll->dev; 496 + struct zl3073x_dpll_pin *pin = pin_priv; 497 + s64 phase_comp; 498 + u8 ref; 499 + int rc; 500 + 501 + /* The value in the register is stored as two's complement negation 502 + * of requested value. 503 + */ 504 + phase_comp = -phase_adjust; 505 + 506 + guard(mutex)(&zldev->multiop_lock); 507 + 508 + /* Read reference configuration */ 509 + ref = zl3073x_input_pin_ref_get(pin->id); 510 + rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD, 511 + ZL_REG_REF_MB_MASK, BIT(ref)); 512 + if (rc) 513 + return rc; 514 + 515 + /* Write the requested value into the compensation register */ 516 + rc = zl3073x_write_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP, phase_comp); 517 + if (rc) 518 + return rc; 519 + 520 + /* Commit reference configuration */ 521 + return zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_WR, 522 + ZL_REG_REF_MB_MASK, BIT(ref)); 513 523 } 514 524 515 525 /** ··· 941 641 } 942 642 943 643 static int 644 + zl3073x_dpll_output_pin_esync_get(const struct dpll_pin *dpll_pin, 645 + void *pin_priv, 646 + const struct dpll_device *dpll, 647 + void *dpll_priv, 648 + struct dpll_pin_esync *esync, 649 + struct netlink_ext_ack *extack) 650 + { 651 + struct zl3073x_dpll *zldpll = dpll_priv; 652 + struct zl3073x_dev *zldev = zldpll->dev; 653 + struct zl3073x_dpll_pin *pin = pin_priv; 654 + struct device *dev = zldev->dev; 655 + u32 esync_period, esync_width; 656 + u8 clock_type, synth; 657 + u8 out, output_mode; 658 + u32 output_div; 659 + u32 synth_freq; 660 + int rc; 661 + 662 + out = zl3073x_output_pin_out_get(pin->id); 663 + 664 + /* If N-division is enabled, esync is not supported. The register used 665 + * for N-division is also used for the esync divider so both cannot 666 + * be used. 667 + */ 668 + switch (zl3073x_out_signal_format_get(zldev, out)) { 669 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV: 670 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV: 671 + return -EOPNOTSUPP; 672 + default: 673 + break; 674 + } 675 + 676 + guard(mutex)(&zldev->multiop_lock); 677 + 678 + /* Read output configuration into mailbox */ 679 + rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 680 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 681 + if (rc) 682 + return rc; 683 + 684 + /* Read output mode */ 685 + rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_MODE, &output_mode); 686 + if (rc) 687 + return rc; 688 + 689 + /* Read output divisor */ 690 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_DIV, &output_div); 691 + if (rc) 692 + return rc; 693 + 694 + /* Check output divisor for zero */ 695 + if (!output_div) { 696 + dev_err(dev, "Zero divisor for OUTPUT%u got from device\n", 697 + out); 698 + return -EINVAL; 699 + } 700 + 701 + /* Get synth attached to output pin */ 702 + synth = zl3073x_out_synth_get(zldev, out); 703 + 704 + /* Get synth frequency */ 705 + synth_freq = zl3073x_synth_freq_get(zldev, synth); 706 + 707 + clock_type = FIELD_GET(ZL_OUTPUT_MODE_CLOCK_TYPE, output_mode); 708 + if (clock_type != ZL_OUTPUT_MODE_CLOCK_TYPE_ESYNC) { 709 + /* No need to read esync data if it is not enabled */ 710 + esync->freq = 0; 711 + esync->pulse = 0; 712 + 713 + goto finish; 714 + } 715 + 716 + /* Read esync period */ 717 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_ESYNC_PERIOD, &esync_period); 718 + if (rc) 719 + return rc; 720 + 721 + /* Check esync divisor for zero */ 722 + if (!esync_period) { 723 + dev_err(dev, "Zero esync divisor for OUTPUT%u got from device\n", 724 + out); 725 + return -EINVAL; 726 + } 727 + 728 + /* Get esync pulse width in units of half synth cycles */ 729 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_ESYNC_WIDTH, &esync_width); 730 + if (rc) 731 + return rc; 732 + 733 + /* Compute esync frequency */ 734 + esync->freq = synth_freq / output_div / esync_period; 735 + 736 + /* By comparing the esync_pulse_width to the half of the pulse width 737 + * the esync pulse percentage can be determined. 738 + * Note that half pulse width is in units of half synth cycles, which 739 + * is why it reduces down to be output_div. 740 + */ 741 + esync->pulse = (50 * esync_width) / output_div; 742 + 743 + finish: 744 + /* Set supported esync ranges if the pin supports esync control and 745 + * if the output frequency is > 1 Hz. 746 + */ 747 + if (pin->esync_control && (synth_freq / output_div) > 1) { 748 + esync->range = esync_freq_ranges; 749 + esync->range_num = ARRAY_SIZE(esync_freq_ranges); 750 + } else { 751 + esync->range = NULL; 752 + esync->range_num = 0; 753 + } 754 + 755 + return 0; 756 + } 757 + 758 + static int 759 + zl3073x_dpll_output_pin_esync_set(const struct dpll_pin *dpll_pin, 760 + void *pin_priv, 761 + const struct dpll_device *dpll, 762 + void *dpll_priv, u64 freq, 763 + struct netlink_ext_ack *extack) 764 + { 765 + u32 esync_period, esync_width, output_div; 766 + struct zl3073x_dpll *zldpll = dpll_priv; 767 + struct zl3073x_dev *zldev = zldpll->dev; 768 + struct zl3073x_dpll_pin *pin = pin_priv; 769 + u8 clock_type, out, output_mode, synth; 770 + u32 synth_freq; 771 + int rc; 772 + 773 + out = zl3073x_output_pin_out_get(pin->id); 774 + 775 + /* If N-division is enabled, esync is not supported. The register used 776 + * for N-division is also used for the esync divider so both cannot 777 + * be used. 778 + */ 779 + switch (zl3073x_out_signal_format_get(zldev, out)) { 780 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV: 781 + case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV: 782 + return -EOPNOTSUPP; 783 + default: 784 + break; 785 + } 786 + 787 + guard(mutex)(&zldev->multiop_lock); 788 + 789 + /* Read output configuration into mailbox */ 790 + rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 791 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 792 + if (rc) 793 + return rc; 794 + 795 + /* Read output mode */ 796 + rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_MODE, &output_mode); 797 + if (rc) 798 + return rc; 799 + 800 + /* Select clock type */ 801 + if (freq) 802 + clock_type = ZL_OUTPUT_MODE_CLOCK_TYPE_ESYNC; 803 + else 804 + clock_type = ZL_OUTPUT_MODE_CLOCK_TYPE_NORMAL; 805 + 806 + /* Update clock type in output mode */ 807 + output_mode &= ~ZL_OUTPUT_MODE_CLOCK_TYPE; 808 + output_mode |= FIELD_PREP(ZL_OUTPUT_MODE_CLOCK_TYPE, clock_type); 809 + rc = zl3073x_write_u8(zldev, ZL_REG_OUTPUT_MODE, output_mode); 810 + if (rc) 811 + return rc; 812 + 813 + /* If esync is being disabled just write mailbox and finish */ 814 + if (!freq) 815 + goto write_mailbox; 816 + 817 + /* Get synth attached to output pin */ 818 + synth = zl3073x_out_synth_get(zldev, out); 819 + 820 + /* Get synth frequency */ 821 + synth_freq = zl3073x_synth_freq_get(zldev, synth); 822 + 823 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_DIV, &output_div); 824 + if (rc) 825 + return rc; 826 + 827 + /* Check output divisor for zero */ 828 + if (!output_div) { 829 + dev_err(zldev->dev, 830 + "Zero divisor for OUTPUT%u got from device\n", out); 831 + return -EINVAL; 832 + } 833 + 834 + /* Compute and update esync period */ 835 + esync_period = synth_freq / (u32)freq / output_div; 836 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_ESYNC_PERIOD, esync_period); 837 + if (rc) 838 + return rc; 839 + 840 + /* Half of the period in units of 1/2 synth cycle can be represented by 841 + * the output_div. To get the supported esync pulse width of 25% of the 842 + * period the output_div can just be divided by 2. Note that this 843 + * assumes that output_div is even, otherwise some resolution will be 844 + * lost. 845 + */ 846 + esync_width = output_div / 2; 847 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_ESYNC_WIDTH, esync_width); 848 + if (rc) 849 + return rc; 850 + 851 + write_mailbox: 852 + /* Commit output configuration */ 853 + return zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_WR, 854 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 855 + } 856 + 857 + static int 944 858 zl3073x_dpll_output_pin_frequency_get(const struct dpll_pin *dpll_pin, 945 859 void *pin_priv, 946 860 const struct dpll_device *dpll, ··· 1378 864 } 1379 865 1380 866 static int 867 + zl3073x_dpll_output_pin_phase_adjust_get(const struct dpll_pin *dpll_pin, 868 + void *pin_priv, 869 + const struct dpll_device *dpll, 870 + void *dpll_priv, 871 + s32 *phase_adjust, 872 + struct netlink_ext_ack *extack) 873 + { 874 + struct zl3073x_dpll *zldpll = dpll_priv; 875 + struct zl3073x_dev *zldev = zldpll->dev; 876 + struct zl3073x_dpll_pin *pin = pin_priv; 877 + u32 synth_freq; 878 + s32 phase_comp; 879 + u8 out, synth; 880 + int rc; 881 + 882 + out = zl3073x_output_pin_out_get(pin->id); 883 + synth = zl3073x_out_synth_get(zldev, out); 884 + synth_freq = zl3073x_synth_freq_get(zldev, synth); 885 + 886 + /* Check synth freq for zero */ 887 + if (!synth_freq) { 888 + dev_err(zldev->dev, "Got zero synth frequency for output %u\n", 889 + out); 890 + return -EINVAL; 891 + } 892 + 893 + guard(mutex)(&zldev->multiop_lock); 894 + 895 + /* Read output configuration */ 896 + rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 897 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 898 + if (rc) 899 + return rc; 900 + 901 + /* Read current output phase compensation */ 902 + rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_PHASE_COMP, &phase_comp); 903 + if (rc) 904 + return rc; 905 + 906 + /* Value in register is expressed in half synth clock cycles */ 907 + phase_comp *= (int)div_u64(PSEC_PER_SEC, 2 * synth_freq); 908 + 909 + /* Reverse two's complement negation applied during 'set' */ 910 + *phase_adjust = -phase_comp; 911 + 912 + return rc; 913 + } 914 + 915 + static int 916 + zl3073x_dpll_output_pin_phase_adjust_set(const struct dpll_pin *dpll_pin, 917 + void *pin_priv, 918 + const struct dpll_device *dpll, 919 + void *dpll_priv, 920 + s32 phase_adjust, 921 + struct netlink_ext_ack *extack) 922 + { 923 + struct zl3073x_dpll *zldpll = dpll_priv; 924 + struct zl3073x_dev *zldev = zldpll->dev; 925 + struct zl3073x_dpll_pin *pin = pin_priv; 926 + int half_synth_cycle; 927 + u32 synth_freq; 928 + u8 out, synth; 929 + int rc; 930 + 931 + /* Get attached synth */ 932 + out = zl3073x_output_pin_out_get(pin->id); 933 + synth = zl3073x_out_synth_get(zldev, out); 934 + 935 + /* Get synth's frequency */ 936 + synth_freq = zl3073x_synth_freq_get(zldev, synth); 937 + 938 + /* Value in register is expressed in half synth clock cycles so 939 + * the given phase adjustment a multiple of half synth clock. 940 + */ 941 + half_synth_cycle = (int)div_u64(PSEC_PER_SEC, 2 * synth_freq); 942 + 943 + if ((phase_adjust % half_synth_cycle) != 0) { 944 + NL_SET_ERR_MSG_FMT(extack, 945 + "Phase adjustment value has to be multiple of %d", 946 + half_synth_cycle); 947 + return -EINVAL; 948 + } 949 + phase_adjust /= half_synth_cycle; 950 + 951 + /* The value in the register is stored as two's complement negation 952 + * of requested value. 953 + */ 954 + phase_adjust = -phase_adjust; 955 + 956 + guard(mutex)(&zldev->multiop_lock); 957 + 958 + /* Read output configuration */ 959 + rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 960 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 961 + if (rc) 962 + return rc; 963 + 964 + /* Write the requested value into the compensation register */ 965 + rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_PHASE_COMP, phase_adjust); 966 + if (rc) 967 + return rc; 968 + 969 + /* Update output configuration from mailbox */ 970 + return zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_WR, 971 + ZL_REG_OUTPUT_MB_MASK, BIT(out)); 972 + } 973 + 974 + static int 1381 975 zl3073x_dpll_output_pin_state_on_dpll_get(const struct dpll_pin *dpll_pin, 1382 976 void *pin_priv, 1383 977 const struct dpll_device *dpll, ··· 1576 954 return 0; 1577 955 } 1578 956 957 + static int 958 + zl3073x_dpll_phase_offset_monitor_get(const struct dpll_device *dpll, 959 + void *dpll_priv, 960 + enum dpll_feature_state *state, 961 + struct netlink_ext_ack *extack) 962 + { 963 + struct zl3073x_dpll *zldpll = dpll_priv; 964 + 965 + if (zldpll->phase_monitor) 966 + *state = DPLL_FEATURE_STATE_ENABLE; 967 + else 968 + *state = DPLL_FEATURE_STATE_DISABLE; 969 + 970 + return 0; 971 + } 972 + 973 + static int 974 + zl3073x_dpll_phase_offset_monitor_set(const struct dpll_device *dpll, 975 + void *dpll_priv, 976 + enum dpll_feature_state state, 977 + struct netlink_ext_ack *extack) 978 + { 979 + struct zl3073x_dpll *zldpll = dpll_priv; 980 + 981 + zldpll->phase_monitor = (state == DPLL_FEATURE_STATE_ENABLE); 982 + 983 + return 0; 984 + } 985 + 1579 986 static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = { 1580 987 .direction_get = zl3073x_dpll_pin_direction_get, 988 + .esync_get = zl3073x_dpll_input_pin_esync_get, 989 + .esync_set = zl3073x_dpll_input_pin_esync_set, 990 + .ffo_get = zl3073x_dpll_input_pin_ffo_get, 1581 991 .frequency_get = zl3073x_dpll_input_pin_frequency_get, 1582 992 .frequency_set = zl3073x_dpll_input_pin_frequency_set, 993 + .phase_offset_get = zl3073x_dpll_input_pin_phase_offset_get, 994 + .phase_adjust_get = zl3073x_dpll_input_pin_phase_adjust_get, 995 + .phase_adjust_set = zl3073x_dpll_input_pin_phase_adjust_set, 1583 996 .prio_get = zl3073x_dpll_input_pin_prio_get, 1584 997 .prio_set = zl3073x_dpll_input_pin_prio_set, 1585 998 .state_on_dpll_get = zl3073x_dpll_input_pin_state_on_dpll_get, ··· 1623 966 1624 967 static const struct dpll_pin_ops zl3073x_dpll_output_pin_ops = { 1625 968 .direction_get = zl3073x_dpll_pin_direction_get, 969 + .esync_get = zl3073x_dpll_output_pin_esync_get, 970 + .esync_set = zl3073x_dpll_output_pin_esync_set, 1626 971 .frequency_get = zl3073x_dpll_output_pin_frequency_get, 1627 972 .frequency_set = zl3073x_dpll_output_pin_frequency_set, 973 + .phase_adjust_get = zl3073x_dpll_output_pin_phase_adjust_get, 974 + .phase_adjust_set = zl3073x_dpll_output_pin_phase_adjust_set, 1628 975 .state_on_dpll_get = zl3073x_dpll_output_pin_state_on_dpll_get, 1629 976 }; 1630 977 1631 978 static const struct dpll_device_ops zl3073x_dpll_device_ops = { 1632 979 .lock_status_get = zl3073x_dpll_lock_status_get, 1633 980 .mode_get = zl3073x_dpll_mode_get, 981 + .phase_offset_monitor_get = zl3073x_dpll_phase_offset_monitor_get, 982 + .phase_offset_monitor_set = zl3073x_dpll_phase_offset_monitor_set, 1634 983 }; 1635 984 1636 985 /** ··· 1703 1040 if (IS_ERR(props)) 1704 1041 return PTR_ERR(props); 1705 1042 1706 - /* Save package label */ 1043 + /* Save package label & esync capability */ 1707 1044 strscpy(pin->label, props->package_label); 1045 + pin->esync_control = props->esync_control; 1708 1046 1709 1047 if (zl3073x_dpll_is_input_pin(pin)) { 1710 1048 rc = zl3073x_dpll_ref_prio_get(pin, &pin->prio); ··· 1990 1326 } 1991 1327 1992 1328 /** 1329 + * zl3073x_dpll_pin_phase_offset_check - check for pin phase offset change 1330 + * @pin: pin to check 1331 + * 1332 + * Check for the change of DPLL to connected pin phase offset change. 1333 + * 1334 + * Return: true on phase offset change, false otherwise 1335 + */ 1336 + static bool 1337 + zl3073x_dpll_pin_phase_offset_check(struct zl3073x_dpll_pin *pin) 1338 + { 1339 + struct zl3073x_dpll *zldpll = pin->dpll; 1340 + struct zl3073x_dev *zldev = zldpll->dev; 1341 + unsigned int reg; 1342 + s64 phase_offset; 1343 + u8 ref; 1344 + int rc; 1345 + 1346 + ref = zl3073x_input_pin_ref_get(pin->id); 1347 + 1348 + /* Select register to read phase offset value depending on pin and 1349 + * phase monitor state: 1350 + * 1) For connected pin use dpll_phase_err_data register 1351 + * 2) For other pins use appropriate ref_phase register if the phase 1352 + * monitor feature is enabled and reference monitor does not 1353 + * report signal errors for given input pin 1354 + */ 1355 + if (pin->pin_state == DPLL_PIN_STATE_CONNECTED) { 1356 + reg = ZL_REG_DPLL_PHASE_ERR_DATA(zldpll->id); 1357 + } else if (zldpll->phase_monitor) { 1358 + u8 status; 1359 + 1360 + /* Get reference monitor status */ 1361 + rc = zl3073x_read_u8(zldev, ZL_REG_REF_MON_STATUS(ref), 1362 + &status); 1363 + if (rc) { 1364 + dev_err(zldev->dev, 1365 + "Failed to read %s refmon status: %pe\n", 1366 + pin->label, ERR_PTR(rc)); 1367 + 1368 + return false; 1369 + } 1370 + 1371 + if (status != ZL_REF_MON_STATUS_OK) 1372 + return false; 1373 + 1374 + reg = ZL_REG_REF_PHASE(ref); 1375 + } else { 1376 + /* The pin is not connected or phase monitor disabled */ 1377 + return false; 1378 + } 1379 + 1380 + /* Read measured phase offset value */ 1381 + rc = zl3073x_read_u48(zldev, reg, &phase_offset); 1382 + if (rc) { 1383 + dev_err(zldev->dev, "Failed to read ref phase offset: %pe\n", 1384 + ERR_PTR(rc)); 1385 + 1386 + return false; 1387 + } 1388 + 1389 + /* Convert to ps */ 1390 + phase_offset = div_s64(sign_extend64(phase_offset, 47), 100); 1391 + 1392 + /* Compare with previous value */ 1393 + if (phase_offset != pin->phase_offset) { 1394 + dev_dbg(zldev->dev, "%s phase offset changed: %lld -> %lld\n", 1395 + pin->label, pin->phase_offset, phase_offset); 1396 + pin->phase_offset = phase_offset; 1397 + 1398 + return true; 1399 + } 1400 + 1401 + return false; 1402 + } 1403 + 1404 + /** 1405 + * zl3073x_dpll_pin_ffo_check - check for pin fractional frequency offset change 1406 + * @pin: pin to check 1407 + * 1408 + * Check for the given pin's fractional frequency change. 1409 + * 1410 + * Return: true on fractional frequency offset change, false otherwise 1411 + */ 1412 + static bool 1413 + zl3073x_dpll_pin_ffo_check(struct zl3073x_dpll_pin *pin) 1414 + { 1415 + struct zl3073x_dpll *zldpll = pin->dpll; 1416 + struct zl3073x_dev *zldev = zldpll->dev; 1417 + u8 ref, status; 1418 + s64 ffo; 1419 + int rc; 1420 + 1421 + /* Get reference monitor status */ 1422 + ref = zl3073x_input_pin_ref_get(pin->id); 1423 + rc = zl3073x_read_u8(zldev, ZL_REG_REF_MON_STATUS(ref), &status); 1424 + if (rc) { 1425 + dev_err(zldev->dev, "Failed to read %s refmon status: %pe\n", 1426 + pin->label, ERR_PTR(rc)); 1427 + 1428 + return false; 1429 + } 1430 + 1431 + /* Do not report ffo changes if the reference monitor report errors */ 1432 + if (status != ZL_REF_MON_STATUS_OK) 1433 + return false; 1434 + 1435 + /* Get the latest measured ref's ffo */ 1436 + ffo = zl3073x_ref_ffo_get(zldev, ref); 1437 + 1438 + /* Compare with previous value */ 1439 + if (pin->freq_offset != ffo) { 1440 + dev_dbg(zldev->dev, "%s freq offset changed: %lld -> %lld\n", 1441 + pin->label, pin->freq_offset, ffo); 1442 + pin->freq_offset = ffo; 1443 + 1444 + return true; 1445 + } 1446 + 1447 + return false; 1448 + } 1449 + 1450 + /** 1993 1451 * zl3073x_dpll_changes_check - check for changes and send notifications 1994 1452 * @zldpll: pointer to zl3073x_dpll structure 1995 1453 * ··· 2128 1342 struct device *dev = zldev->dev; 2129 1343 struct zl3073x_dpll_pin *pin; 2130 1344 int rc; 1345 + 1346 + zldpll->check_count++; 2131 1347 2132 1348 /* Get current lock status for the DPLL */ 2133 1349 rc = zl3073x_dpll_lock_status_get(zldpll->dpll_dev, zldpll, ··· 2153 1365 zldpll->refsel_mode != ZL_DPLL_MODE_REFSEL_MODE_REFLOCK) 2154 1366 return; 2155 1367 1368 + /* Update phase offset latch registers for this DPLL if the phase 1369 + * offset monitor feature is enabled. 1370 + */ 1371 + if (zldpll->phase_monitor) { 1372 + rc = zl3073x_ref_phase_offsets_update(zldev, zldpll->id); 1373 + if (rc) { 1374 + dev_err(zldev->dev, 1375 + "Failed to update phase offsets: %pe\n", 1376 + ERR_PTR(rc)); 1377 + return; 1378 + } 1379 + } 1380 + 2156 1381 list_for_each_entry(pin, &zldpll->pins, list) { 2157 1382 enum dpll_pin_state state; 1383 + bool pin_changed = false; 2158 1384 2159 1385 /* Output pins change checks are not necessary because output 2160 1386 * states are constant. ··· 2188 1386 dev_dbg(dev, "%s state changed: %u->%u\n", pin->label, 2189 1387 pin->pin_state, state); 2190 1388 pin->pin_state = state; 2191 - dpll_pin_change_ntf(pin->dpll_pin); 1389 + pin_changed = true; 2192 1390 } 1391 + 1392 + /* Check for phase offset and ffo change once per second */ 1393 + if (zldpll->check_count % 2 == 0) { 1394 + if (zl3073x_dpll_pin_phase_offset_check(pin)) 1395 + pin_changed = true; 1396 + 1397 + if (zl3073x_dpll_pin_ffo_check(pin)) 1398 + pin_changed = true; 1399 + } 1400 + 1401 + if (pin_changed) 1402 + dpll_pin_change_ntf(pin->dpll_pin); 2193 1403 } 2194 1404 } 2195 1405
+4
drivers/dpll/zl3073x/dpll.h
··· 15 15 * @id: DPLL index 16 16 * @refsel_mode: reference selection mode 17 17 * @forced_ref: selected reference in forced reference lock mode 18 + * @check_count: periodic check counter 19 + * @phase_monitor: is phase offset monitor enabled 18 20 * @dpll_dev: pointer to registered DPLL device 19 21 * @lock_status: last saved DPLL lock status 20 22 * @pins: list of pins ··· 27 25 u8 id; 28 26 u8 refsel_mode; 29 27 u8 forced_ref; 28 + u8 check_count; 29 + bool phase_monitor; 30 30 struct dpll_device *dpll_dev; 31 31 enum dpll_lock_status lock_status; 32 32 struct list_head pins;
+55
drivers/dpll/zl3073x/regs.h
··· 94 94 #define ZL_DPLL_REFSEL_STATUS_STATE GENMASK(6, 4) 95 95 #define ZL_DPLL_REFSEL_STATUS_STATE_LOCK 4 96 96 97 + #define ZL_REG_REF_FREQ(_idx) \ 98 + ZL_REG_IDX(_idx, 2, 0x44, 4, ZL3073X_NUM_REFS, 4) 99 + 100 + /********************** 101 + * Register Page 4, Ref 102 + **********************/ 103 + 104 + #define ZL_REG_REF_PHASE_ERR_READ_RQST ZL_REG(4, 0x0f, 1) 105 + #define ZL_REF_PHASE_ERR_READ_RQST_RD BIT(0) 106 + 107 + #define ZL_REG_REF_FREQ_MEAS_CTRL ZL_REG(4, 0x1c, 1) 108 + #define ZL_REF_FREQ_MEAS_CTRL GENMASK(1, 0) 109 + #define ZL_REF_FREQ_MEAS_CTRL_REF_FREQ 1 110 + #define ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF 2 111 + #define ZL_REF_FREQ_MEAS_CTRL_DPLL_FREQ_OFF 3 112 + 113 + #define ZL_REG_REF_FREQ_MEAS_MASK_3_0 ZL_REG(4, 0x1d, 1) 114 + #define ZL_REF_FREQ_MEAS_MASK_3_0(_ref) BIT(_ref) 115 + 116 + #define ZL_REG_REF_FREQ_MEAS_MASK_4 ZL_REG(4, 0x1e, 1) 117 + #define ZL_REF_FREQ_MEAS_MASK_4(_ref) BIT((_ref) - 8) 118 + 119 + #define ZL_REG_DPLL_MEAS_REF_FREQ_CTRL ZL_REG(4, 0x1f, 1) 120 + #define ZL_DPLL_MEAS_REF_FREQ_CTRL_EN BIT(0) 121 + #define ZL_DPLL_MEAS_REF_FREQ_CTRL_IDX GENMASK(6, 4) 122 + 123 + #define ZL_REG_REF_PHASE(_idx) \ 124 + ZL_REG_IDX(_idx, 4, 0x20, 6, ZL3073X_NUM_REFS, 6) 125 + 97 126 /*********************** 98 127 * Register Page 5, DPLL 99 128 ***********************/ ··· 136 107 #define ZL_DPLL_MODE_REFSEL_MODE_AUTO 3 137 108 #define ZL_DPLL_MODE_REFSEL_MODE_NCO 4 138 109 #define ZL_DPLL_MODE_REFSEL_REF GENMASK(7, 4) 110 + 111 + #define ZL_REG_DPLL_MEAS_CTRL ZL_REG(5, 0x50, 1) 112 + #define ZL_DPLL_MEAS_CTRL_EN BIT(0) 113 + #define ZL_DPLL_MEAS_CTRL_AVG_FACTOR GENMASK(7, 4) 114 + 115 + #define ZL_REG_DPLL_MEAS_IDX ZL_REG(5, 0x51, 1) 116 + #define ZL_DPLL_MEAS_IDX GENMASK(2, 0) 117 + 118 + #define ZL_REG_DPLL_PHASE_ERR_READ_MASK ZL_REG(5, 0x54, 1) 119 + 120 + #define ZL_REG_DPLL_PHASE_ERR_DATA(_idx) \ 121 + ZL_REG_IDX(_idx, 5, 0x55, 6, ZL3073X_MAX_CHANNELS, 6) 139 122 140 123 /*********************************** 141 124 * Register Page 9, Synth and Output ··· 186 145 #define ZL_REG_REF_CONFIG ZL_REG(10, 0x0d, 1) 187 146 #define ZL_REF_CONFIG_ENABLE BIT(0) 188 147 #define ZL_REF_CONFIG_DIFF_EN BIT(2) 148 + 149 + #define ZL_REG_REF_PHASE_OFFSET_COMP ZL_REG(10, 0x28, 6) 150 + 151 + #define ZL_REG_REF_SYNC_CTRL ZL_REG(10, 0x2e, 1) 152 + #define ZL_REF_SYNC_CTRL_MODE GENMASK(2, 0) 153 + #define ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR_OFF 0 154 + #define ZL_REF_SYNC_CTRL_MODE_50_50_ESYNC_25_75 2 155 + 156 + #define ZL_REG_REF_ESYNC_DIV ZL_REG(10, 0x30, 4) 157 + #define ZL_REF_ESYNC_DIV_1HZ 0 189 158 190 159 /******************************** 191 160 * Register Page 12, DPLL Mailbox ··· 239 188 #define ZL_OUTPUT_MB_SEM_RD BIT(1) 240 189 241 190 #define ZL_REG_OUTPUT_MODE ZL_REG(14, 0x05, 1) 191 + #define ZL_OUTPUT_MODE_CLOCK_TYPE GENMASK(2, 0) 192 + #define ZL_OUTPUT_MODE_CLOCK_TYPE_NORMAL 0 193 + #define ZL_OUTPUT_MODE_CLOCK_TYPE_ESYNC 1 242 194 #define ZL_OUTPUT_MODE_SIGNAL_FORMAT GENMASK(7, 4) 243 195 #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED 0 244 196 #define ZL_OUTPUT_MODE_SIGNAL_FORMAT_LVDS 1 ··· 258 204 #define ZL_REG_OUTPUT_WIDTH ZL_REG(14, 0x10, 4) 259 205 #define ZL_REG_OUTPUT_ESYNC_PERIOD ZL_REG(14, 0x14, 4) 260 206 #define ZL_REG_OUTPUT_ESYNC_WIDTH ZL_REG(14, 0x18, 4) 207 + #define ZL_REG_OUTPUT_PHASE_COMP ZL_REG(14, 0x20, 4) 261 208 262 209 #endif /* _ZL3073X_REGS_H */