linux/drivers/clk/clk-lmk04832.c

// SPDX-License-Identifier: GPL-2.0
/*
 * LMK04832 Ultra Low-Noise JESD204B Compliant Clock Jitter Cleaner
 * Pin compatible with the LMK0482x family
 *
 * Datasheet: https://www.ti.com/lit/ds/symlink/lmk04832.pdf
 *
 * Copyright (c) 2020, Xiphos Systems Corp.
 *
 */

#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/gcd.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>

/* 0x000 - 0x00d System Functions */
#define LMK04832_REG_RST3W
#define LMK04832_BIT_RESET
#define LMK04832_BIT_SPI_3WIRE_DIS
#define LMK04832_REG_POWERDOWN
#define LMK04832_REG_ID_DEV_TYPE
#define LMK04832_REG_ID_PROD_MSB
#define LMK04832_REG_ID_PROD_LSB
#define LMK04832_REG_ID_MASKREV
#define LMK04832_REG_ID_VNDR_MSB
#define LMK04832_REG_ID_VNDR_LSB

/* 0x100 - 0x137 Device Clock and SYSREF Clock Output Control */
#define LMK04832_REG_CLKOUT_CTRL0(ch)
#define LMK04832_BIT_DCLK_DIV_LSB
#define LMK04832_REG_CLKOUT_CTRL1(ch)
#define LMK04832_BIT_DCLKX_Y_DDLY_LSB
#define LMK04832_REG_CLKOUT_CTRL2(ch)
#define LMK04832_BIT_CLKOUTX_Y_PD
#define LMK04832_BIT_DCLKX_Y_DDLY_PD
#define LMK04832_BIT_DCLKX_Y_DDLY_MSB
#define LMK04832_BIT_DCLK_DIV_MSB
#define LMK04832_REG_CLKOUT_SRC_MUX(ch)
#define LMK04832_BIT_CLKOUT_SRC_MUX
#define LMK04832_REG_CLKOUT_CTRL3(ch)
#define LMK04832_BIT_DCLKX_Y_PD
#define LMK04832_BIT_DCLKX_Y_DCC
#define LMK04832_BIT_DCLKX_Y_HS
#define LMK04832_REG_CLKOUT_CTRL4(ch)
#define LMK04832_BIT_SCLK_PD
#define LMK04832_BIT_SCLKX_Y_DIS_MODE
#define LMK04832_REG_SCLKX_Y_ADLY(ch)
#define LMK04832_REG_SCLKX_Y_DDLY(ch)
#define LMK04832_BIT_SCLKX_Y_DDLY
#define LMK04832_REG_CLKOUT_FMT(ch)
#define LMK04832_BIT_CLKOUT_FMT(ch)
#define LMK04832_VAL_CLKOUT_FMT_POWERDOWN
#define LMK04832_VAL_CLKOUT_FMT_LVDS
#define LMK04832_VAL_CLKOUT_FMT_HSDS6
#define LMK04832_VAL_CLKOUT_FMT_HSDS8
#define LMK04832_VAL_CLKOUT_FMT_LVPECL1600
#define LMK04832_VAL_CLKOUT_FMT_LVPECL2000
#define LMK04832_VAL_CLKOUT_FMT_LCPECL
#define LMK04832_VAL_CLKOUT_FMT_CML16
#define LMK04832_VAL_CLKOUT_FMT_CML24
#define LMK04832_VAL_CLKOUT_FMT_CML32
#define LMK04832_VAL_CLKOUT_FMT_CMOS_OFF_INV
#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_OFF
#define LMK04832_VAL_CLKOUT_FMT_CMOS_INV_INV
#define LMK04832_VAL_CLKOUT_FMT_CMOS_INV_NOR
#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_INV
#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_NOR

