diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt b/Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt index 5ad58b2cc8ef8d..c767c4213d2e95 100644 --- a/Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt +++ b/Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt @@ -28,6 +28,8 @@ Optional properties: SYNCOUTB signal, default is CMOS. - adi,sysref-coupling-dc-enable: Enables SYSREF signal DC coupling, default is AC coupling. + - adi,sysref-error-window: Amount of jitter allowed on the sysref + input pins. Unit is in DAC clock cycles. - reset-gpio: a GPIO spec for the reset pin. - txen0-gpio: a GPIO spec for the TXEN0 pin. - txen1-gpio: a GPIO spec for the TXEN1 pin. diff --git a/drivers/iio/frequency/ad9172.c b/drivers/iio/frequency/ad9172.c index 106196cccfbf94..8f867a80bfd246 100644 --- a/drivers/iio/frequency/ad9172.c +++ b/drivers/iio/frequency/ad9172.c @@ -67,6 +67,7 @@ struct ad9172_state { u32 clock_output_config; u32 scrambling; u32 sysref_mode; + u32 sysref_err_win; bool pll_bypass; signal_type_t syncoutb_type; signal_coupling_t sysref_coupling; @@ -928,6 +929,9 @@ static int ad9172_parse_dt(struct spi_device *spi, struct ad9172_state *st) if (of_property_read_u32(np, "adi,sysref-mode", &st->sysref_mode)) st->sysref_mode = SYSREF_CONT; + st->sysref_err_win = 0; + of_property_read_u32(np, "adi,sysref-error-window", &st->sysref_err_win); + /*Logic lane configuration*/ ret = of_property_read_u8_array(np,"adi,logic-lanes-mapping", st->logic_lanes, sizeof(st->logic_lanes)); @@ -1001,6 +1005,14 @@ static int ad9172_jesd204_link_enable(struct jesd204_dev *jdev, ad917x_jesd_set_sysref_enable(&st->dac_h, !!st->jesd_subclass); + if (lnk->subclass == JESD204_SUBCLASS_1) { + ret = ad917x_jesd_oneshot_sync(&st->dac_h, st->sysref_err_win); + if (ret != 0) { + dev_err(dev, "Failed to set oneshot sync (%d)\n", ret); + return ret; + } + } + /*Enable Link*/ ret = ad917x_jesd_enable_link(&st->dac_h, JESD_LINK_ALL, reason == JESD204_STATE_OP_REASON_INIT); @@ -1021,6 +1033,7 @@ static int ad9172_jesd204_link_running(struct jesd204_dev *jdev, struct ad9172_state *st = priv->st; unsigned long lane_rate_khz; int ret; + bool done; if (reason != JESD204_STATE_OP_REASON_INIT) return JESD204_STATE_CHANGE_DONE; @@ -1040,6 +1053,19 @@ static int ad9172_jesd204_link_running(struct jesd204_dev *jdev, return ret; } + if (lnk->subclass == JESD204_SUBCLASS_1) { + ret = ad917x_jesd_get_sync_rotation_done(&st->dac_h, &done); + if (ret) { + dev_err(dev, "Failed sync rotation read (%d)\n", ret); + return ret; + } + + if (!done) { + dev_err(dev, "JESD204 sync rotation check failed\n"); + return JESD204_STATE_CHANGE_ERROR; + } + } + return JESD204_STATE_CHANGE_DONE; } diff --git a/drivers/iio/frequency/ad917x/AD917x.h b/drivers/iio/frequency/ad917x/AD917x.h index adabca4e3cd68d..10e94d426bed6f 100644 --- a/drivers/iio/frequency/ad917x/AD917x.h +++ b/drivers/iio/frequency/ad917x/AD917x.h @@ -473,6 +473,27 @@ int ad917x_jesd_set_sysref_enable(ad917x_handle_t *h, uint8_t en); */ int ad917x_jesd_get_sysref_enable(ad917x_handle_t *h, uint8_t *en); +/** + * \brief Configure SYSREF for oneshot sync + * + * Configure SYSREF oneshot sequence to align LMFC on next SYSREF + * rising edge signal. + * + * \param h Pointer to the AD917X device reference handle. + * \param err_window Error window in DAC clock cycles for SYSREF + * jitter. + */ +int ad917x_jesd_oneshot_sync(ad917x_handle_t *h, u8 err_window); + +/** + * \brief Check if sync rotation has happened + * + * Checks if SYSREF to LMFC synchronization logic has completed. + * + * \param h Pointer to the AD917X device reference handle. + * \param *done Return value indicating if rotation has completed. + */ +int ad917x_jesd_get_sync_rotation_done(ad917x_handle_t *h, bool *done); /** * \brief Set the LMFC Delay and Variance for the JESD Links diff --git a/drivers/iio/frequency/ad917x/ad917x_jesd_api.c b/drivers/iio/frequency/ad917x/ad917x_jesd_api.c index d2b902bf5b2509..edef9208397867 100644 --- a/drivers/iio/frequency/ad917x/ad917x_jesd_api.c +++ b/drivers/iio/frequency/ad917x/ad917x_jesd_api.c @@ -243,6 +243,52 @@ int ad917x_jesd_get_cfg_param(ad917x_handle_t *h, return API_ERROR_OK; } +int ad917x_jesd_oneshot_sync(ad917x_handle_t *h, u8 err_window) +{ + int err; + u8 mode; + + if (h == NULL) + return API_ERROR_INVALID_HANDLE_PTR; + + err = ad917x_register_write(h, AD917X_SYSREF_ERR_WINDOW_REG, + AD917X_SYSREF_ERR_WIN(err_window)); + if (err != API_ERROR_OK) + return err; + + err = ad917x_register_read(h, AD917X_SYSREF_MODE_REG, &mode); + if (err != API_ERROR_OK) + return err; + + if (mode & AD917X_SYSREF_MODE_ONESHOT) { + err = ad917x_register_write(h, AD917X_SYSREF_MODE_REG, + mode & ~AD917X_SYSREF_MODE_ONESHOT); + if (err != API_ERROR_OK) + return err; + } + + err = ad917x_register_write(h, AD917X_SYSREF_MODE_REG, + mode | AD917X_SYSREF_MODE_ONESHOT); + return err; +} + +int ad917x_jesd_get_sync_rotation_done(ad917x_handle_t *h, bool *done) +{ + int err; + u8 mode; + + if (h == NULL) + return API_ERROR_INVALID_HANDLE_PTR; + + err = ad917x_register_read(h, AD917X_SYSREF_MODE_REG, &mode); + if (err != API_ERROR_OK) + return err; + + *done = (mode & AD917X_SYNC_ROTATION_DONE); + + return API_ERROR_OK; +} + int ad917x_jesd_set_sysref_enable(ad917x_handle_t *h, uint8_t en) { int err; diff --git a/drivers/iio/frequency/ad917x/ad917x_reg.h b/drivers/iio/frequency/ad917x/ad917x_reg.h index 78b0dc50e9d4f4..7b4711ad2d228a 100644 --- a/drivers/iio/frequency/ad917x/ad917x_reg.h +++ b/drivers/iio/frequency/ad917x/ad917x_reg.h @@ -47,6 +47,14 @@ int ad917x_register_read_block(ad917x_handle_t *h, #define AD917X_MAINDAC_PAGE_0 BIT(6) #define AD917X_MAINDAC_PAGE_1 BIT(7) +#define AD917X_SYSREF_ERR_WINDOW_REG 0x039 +#define AD917X_SYSREF_ERR_WIN(x) (((x) & 0x7F) << 0) + +#define AD917X_SYSREF_MODE_REG 0x03A +#define AD917X_SYNC_ROTATION_DONE BIT(4) +#define AD917X_SYSREF_MODE_ONESHOT BIT(1) +#define AD917X_SYSREF_MODE_CONTINUOUS BIT(0) + #define AD917X_SYSREF_ROTATION_REG 0x03B #define AD917X_SYNC_LOGIC_EN BIT(7) #define AD917X_SYNC_RSV_EN BIT(6)