/* 0x138 - 0x145 SYSREF, SYNC, and Device Config */
#define LMK04832_REG_VCO_OSCOUT
#define LMK04832_BIT_VCO_MUX
#define LMK04832_VAL_VCO_MUX_VCO0
#define LMK04832_VAL_VCO_MUX_VCO1
#define LMK04832_VAL_VCO_MUX_EXT
#define LMK04832_REG_SYSREF_OUT
#define LMK04832_BIT_SYSREF_REQ_EN
#define LMK04832_BIT_SYSREF_MUX
#define LMK04832_VAL_SYSREF_MUX_NORMAL_SYNC
#define LMK04832_VAL_SYSREF_MUX_RECLK
#define LMK04832_VAL_SYSREF_MUX_PULSER
#define LMK04832_VAL_SYSREF_MUX_CONTINUOUS
#define LMK04832_REG_SYSREF_DIV_MSB
#define LMK04832_BIT_SYSREF_DIV_MSB
#define LMK04832_REG_SYSREF_DIV_LSB
#define LMK04832_REG_SYSREF_DDLY_MSB
#define LMK04832_BIT_SYSREF_DDLY_MSB
#define LMK04832_REG_SYSREF_DDLY_LSB
#define LMK04832_REG_SYSREF_PULSE_CNT
#define LMK04832_REG_FB_CTRL
#define LMK04832_BIT_PLL2_RCLK_MUX
#define LMK04832_VAL_PLL2_RCLK_MUX_OSCIN
#define LMK04832_VAL_PLL2_RCLK_MUX_CLKIN
#define LMK04832_BIT_PLL2_NCLK_MUX
#define LMK04832_VAL_PLL2_NCLK_MUX_PLL2_P
#define LMK04832_VAL_PLL2_NCLK_MUX_FB_MUX
#define LMK04832_BIT_FB_MUX_EN
#define LMK04832_REG_MAIN_PD
#define LMK04832_BIT_PLL1_PD
#define LMK04832_BIT_VCO_LDO_PD
#define LMK04832_BIT_VCO_PD
#define LMK04832_BIT_OSCIN_PD
#define LMK04832_BIT_SYSREF_GBL_PD
#define LMK04832_BIT_SYSREF_PD
#define LMK04832_BIT_SYSREF_DDLY_PD
#define LMK04832_BIT_SYSREF_PLSR_PD
#define LMK04832_REG_SYNC
#define LMK04832_BIT_SYNC_CLR
#define LMK04832_BIT_SYNC_1SHOT_EN
#define LMK04832_BIT_SYNC_POL
#define LMK04832_BIT_SYNC_EN
#define LMK04832_BIT_SYNC_MODE
#define LMK04832_VAL_SYNC_MODE_OFF
#define LMK04832_VAL_SYNC_MODE_ON
#define LMK04832_VAL_SYNC_MODE_PULSER_PIN
#define LMK04832_VAL_SYNC_MODE_PULSER_SPI
#define LMK04832_REG_SYNC_DIS

/* 0x146 - 0x14a CLKin Control */
#define LMK04832_REG_CLKIN_SEL0
#define LMK04832_REG_CLKIN_SEL1
#define LMK04832_REG_CLKIN_RST
#define LMK04832_BIT_SDIO_RDBK_TYPE
#define LMK04832_BIT_CLKIN_SEL_MUX
#define LMK04832_VAL_CLKIN_SEL_MUX_SPI_RDBK
#define LMK04832_BIT_CLKIN_SEL_TYPE
#define LMK04832_VAL_CLKIN_SEL_TYPE_OUT

/* 0x14b - 0x152 Holdover */

/* 0x153 - 0x15f PLL1 Configuration */
#define LMK04832_REG_PLL1_LD
#define LMK04832_BIT_PLL1_LD_MUX
#define LMK04832_VAL_PLL1_LD_MUX_SPI_RDBK
#define LMK04832_BIT_PLL1_LD_TYPE
#define LMK04832_VAL_PLL1_LD_TYPE_OUT_PP

/* 0x160 - 0x16e PLL2 Configuration */
#define LMK04832_REG_PLL2_R_MSB
#define LMK04832_BIT_PLL2_R_MSB
#define LMK04832_REG_PLL2_R_LSB
#define LMK04832_REG_PLL2_MISC
#define LMK04832_BIT_PLL2_MISC_P
#define LMK04832_BIT_PLL2_MISC_REF_2X_EN
#define LMK04832_REG_PLL2_N_CAL_0
#define LMK04832_BIT_PLL2_N_CAL_0
#define LMK04832_REG_PLL2_N_CAL_1
#define LMK04832_REG_PLL2_N_CAL_2
#define LMK04832_REG_PLL2_N_0
#define LMK04832_BIT_PLL2_N_0
#define LMK04832_REG_PLL2_N_1
#define LMK04832_REG_PLL2_N_2
#define LMK04832_REG_PLL2_DLD_CNT_MSB
#define LMK04832_REG_PLL2_DLD_CNT_LSB
#define LMK04832_REG_PLL2_LD
#define LMK04832_BIT_PLL2_LD_MUX
#define LMK04832_VAL_PLL2_LD_MUX_PLL2_DLD
#define LMK04832_BIT_PLL2_LD_TYPE
#define LMK04832_VAL_PLL2_LD_TYPE_OUT_PP

/* 0x16F - 0x555 Misc Registers */
#define LMK04832_REG_PLL2_PD
#define LMK04832_BIT_PLL2_PRE_PD
#define LMK04832_BIT_PLL2_PD
#define LMK04832_REG_PLL1R_RST
#define LMK04832_REG_CLR_PLL_LOST
#define LMK04832_REG_RB_PLL_LD
#define LMK04832_REG_RB_CLK_DAC_VAL_MSB
#define LMK04832_REG_RB_DAC_VAL_LSB
#define LMK04832_REG_RB_HOLDOVER
#define LMK04832_REG_SPI_LOCK

enum lmk04832_device_types {};

/**
 * struct lmk04832_device_info - Holds static device information that is
 *                               specific to the chip revision
 *
 * @pid:          Product Identifier
 * @maskrev:      IC version identifier
 * @num_channels: Number of available output channels (clkout count)
 * @vco0_range:   {min, max} of the VCO0 operating range (in MHz)
 * @vco1_range:   {min, max} of the VCO1 operating range (in MHz)
 */
struct lmk04832_device_info {};

static const struct lmk04832_device_info lmk04832_device_info[] =;

enum lmk04832_rdbk_type {};

struct lmk_dclk {};

struct lmk_clkout {};

/**
 * struct lmk04832 - The LMK04832 device structure
 *
 * @dev: reference to a struct device, linked to the spi_device
 * @regmap: struct regmap instance use to access the chip
 * @sync_mode: operational mode for SYNC signal
 * @sysref_mux: select SYSREF source
 * @sysref_pulse_cnt: number of SYSREF pulses generated while not in continuous
 *                    mode.
 * @sysref_ddly: SYSREF digital delay value
 * @oscin: PLL2 input clock
 * @vco: reference to the internal VCO clock
 * @sclk: reference to the internal sysref clock (SCLK)
 * @vco_rate: user provided VCO rate
 * @reset_gpio: reference to the reset GPIO
 * @dclk: list of internal device clock references.
 *        Each pair of clkout clocks share a single device clock (DCLKX_Y)
 * @clkout: list of output clock references
 * @clk_data: holds clkout related data like clk_hw* and number of clocks
 */
struct lmk04832 {};

static bool lmk04832_regmap_rd_regs(struct device *dev, unsigned int reg)
{}

static bool lmk04832_regmap_wr_regs(struct device *dev, unsigned int reg)
{}

static const struct regmap_config regmap_config =;

static int lmk04832_vco_is_enabled(struct clk_hw *hw)
{}

static int lmk04832_vco_prepare(struct clk_hw *hw)
{}

static void lmk04832_vco_unprepare(struct clk_hw *hw)
{}

static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw,
					      unsigned long prate)
{}

/**
 * lmk04832_check_vco_ranges - Check requested VCO frequency against VCO ranges
 *
 * @lmk:   Reference to the lmk device
 * @rate:  Desired output rate for the VCO
 *
 * The LMK04832 has 2 internal VCO, each with independent operating ranges.
 * Use the device_info structure to determine which VCO to use based on rate.
 *
 * Returns: VCO_MUX value or negative errno.
 */
static int lmk04832_check_vco_ranges(struct lmk04832 *lmk, unsigned long rate)
{}

/**
 * lmk04832_calc_pll2_params - Get PLL2 parameters used to set the VCO frequency
 *
 * @prate: parent rate to the PLL2, usually OSCin
 * @rate:  Desired output rate for the VCO
 * @n:     reference to PLL2_N
 * @p:     reference to PLL2_P
 * @r:     reference to PLL2_R
 *
 * This functions assumes LMK04832_BIT_PLL2_MISC_REF_2X_EN is set since it is
 * recommended in the datasheet because a higher phase detector frequencies
 * makes the design of wider loop bandwidth filters possible.
 *
 * the VCO rate can be calculated using the following expression:
 *
 *	VCO = OSCin * 2 * PLL2_N * PLL2_P / PLL2_R
 *
 * Returns: vco rate or negative errno.
 */
static long lmk04832_calc_pll2_params(unsigned long prate, unsigned long rate,
				      unsigned int *n, unsigned int *p,
				      unsigned int *r)
{}

static long lmk04832_vco_round_rate(struct clk_hw *hw, unsigned long rate,
				    unsigned long *prate)
{}

static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate,
				 unsigned long prate)
{}

static const struct clk_ops lmk04832_vco_ops =;

/*
 * lmk04832_register_vco - Initialize the internal VCO and clock distribution
 *                         path in PLL2 single loop mode.
 */
static int lmk04832_register_vco(struct lmk04832 *lmk)
{}

static int lmk04832_clkout_set_ddly(struct lmk04832 *lmk, int id)
{}

/** lmk04832_sclk_sync - Establish deterministic phase relationship between sclk
 *                       and dclk
 *
 * @lmk: Reference to the lmk device
 *
 * The synchronization sequence:
 * - in the datasheet https://www.ti.com/lit/ds/symlink/lmk04832.pdf, p.31
 *   (8.3.3.1 How to enable SYSREF)
 * - Ti forum: https://e2e.ti.com/support/clock-and-timing/f/48/t/970972
 *
 * Returns 0 or negative errno.
 */
static int lmk04832_sclk_sync_sequence(struct lmk04832 *lmk)
{}

static int lmk04832_sclk_is_enabled(struct clk_hw *hw)
{}

static int lmk04832_sclk_prepare(struct clk_hw *hw)
{}

static void lmk04832_sclk_unprepare(struct clk_hw *hw)
{}

static unsigned long lmk04832_sclk_recalc_rate(struct clk_hw *hw,
					       unsigned long prate)
{}

static long lmk04832_sclk_round_rate(struct clk_hw *hw, unsigned long rate,
				     unsigned long *prate)
{}

static int lmk04832_sclk_set_rate(struct clk_hw *hw, unsigned long rate,
				  unsigned long prate)
{}

static const struct clk_ops lmk04832_sclk_ops =;

static int lmk04832_register_sclk(struct lmk04832 *lmk)
{}

static int lmk04832_dclk_is_enabled(struct clk_hw *hw)
{}

static int lmk04832_dclk_prepare(struct clk_hw *hw)
{}

static void lmk04832_dclk_unprepare(struct clk_hw *hw)
{}

static unsigned long lmk04832_dclk_recalc_rate(struct clk_hw *hw,
					       unsigned long prate)
{}

static long lmk04832_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
				     unsigned long *prate)
{}

static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
				  unsigned long prate)
{}

static const struct clk_ops lmk04832_dclk_ops =;

static int lmk04832_clkout_is_enabled(struct clk_hw *hw)
{}

static int lmk04832_clkout_prepare(struct clk_hw *hw)
{}

static void lmk04832_clkout_unprepare(struct clk_hw *hw)
{}

static int lmk04832_clkout_set_parent(struct clk_hw *hw, uint8_t index)
{}

static uint8_t lmk04832_clkout_get_parent(struct clk_hw *hw)
{}

static const struct clk_ops lmk04832_clkout_ops =;

static int lmk04832_register_clkout(struct lmk04832 *lmk, const int num)
{}

static int lmk04832_set_spi_rdbk(const struct lmk04832 *lmk, const int rdbk_pin)
{}

static int lmk04832_probe(struct spi_device *spi)
{}

static void lmk04832_remove(struct spi_device *spi)
{}

static const struct spi_device_id lmk04832_id[] =;
MODULE_DEVICE_TABLE(spi, lmk04832_id);

static const struct of_device_id lmk04832_of_id[] =;
MODULE_DEVICE_TABLE(of, lmk04832_of_id);

static struct spi_driver lmk04832_driver =;
module_spi_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();