13bc61cfdSLiam Beguin // SPDX-License-Identifier: GPL-2.0
23bc61cfdSLiam Beguin /*
33bc61cfdSLiam Beguin * LMK04832 Ultra Low-Noise JESD204B Compliant Clock Jitter Cleaner
43bc61cfdSLiam Beguin * Pin compatible with the LMK0482x family
53bc61cfdSLiam Beguin *
63bc61cfdSLiam Beguin * Datasheet: https://www.ti.com/lit/ds/symlink/lmk04832.pdf
73bc61cfdSLiam Beguin *
83bc61cfdSLiam Beguin * Copyright (c) 2020, Xiphos Systems Corp.
93bc61cfdSLiam Beguin *
103bc61cfdSLiam Beguin */
113bc61cfdSLiam Beguin
123bc61cfdSLiam Beguin #include <linux/bitfield.h>
133bc61cfdSLiam Beguin #include <linux/clk.h>
143bc61cfdSLiam Beguin #include <linux/clk-provider.h>
153bc61cfdSLiam Beguin #include <linux/device.h>
163bc61cfdSLiam Beguin #include <linux/gcd.h>
173bc61cfdSLiam Beguin #include <linux/gpio/consumer.h>
183bc61cfdSLiam Beguin #include <linux/module.h>
193bc61cfdSLiam Beguin #include <linux/regmap.h>
203bc61cfdSLiam Beguin #include <linux/spi/spi.h>
213bc61cfdSLiam Beguin
223bc61cfdSLiam Beguin /* 0x000 - 0x00d System Functions */
233bc61cfdSLiam Beguin #define LMK04832_REG_RST3W 0x000
243bc61cfdSLiam Beguin #define LMK04832_BIT_RESET BIT(7)
253bc61cfdSLiam Beguin #define LMK04832_BIT_SPI_3WIRE_DIS BIT(4)
263bc61cfdSLiam Beguin #define LMK04832_REG_POWERDOWN 0x002
273bc61cfdSLiam Beguin #define LMK04832_REG_ID_DEV_TYPE 0x003
283bc61cfdSLiam Beguin #define LMK04832_REG_ID_PROD_MSB 0x004
293bc61cfdSLiam Beguin #define LMK04832_REG_ID_PROD_LSB 0x005
303bc61cfdSLiam Beguin #define LMK04832_REG_ID_MASKREV 0x006
313bc61cfdSLiam Beguin #define LMK04832_REG_ID_VNDR_MSB 0x00c
323bc61cfdSLiam Beguin #define LMK04832_REG_ID_VNDR_LSB 0x00d
333bc61cfdSLiam Beguin
343bc61cfdSLiam Beguin /* 0x100 - 0x137 Device Clock and SYSREF Clock Output Control */
353bc61cfdSLiam Beguin #define LMK04832_REG_CLKOUT_CTRL0(ch) (0x100 + (ch >> 1) * 8)
363bc61cfdSLiam Beguin #define LMK04832_BIT_DCLK_DIV_LSB GENMASK(7, 0)
373bc61cfdSLiam Beguin #define LMK04832_REG_CLKOUT_CTRL1(ch) (0x101 + (ch >> 1) * 8)
386181baa1SLiam Beguin #define LMK04832_BIT_DCLKX_Y_DDLY_LSB GENMASK(7, 0)
393bc61cfdSLiam Beguin #define LMK04832_REG_CLKOUT_CTRL2(ch) (0x102 + (ch >> 1) * 8)
403bc61cfdSLiam Beguin #define LMK04832_BIT_CLKOUTX_Y_PD BIT(7)
416181baa1SLiam Beguin #define LMK04832_BIT_DCLKX_Y_DDLY_PD BIT(4)
426181baa1SLiam Beguin #define LMK04832_BIT_DCLKX_Y_DDLY_MSB GENMASK(3, 2)
433bc61cfdSLiam Beguin #define LMK04832_BIT_DCLK_DIV_MSB GENMASK(1, 0)
443bc61cfdSLiam Beguin #define LMK04832_REG_CLKOUT_SRC_MUX(ch) (0x103 + (ch % 2) + (ch >> 1) * 8)
453bc61cfdSLiam Beguin #define LMK04832_BIT_CLKOUT_SRC_MUX BIT(5)
463bc61cfdSLiam Beguin #define LMK04832_REG_CLKOUT_CTRL3(ch) (0x103 + (ch >> 1) * 8)
473bc61cfdSLiam Beguin #define LMK04832_BIT_DCLKX_Y_PD BIT(4)
483bc61cfdSLiam Beguin #define LMK04832_BIT_DCLKX_Y_DCC BIT(2)
496181baa1SLiam Beguin #define LMK04832_BIT_DCLKX_Y_HS BIT(0)
503bc61cfdSLiam Beguin #define LMK04832_REG_CLKOUT_CTRL4(ch) (0x104 + (ch >> 1) * 8)
513bc61cfdSLiam Beguin #define LMK04832_BIT_SCLK_PD BIT(4)
526181baa1SLiam Beguin #define LMK04832_BIT_SCLKX_Y_DIS_MODE GENMASK(3, 2)
536181baa1SLiam Beguin #define LMK04832_REG_SCLKX_Y_ADLY(ch) (0x105 + (ch >> 1) * 8)
546181baa1SLiam Beguin #define LMK04832_REG_SCLKX_Y_DDLY(ch) (0x106 + (ch >> 1) * 8)
556181baa1SLiam Beguin #define LMK04832_BIT_SCLKX_Y_DDLY GENMASK(3, 0)
563bc61cfdSLiam Beguin #define LMK04832_REG_CLKOUT_FMT(ch) (0x107 + (ch >> 1) * 8)
573bc61cfdSLiam Beguin #define LMK04832_BIT_CLKOUT_FMT(ch) (ch % 2 ? 0xf0 : 0x0f)
583bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_POWERDOWN 0x00
593bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_LVDS 0x01
603bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_HSDS6 0x02
613bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_HSDS8 0x03
623bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_LVPECL1600 0x04
633bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_LVPECL2000 0x05
643bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_LCPECL 0x06
653bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CML16 0x07
663bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CML24 0x08
673bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CML32 0x09
683bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CMOS_OFF_INV 0x0a
693bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_OFF 0x0b
703bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CMOS_INV_INV 0x0c
713bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CMOS_INV_NOR 0x0d
723bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_INV 0x0e
733bc61cfdSLiam Beguin #define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_NOR 0x0f
743bc61cfdSLiam Beguin
753bc61cfdSLiam Beguin /* 0x138 - 0x145 SYSREF, SYNC, and Device Config */
763bc61cfdSLiam Beguin #define LMK04832_REG_VCO_OSCOUT 0x138
773bc61cfdSLiam Beguin #define LMK04832_BIT_VCO_MUX GENMASK(6, 5)
783bc61cfdSLiam Beguin #define LMK04832_VAL_VCO_MUX_VCO0 0x00
793bc61cfdSLiam Beguin #define LMK04832_VAL_VCO_MUX_VCO1 0x01
803bc61cfdSLiam Beguin #define LMK04832_VAL_VCO_MUX_EXT 0x02
813bc61cfdSLiam Beguin #define LMK04832_REG_SYSREF_OUT 0x139
826181baa1SLiam Beguin #define LMK04832_BIT_SYSREF_REQ_EN BIT(6)
833bc61cfdSLiam Beguin #define LMK04832_BIT_SYSREF_MUX GENMASK(1, 0)
846181baa1SLiam Beguin #define LMK04832_VAL_SYSREF_MUX_NORMAL_SYNC 0x00
856181baa1SLiam Beguin #define LMK04832_VAL_SYSREF_MUX_RECLK 0x01
866181baa1SLiam Beguin #define LMK04832_VAL_SYSREF_MUX_PULSER 0x02
873bc61cfdSLiam Beguin #define LMK04832_VAL_SYSREF_MUX_CONTINUOUS 0x03
883bc61cfdSLiam Beguin #define LMK04832_REG_SYSREF_DIV_MSB 0x13a
893bc61cfdSLiam Beguin #define LMK04832_BIT_SYSREF_DIV_MSB GENMASK(4, 0)
903bc61cfdSLiam Beguin #define LMK04832_REG_SYSREF_DIV_LSB 0x13b
916181baa1SLiam Beguin #define LMK04832_REG_SYSREF_DDLY_MSB 0x13c
926181baa1SLiam Beguin #define LMK04832_BIT_SYSREF_DDLY_MSB GENMASK(4, 0)
936181baa1SLiam Beguin #define LMK04832_REG_SYSREF_DDLY_LSB 0x13d
946181baa1SLiam Beguin #define LMK04832_REG_SYSREF_PULSE_CNT 0x13e
953bc61cfdSLiam Beguin #define LMK04832_REG_FB_CTRL 0x13f
963bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_RCLK_MUX BIT(7)
973bc61cfdSLiam Beguin #define LMK04832_VAL_PLL2_RCLK_MUX_OSCIN 0x00
983bc61cfdSLiam Beguin #define LMK04832_VAL_PLL2_RCLK_MUX_CLKIN 0x01
993bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_NCLK_MUX BIT(5)
1003bc61cfdSLiam Beguin #define LMK04832_VAL_PLL2_NCLK_MUX_PLL2_P 0x00
1013bc61cfdSLiam Beguin #define LMK04832_VAL_PLL2_NCLK_MUX_FB_MUX 0x01
1023bc61cfdSLiam Beguin #define LMK04832_BIT_FB_MUX_EN BIT(0)
1033bc61cfdSLiam Beguin #define LMK04832_REG_MAIN_PD 0x140
1043bc61cfdSLiam Beguin #define LMK04832_BIT_PLL1_PD BIT(7)
1053bc61cfdSLiam Beguin #define LMK04832_BIT_VCO_LDO_PD BIT(6)
1063bc61cfdSLiam Beguin #define LMK04832_BIT_VCO_PD BIT(5)
1073bc61cfdSLiam Beguin #define LMK04832_BIT_OSCIN_PD BIT(4)
1083bc61cfdSLiam Beguin #define LMK04832_BIT_SYSREF_GBL_PD BIT(3)
1093bc61cfdSLiam Beguin #define LMK04832_BIT_SYSREF_PD BIT(2)
1103bc61cfdSLiam Beguin #define LMK04832_BIT_SYSREF_DDLY_PD BIT(1)
1113bc61cfdSLiam Beguin #define LMK04832_BIT_SYSREF_PLSR_PD BIT(0)
1123bc61cfdSLiam Beguin #define LMK04832_REG_SYNC 0x143
1136181baa1SLiam Beguin #define LMK04832_BIT_SYNC_CLR BIT(7)
1146181baa1SLiam Beguin #define LMK04832_BIT_SYNC_1SHOT_EN BIT(6)
1156181baa1SLiam Beguin #define LMK04832_BIT_SYNC_POL BIT(5)
1163bc61cfdSLiam Beguin #define LMK04832_BIT_SYNC_EN BIT(4)
1176181baa1SLiam Beguin #define LMK04832_BIT_SYNC_MODE GENMASK(1, 0)
1186181baa1SLiam Beguin #define LMK04832_VAL_SYNC_MODE_OFF 0x00
1196181baa1SLiam Beguin #define LMK04832_VAL_SYNC_MODE_ON 0x01
1206181baa1SLiam Beguin #define LMK04832_VAL_SYNC_MODE_PULSER_PIN 0x02
1216181baa1SLiam Beguin #define LMK04832_VAL_SYNC_MODE_PULSER_SPI 0x03
1223bc61cfdSLiam Beguin #define LMK04832_REG_SYNC_DIS 0x144
1233bc61cfdSLiam Beguin
1243bc61cfdSLiam Beguin /* 0x146 - 0x14a CLKin Control */
1253bc61cfdSLiam Beguin #define LMK04832_REG_CLKIN_SEL0 0x148
1263bc61cfdSLiam Beguin #define LMK04832_REG_CLKIN_SEL1 0x149
1273bc61cfdSLiam Beguin #define LMK04832_REG_CLKIN_RST 0x14a
1283bc61cfdSLiam Beguin #define LMK04832_BIT_SDIO_RDBK_TYPE BIT(6)
1293bc61cfdSLiam Beguin #define LMK04832_BIT_CLKIN_SEL_MUX GENMASK(5, 3)
1303bc61cfdSLiam Beguin #define LMK04832_VAL_CLKIN_SEL_MUX_SPI_RDBK 0x06
1313bc61cfdSLiam Beguin #define LMK04832_BIT_CLKIN_SEL_TYPE GENMASK(2, 0)
1323bc61cfdSLiam Beguin #define LMK04832_VAL_CLKIN_SEL_TYPE_OUT 0x03
1333bc61cfdSLiam Beguin
1343bc61cfdSLiam Beguin /* 0x14b - 0x152 Holdover */
1353bc61cfdSLiam Beguin
1363bc61cfdSLiam Beguin /* 0x153 - 0x15f PLL1 Configuration */
137*6aa8dc69SMike Looijmans #define LMK04832_REG_PLL1_LD 0x15f
138*6aa8dc69SMike Looijmans #define LMK04832_BIT_PLL1_LD_MUX GENMASK(7, 3)
139*6aa8dc69SMike Looijmans #define LMK04832_VAL_PLL1_LD_MUX_SPI_RDBK 0x07
140*6aa8dc69SMike Looijmans #define LMK04832_BIT_PLL1_LD_TYPE GENMASK(2, 0)
141*6aa8dc69SMike Looijmans #define LMK04832_VAL_PLL1_LD_TYPE_OUT_PP 0x03
1423bc61cfdSLiam Beguin
1433bc61cfdSLiam Beguin /* 0x160 - 0x16e PLL2 Configuration */
1443bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_R_MSB 0x160
1453bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_R_MSB GENMASK(3, 0)
1463bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_R_LSB 0x161
1473bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_MISC 0x162
1483bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_MISC_P GENMASK(7, 5)
1493bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_MISC_REF_2X_EN BIT(0)
1503bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_N_CAL_0 0x163
1513bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_N_CAL_0 GENMASK(1, 0)
1523bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_N_CAL_1 0x164
1533bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_N_CAL_2 0x165
1543bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_N_0 0x166
1553bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_N_0 GENMASK(1, 0)
1563bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_N_1 0x167
1573bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_N_2 0x168
1586181baa1SLiam Beguin #define LMK04832_REG_PLL2_DLD_CNT_MSB 0x16a
1593bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_DLD_CNT_LSB 0x16b
1603bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_LD 0x16e
1613bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_LD_MUX GENMASK(7, 3)
1623bc61cfdSLiam Beguin #define LMK04832_VAL_PLL2_LD_MUX_PLL2_DLD 0x02
1633bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_LD_TYPE GENMASK(2, 0)
1643bc61cfdSLiam Beguin #define LMK04832_VAL_PLL2_LD_TYPE_OUT_PP 0x03
1653bc61cfdSLiam Beguin
1663bc61cfdSLiam Beguin /* 0x16F - 0x555 Misc Registers */
1673bc61cfdSLiam Beguin #define LMK04832_REG_PLL2_PD 0x173
1683bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_PRE_PD BIT(6)
1693bc61cfdSLiam Beguin #define LMK04832_BIT_PLL2_PD BIT(5)
1703bc61cfdSLiam Beguin #define LMK04832_REG_PLL1R_RST 0x177
1713bc61cfdSLiam Beguin #define LMK04832_REG_CLR_PLL_LOST 0x182
1723bc61cfdSLiam Beguin #define LMK04832_REG_RB_PLL_LD 0x183
1733bc61cfdSLiam Beguin #define LMK04832_REG_RB_CLK_DAC_VAL_MSB 0x184
1743bc61cfdSLiam Beguin #define LMK04832_REG_RB_DAC_VAL_LSB 0x185
1753bc61cfdSLiam Beguin #define LMK04832_REG_RB_HOLDOVER 0x188
1763bc61cfdSLiam Beguin #define LMK04832_REG_SPI_LOCK 0x555
1773bc61cfdSLiam Beguin
1783bc61cfdSLiam Beguin enum lmk04832_device_types {
1793bc61cfdSLiam Beguin LMK04832,
1803bc61cfdSLiam Beguin };
1813bc61cfdSLiam Beguin
1823bc61cfdSLiam Beguin /**
18340b85eecSLiam Beguin * struct lmk04832_device_info - Holds static device information that is
18440b85eecSLiam Beguin * specific to the chip revision
1853bc61cfdSLiam Beguin *
18640b85eecSLiam Beguin * @pid: Product Identifier
18740b85eecSLiam Beguin * @maskrev: IC version identifier
18840b85eecSLiam Beguin * @num_channels: Number of available output channels (clkout count)
18940b85eecSLiam Beguin * @vco0_range: {min, max} of the VCO0 operating range (in MHz)
19040b85eecSLiam Beguin * @vco1_range: {min, max} of the VCO1 operating range (in MHz)
1913bc61cfdSLiam Beguin */
1923bc61cfdSLiam Beguin struct lmk04832_device_info {
1933bc61cfdSLiam Beguin u16 pid;
1943bc61cfdSLiam Beguin u8 maskrev;
1953bc61cfdSLiam Beguin size_t num_channels;
1963bc61cfdSLiam Beguin unsigned int vco0_range[2];
1973bc61cfdSLiam Beguin unsigned int vco1_range[2];
1983bc61cfdSLiam Beguin };
1993bc61cfdSLiam Beguin
2003bc61cfdSLiam Beguin static const struct lmk04832_device_info lmk04832_device_info[] = {
2013bc61cfdSLiam Beguin [LMK04832] = {
2023bc61cfdSLiam Beguin .pid = 0x63d1, /* WARNING PROD_ID is inverted in the datasheet */
2033bc61cfdSLiam Beguin .maskrev = 0x70,
2043bc61cfdSLiam Beguin .num_channels = 14,
2053bc61cfdSLiam Beguin .vco0_range = { 2440, 2580 },
2063bc61cfdSLiam Beguin .vco1_range = { 2945, 3255 },
2073bc61cfdSLiam Beguin },
2083bc61cfdSLiam Beguin };
2093bc61cfdSLiam Beguin
2103bc61cfdSLiam Beguin enum lmk04832_rdbk_type {
2113bc61cfdSLiam Beguin RDBK_CLKIN_SEL0,
2123bc61cfdSLiam Beguin RDBK_CLKIN_SEL1,
2133bc61cfdSLiam Beguin RDBK_RESET,
214*6aa8dc69SMike Looijmans RDBK_PLL1_LD,
2153bc61cfdSLiam Beguin };
2163bc61cfdSLiam Beguin
2173bc61cfdSLiam Beguin struct lmk_dclk {
2183bc61cfdSLiam Beguin struct lmk04832 *lmk;
2193bc61cfdSLiam Beguin struct clk_hw hw;
2203bc61cfdSLiam Beguin u8 id;
2213bc61cfdSLiam Beguin };
2223bc61cfdSLiam Beguin
2233bc61cfdSLiam Beguin struct lmk_clkout {
2243bc61cfdSLiam Beguin struct lmk04832 *lmk;
2253bc61cfdSLiam Beguin struct clk_hw hw;
2263bc61cfdSLiam Beguin bool sysref;
2273bc61cfdSLiam Beguin u32 format;
2283bc61cfdSLiam Beguin u8 id;
2293bc61cfdSLiam Beguin };
2303bc61cfdSLiam Beguin
2313bc61cfdSLiam Beguin /**
2323bc61cfdSLiam Beguin * struct lmk04832 - The LMK04832 device structure
2333bc61cfdSLiam Beguin *
2343bc61cfdSLiam Beguin * @dev: reference to a struct device, linked to the spi_device
2353bc61cfdSLiam Beguin * @regmap: struct regmap instance use to access the chip
2366181baa1SLiam Beguin * @sync_mode: operational mode for SYNC signal
2376181baa1SLiam Beguin * @sysref_mux: select SYSREF source
2386181baa1SLiam Beguin * @sysref_pulse_cnt: number of SYSREF pulses generated while not in continuous
2396181baa1SLiam Beguin * mode.
2406181baa1SLiam Beguin * @sysref_ddly: SYSREF digital delay value
2413bc61cfdSLiam Beguin * @oscin: PLL2 input clock
2423bc61cfdSLiam Beguin * @vco: reference to the internal VCO clock
2433bc61cfdSLiam Beguin * @sclk: reference to the internal sysref clock (SCLK)
2443bc61cfdSLiam Beguin * @vco_rate: user provided VCO rate
2453bc61cfdSLiam Beguin * @reset_gpio: reference to the reset GPIO
2463bc61cfdSLiam Beguin * @dclk: list of internal device clock references.
2473bc61cfdSLiam Beguin * Each pair of clkout clocks share a single device clock (DCLKX_Y)
2483bc61cfdSLiam Beguin * @clkout: list of output clock references
2493bc61cfdSLiam Beguin * @clk_data: holds clkout related data like clk_hw* and number of clocks
2503bc61cfdSLiam Beguin */
2513bc61cfdSLiam Beguin struct lmk04832 {
2523bc61cfdSLiam Beguin struct device *dev;
2533bc61cfdSLiam Beguin struct regmap *regmap;
2543bc61cfdSLiam Beguin
2556181baa1SLiam Beguin unsigned int sync_mode;
2566181baa1SLiam Beguin unsigned int sysref_mux;
2576181baa1SLiam Beguin unsigned int sysref_pulse_cnt;
2586181baa1SLiam Beguin unsigned int sysref_ddly;
2596181baa1SLiam Beguin
2603bc61cfdSLiam Beguin struct clk *oscin;
2613bc61cfdSLiam Beguin struct clk_hw vco;
2623bc61cfdSLiam Beguin struct clk_hw sclk;
2633bc61cfdSLiam Beguin unsigned int vco_rate;
2643bc61cfdSLiam Beguin
2653bc61cfdSLiam Beguin struct gpio_desc *reset_gpio;
2663bc61cfdSLiam Beguin
2673bc61cfdSLiam Beguin struct lmk_dclk *dclk;
2683bc61cfdSLiam Beguin struct lmk_clkout *clkout;
2693bc61cfdSLiam Beguin struct clk_hw_onecell_data *clk_data;
2703bc61cfdSLiam Beguin };
2713bc61cfdSLiam Beguin
lmk04832_regmap_rd_regs(struct device * dev,unsigned int reg)2723bc61cfdSLiam Beguin static bool lmk04832_regmap_rd_regs(struct device *dev, unsigned int reg)
2733bc61cfdSLiam Beguin {
2743bc61cfdSLiam Beguin switch (reg) {
2753bc61cfdSLiam Beguin case LMK04832_REG_RST3W ... LMK04832_REG_ID_MASKREV:
2763bc61cfdSLiam Beguin case LMK04832_REG_ID_VNDR_MSB:
2773bc61cfdSLiam Beguin case LMK04832_REG_ID_VNDR_LSB:
2783bc61cfdSLiam Beguin case LMK04832_REG_CLKOUT_CTRL0(0) ... LMK04832_REG_PLL2_DLD_CNT_LSB:
2793bc61cfdSLiam Beguin case LMK04832_REG_PLL2_LD:
2803bc61cfdSLiam Beguin case LMK04832_REG_PLL2_PD:
2813bc61cfdSLiam Beguin case LMK04832_REG_PLL1R_RST:
2823bc61cfdSLiam Beguin case LMK04832_REG_CLR_PLL_LOST ... LMK04832_REG_RB_DAC_VAL_LSB:
2833bc61cfdSLiam Beguin case LMK04832_REG_RB_HOLDOVER:
2843bc61cfdSLiam Beguin case LMK04832_REG_SPI_LOCK:
2853bc61cfdSLiam Beguin return true;
2863bc61cfdSLiam Beguin default:
2873bc61cfdSLiam Beguin return false;
2883bc61cfdSLiam Beguin };
289992a3552SLiam Beguin }
2903bc61cfdSLiam Beguin
lmk04832_regmap_wr_regs(struct device * dev,unsigned int reg)2913bc61cfdSLiam Beguin static bool lmk04832_regmap_wr_regs(struct device *dev, unsigned int reg)
2923bc61cfdSLiam Beguin {
2933bc61cfdSLiam Beguin switch (reg) {
2943bc61cfdSLiam Beguin case LMK04832_REG_RST3W:
2953bc61cfdSLiam Beguin case LMK04832_REG_POWERDOWN:
2963bc61cfdSLiam Beguin return true;
2973bc61cfdSLiam Beguin case LMK04832_REG_ID_DEV_TYPE ... LMK04832_REG_ID_MASKREV:
2983bc61cfdSLiam Beguin case LMK04832_REG_ID_VNDR_MSB:
2993bc61cfdSLiam Beguin case LMK04832_REG_ID_VNDR_LSB:
3003bc61cfdSLiam Beguin return false;
3013bc61cfdSLiam Beguin case LMK04832_REG_CLKOUT_CTRL0(0) ... LMK04832_REG_PLL2_DLD_CNT_LSB:
3023bc61cfdSLiam Beguin case LMK04832_REG_PLL2_LD:
3033bc61cfdSLiam Beguin case LMK04832_REG_PLL2_PD:
3043bc61cfdSLiam Beguin case LMK04832_REG_PLL1R_RST:
3053bc61cfdSLiam Beguin case LMK04832_REG_CLR_PLL_LOST ... LMK04832_REG_RB_DAC_VAL_LSB:
3063bc61cfdSLiam Beguin case LMK04832_REG_RB_HOLDOVER:
3073bc61cfdSLiam Beguin case LMK04832_REG_SPI_LOCK:
3083bc61cfdSLiam Beguin return true;
3093bc61cfdSLiam Beguin default:
3103bc61cfdSLiam Beguin return false;
3113bc61cfdSLiam Beguin };
312992a3552SLiam Beguin }
3133bc61cfdSLiam Beguin
3143bc61cfdSLiam Beguin static const struct regmap_config regmap_config = {
3153bc61cfdSLiam Beguin .name = "lmk04832",
3163bc61cfdSLiam Beguin .reg_bits = 16,
3173bc61cfdSLiam Beguin .val_bits = 8,
3183bc61cfdSLiam Beguin .use_single_read = 1,
3193bc61cfdSLiam Beguin .use_single_write = 1,
3203bc61cfdSLiam Beguin .read_flag_mask = 0x80,
3213bc61cfdSLiam Beguin .write_flag_mask = 0x00,
3223bc61cfdSLiam Beguin .readable_reg = lmk04832_regmap_rd_regs,
3233bc61cfdSLiam Beguin .writeable_reg = lmk04832_regmap_wr_regs,
3243bc61cfdSLiam Beguin .cache_type = REGCACHE_NONE,
3253bc61cfdSLiam Beguin .max_register = LMK04832_REG_SPI_LOCK,
3263bc61cfdSLiam Beguin };
3273bc61cfdSLiam Beguin
lmk04832_vco_is_enabled(struct clk_hw * hw)3283bc61cfdSLiam Beguin static int lmk04832_vco_is_enabled(struct clk_hw *hw)
3293bc61cfdSLiam Beguin {
3303bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco);
3313bc61cfdSLiam Beguin unsigned int tmp;
3323bc61cfdSLiam Beguin int ret;
3333bc61cfdSLiam Beguin
3343bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_MAIN_PD, &tmp);
3353bc61cfdSLiam Beguin if (ret)
3363bc61cfdSLiam Beguin return ret;
3373bc61cfdSLiam Beguin
3383bc61cfdSLiam Beguin return !(FIELD_GET(LMK04832_BIT_OSCIN_PD, tmp) |
3393bc61cfdSLiam Beguin FIELD_GET(LMK04832_BIT_VCO_PD, tmp) |
3403bc61cfdSLiam Beguin FIELD_GET(LMK04832_BIT_VCO_LDO_PD, tmp));
3413bc61cfdSLiam Beguin }
3423bc61cfdSLiam Beguin
lmk04832_vco_prepare(struct clk_hw * hw)3433bc61cfdSLiam Beguin static int lmk04832_vco_prepare(struct clk_hw *hw)
3443bc61cfdSLiam Beguin {
3453bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco);
3463bc61cfdSLiam Beguin int ret;
3473bc61cfdSLiam Beguin
3483bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_PD,
3493bc61cfdSLiam Beguin LMK04832_BIT_PLL2_PRE_PD |
3503bc61cfdSLiam Beguin LMK04832_BIT_PLL2_PD,
3513bc61cfdSLiam Beguin 0x00);
3523bc61cfdSLiam Beguin if (ret)
3533bc61cfdSLiam Beguin return ret;
3543bc61cfdSLiam Beguin
3553bc61cfdSLiam Beguin return regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD,
3563bc61cfdSLiam Beguin LMK04832_BIT_VCO_LDO_PD |
3573bc61cfdSLiam Beguin LMK04832_BIT_VCO_PD |
3583bc61cfdSLiam Beguin LMK04832_BIT_OSCIN_PD, 0x00);
3593bc61cfdSLiam Beguin }
3603bc61cfdSLiam Beguin
lmk04832_vco_unprepare(struct clk_hw * hw)3613bc61cfdSLiam Beguin static void lmk04832_vco_unprepare(struct clk_hw *hw)
3623bc61cfdSLiam Beguin {
3633bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco);
3643bc61cfdSLiam Beguin
3653bc61cfdSLiam Beguin regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_PD,
3663bc61cfdSLiam Beguin LMK04832_BIT_PLL2_PRE_PD | LMK04832_BIT_PLL2_PD,
3673bc61cfdSLiam Beguin 0xff);
3683bc61cfdSLiam Beguin
3693bc61cfdSLiam Beguin /* Don't set LMK04832_BIT_OSCIN_PD since other clocks depend on it */
3703bc61cfdSLiam Beguin regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD,
3713bc61cfdSLiam Beguin LMK04832_BIT_VCO_LDO_PD | LMK04832_BIT_VCO_PD, 0xff);
3723bc61cfdSLiam Beguin }
3733bc61cfdSLiam Beguin
lmk04832_vco_recalc_rate(struct clk_hw * hw,unsigned long prate)3743bc61cfdSLiam Beguin static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw,
3753bc61cfdSLiam Beguin unsigned long prate)
3763bc61cfdSLiam Beguin {
3773bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco);
3786c634446SLiam Beguin const unsigned int pll2_p[] = {8, 2, 2, 3, 4, 5, 6, 7};
3793bc61cfdSLiam Beguin unsigned int pll2_n, p, pll2_r;
3803bc61cfdSLiam Beguin unsigned int pll2_misc;
3813bc61cfdSLiam Beguin unsigned long vco_rate;
3823bc61cfdSLiam Beguin u8 tmp[3];
3833bc61cfdSLiam Beguin int ret;
3843bc61cfdSLiam Beguin
3853bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_PLL2_MISC, &pll2_misc);
3863bc61cfdSLiam Beguin if (ret)
3873bc61cfdSLiam Beguin return ret;
3883bc61cfdSLiam Beguin
3893bc61cfdSLiam Beguin p = FIELD_GET(LMK04832_BIT_PLL2_MISC_P, pll2_misc);
3903bc61cfdSLiam Beguin
3913bc61cfdSLiam Beguin ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_PLL2_N_0, &tmp, 3);
3923bc61cfdSLiam Beguin if (ret)
3933bc61cfdSLiam Beguin return ret;
3943bc61cfdSLiam Beguin
3953bc61cfdSLiam Beguin pll2_n = FIELD_PREP(0x030000, tmp[0]) |
3963bc61cfdSLiam Beguin FIELD_PREP(0x00ff00, tmp[1]) |
3973bc61cfdSLiam Beguin FIELD_PREP(0x0000ff, tmp[2]);
3983bc61cfdSLiam Beguin
3993bc61cfdSLiam Beguin ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_PLL2_R_MSB, &tmp, 2);
4003bc61cfdSLiam Beguin if (ret)
4013bc61cfdSLiam Beguin return ret;
4023bc61cfdSLiam Beguin
4033bc61cfdSLiam Beguin pll2_r = FIELD_PREP(0x0f00, tmp[0]) |
4043bc61cfdSLiam Beguin FIELD_PREP(0x00ff, tmp[1]);
4053bc61cfdSLiam Beguin
4063bc61cfdSLiam Beguin vco_rate = (prate << FIELD_GET(LMK04832_BIT_PLL2_MISC_REF_2X_EN,
4073bc61cfdSLiam Beguin pll2_misc)) * pll2_n * pll2_p[p] / pll2_r;
4083bc61cfdSLiam Beguin
4093bc61cfdSLiam Beguin return vco_rate;
410992a3552SLiam Beguin }
4113bc61cfdSLiam Beguin
4123bc61cfdSLiam Beguin /**
4133bc61cfdSLiam Beguin * lmk04832_check_vco_ranges - Check requested VCO frequency against VCO ranges
4143bc61cfdSLiam Beguin *
4153bc61cfdSLiam Beguin * @lmk: Reference to the lmk device
4163bc61cfdSLiam Beguin * @rate: Desired output rate for the VCO
4173bc61cfdSLiam Beguin *
4183bc61cfdSLiam Beguin * The LMK04832 has 2 internal VCO, each with independent operating ranges.
4193bc61cfdSLiam Beguin * Use the device_info structure to determine which VCO to use based on rate.
4203bc61cfdSLiam Beguin *
42140b85eecSLiam Beguin * Returns: VCO_MUX value or negative errno.
4223bc61cfdSLiam Beguin */
lmk04832_check_vco_ranges(struct lmk04832 * lmk,unsigned long rate)4233bc61cfdSLiam Beguin static int lmk04832_check_vco_ranges(struct lmk04832 *lmk, unsigned long rate)
4243bc61cfdSLiam Beguin {
4253bc61cfdSLiam Beguin struct spi_device *spi = to_spi_device(lmk->dev);
4263bc61cfdSLiam Beguin const struct lmk04832_device_info *info;
4273bc61cfdSLiam Beguin unsigned long mhz = rate / 1000000;
4283bc61cfdSLiam Beguin
4293bc61cfdSLiam Beguin info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data];
4303bc61cfdSLiam Beguin
4313bc61cfdSLiam Beguin if (mhz >= info->vco0_range[0] && mhz <= info->vco0_range[1])
4323bc61cfdSLiam Beguin return LMK04832_VAL_VCO_MUX_VCO0;
4333bc61cfdSLiam Beguin
4343bc61cfdSLiam Beguin if (mhz >= info->vco1_range[0] && mhz <= info->vco1_range[1])
4353bc61cfdSLiam Beguin return LMK04832_VAL_VCO_MUX_VCO1;
4363bc61cfdSLiam Beguin
4373bc61cfdSLiam Beguin dev_err(lmk->dev, "%lu Hz is out of VCO ranges\n", rate);
4383bc61cfdSLiam Beguin return -ERANGE;
4393bc61cfdSLiam Beguin }
4403bc61cfdSLiam Beguin
4413bc61cfdSLiam Beguin /**
4423bc61cfdSLiam Beguin * lmk04832_calc_pll2_params - Get PLL2 parameters used to set the VCO frequency
4433bc61cfdSLiam Beguin *
4443bc61cfdSLiam Beguin * @prate: parent rate to the PLL2, usually OSCin
4453bc61cfdSLiam Beguin * @rate: Desired output rate for the VCO
4463bc61cfdSLiam Beguin * @n: reference to PLL2_N
4473bc61cfdSLiam Beguin * @p: reference to PLL2_P
4483bc61cfdSLiam Beguin * @r: reference to PLL2_R
4493bc61cfdSLiam Beguin *
4503bc61cfdSLiam Beguin * This functions assumes LMK04832_BIT_PLL2_MISC_REF_2X_EN is set since it is
4513bc61cfdSLiam Beguin * recommended in the datasheet because a higher phase detector frequencies
4523bc61cfdSLiam Beguin * makes the design of wider loop bandwidth filters possible.
4533bc61cfdSLiam Beguin *
4543bc61cfdSLiam Beguin * the VCO rate can be calculated using the following expression:
4553bc61cfdSLiam Beguin *
4563bc61cfdSLiam Beguin * VCO = OSCin * 2 * PLL2_N * PLL2_P / PLL2_R
4573bc61cfdSLiam Beguin *
45840b85eecSLiam Beguin * Returns: vco rate or negative errno.
4593bc61cfdSLiam Beguin */
lmk04832_calc_pll2_params(unsigned long prate,unsigned long rate,unsigned int * n,unsigned int * p,unsigned int * r)4603bc61cfdSLiam Beguin static long lmk04832_calc_pll2_params(unsigned long prate, unsigned long rate,
4613bc61cfdSLiam Beguin unsigned int *n, unsigned int *p,
4623bc61cfdSLiam Beguin unsigned int *r)
4633bc61cfdSLiam Beguin {
4643bc61cfdSLiam Beguin unsigned int pll2_n, pll2_p, pll2_r;
4653bc61cfdSLiam Beguin unsigned long num, div;
4663bc61cfdSLiam Beguin
4673bc61cfdSLiam Beguin /* Set PLL2_P to a fixed value to simplify optimizations */
4683bc61cfdSLiam Beguin pll2_p = 2;
4693bc61cfdSLiam Beguin
4703bc61cfdSLiam Beguin div = gcd(rate, prate);
4713bc61cfdSLiam Beguin
4723bc61cfdSLiam Beguin num = DIV_ROUND_CLOSEST(rate, div);
4733bc61cfdSLiam Beguin pll2_r = DIV_ROUND_CLOSEST(prate, div);
4743bc61cfdSLiam Beguin
4753bc61cfdSLiam Beguin if (num > 4) {
4763bc61cfdSLiam Beguin pll2_n = num >> 2;
4773bc61cfdSLiam Beguin } else {
4783bc61cfdSLiam Beguin pll2_r = pll2_r << 2;
4793bc61cfdSLiam Beguin pll2_n = num;
4803bc61cfdSLiam Beguin }
4813bc61cfdSLiam Beguin
4823bc61cfdSLiam Beguin if (pll2_n < 1 || pll2_n > 0x03ffff)
4833bc61cfdSLiam Beguin return -EINVAL;
4843bc61cfdSLiam Beguin if (pll2_r < 1 || pll2_r > 0xfff)
4853bc61cfdSLiam Beguin return -EINVAL;
4863bc61cfdSLiam Beguin
4873bc61cfdSLiam Beguin *n = pll2_n;
4883bc61cfdSLiam Beguin *p = pll2_p;
4893bc61cfdSLiam Beguin *r = pll2_r;
4903bc61cfdSLiam Beguin
4913bc61cfdSLiam Beguin return DIV_ROUND_CLOSEST(prate * 2 * pll2_p * pll2_n, pll2_r);
4923bc61cfdSLiam Beguin }
4933bc61cfdSLiam Beguin
lmk04832_vco_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)4943bc61cfdSLiam Beguin static long lmk04832_vco_round_rate(struct clk_hw *hw, unsigned long rate,
4953bc61cfdSLiam Beguin unsigned long *prate)
4963bc61cfdSLiam Beguin {
4973bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco);
4983bc61cfdSLiam Beguin unsigned int n, p, r;
4993bc61cfdSLiam Beguin long vco_rate;
5003bc61cfdSLiam Beguin int ret;
5013bc61cfdSLiam Beguin
5023bc61cfdSLiam Beguin ret = lmk04832_check_vco_ranges(lmk, rate);
5033bc61cfdSLiam Beguin if (ret < 0)
5043bc61cfdSLiam Beguin return ret;
5053bc61cfdSLiam Beguin
5063bc61cfdSLiam Beguin vco_rate = lmk04832_calc_pll2_params(*prate, rate, &n, &p, &r);
5073bc61cfdSLiam Beguin if (vco_rate < 0) {
5082cdee50eSColin Ian King dev_err(lmk->dev, "PLL2 parameters out of range\n");
5093bc61cfdSLiam Beguin return vco_rate;
5103bc61cfdSLiam Beguin }
5113bc61cfdSLiam Beguin
5123bc61cfdSLiam Beguin if (rate != vco_rate)
5133bc61cfdSLiam Beguin return -EINVAL;
5143bc61cfdSLiam Beguin
5153bc61cfdSLiam Beguin return vco_rate;
516992a3552SLiam Beguin }
5173bc61cfdSLiam Beguin
lmk04832_vco_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long prate)5183bc61cfdSLiam Beguin static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate,
5193bc61cfdSLiam Beguin unsigned long prate)
5203bc61cfdSLiam Beguin {
5213bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco);
5223bc61cfdSLiam Beguin unsigned int n, p, r;
5233bc61cfdSLiam Beguin long vco_rate;
5243bc61cfdSLiam Beguin int vco_mux;
5253bc61cfdSLiam Beguin int ret;
5263bc61cfdSLiam Beguin
5273bc61cfdSLiam Beguin vco_mux = lmk04832_check_vco_ranges(lmk, rate);
5283bc61cfdSLiam Beguin if (vco_mux < 0)
5293bc61cfdSLiam Beguin return vco_mux;
5303bc61cfdSLiam Beguin
5313bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_VCO_OSCOUT,
5323bc61cfdSLiam Beguin LMK04832_BIT_VCO_MUX,
5333bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_VCO_MUX, vco_mux));
5343bc61cfdSLiam Beguin if (ret)
5353bc61cfdSLiam Beguin return ret;
5363bc61cfdSLiam Beguin
5373bc61cfdSLiam Beguin vco_rate = lmk04832_calc_pll2_params(prate, rate, &n, &p, &r);
5383bc61cfdSLiam Beguin if (vco_rate < 0) {
5392cdee50eSColin Ian King dev_err(lmk->dev, "failed to determine PLL2 parameters\n");
5403bc61cfdSLiam Beguin return vco_rate;
5413bc61cfdSLiam Beguin }
5423bc61cfdSLiam Beguin
5433bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_R_MSB,
5443bc61cfdSLiam Beguin LMK04832_BIT_PLL2_R_MSB,
5453bc61cfdSLiam Beguin FIELD_GET(0x000700, r));
5463bc61cfdSLiam Beguin if (ret)
5473bc61cfdSLiam Beguin return ret;
5483bc61cfdSLiam Beguin
5493bc61cfdSLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_R_LSB,
5503bc61cfdSLiam Beguin FIELD_GET(0x0000ff, r));
5513bc61cfdSLiam Beguin if (ret)
5523bc61cfdSLiam Beguin return ret;
5533bc61cfdSLiam Beguin
5543bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_MISC,
5553bc61cfdSLiam Beguin LMK04832_BIT_PLL2_MISC_P,
5563bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_PLL2_MISC_P, p));
5573bc61cfdSLiam Beguin if (ret)
5583bc61cfdSLiam Beguin return ret;
5593bc61cfdSLiam Beguin
5603bc61cfdSLiam Beguin /*
5613bc61cfdSLiam Beguin * PLL2_N registers must be programmed after other PLL2 dividers are
5622cdee50eSColin Ian King * programmed to ensure proper VCO frequency calibration
5633bc61cfdSLiam Beguin */
5643bc61cfdSLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_0,
5653bc61cfdSLiam Beguin FIELD_GET(0x030000, n));
5663bc61cfdSLiam Beguin if (ret)
5673bc61cfdSLiam Beguin return ret;
5683bc61cfdSLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_1,
5693bc61cfdSLiam Beguin FIELD_GET(0x00ff00, n));
5703bc61cfdSLiam Beguin if (ret)
5713bc61cfdSLiam Beguin return ret;
5723bc61cfdSLiam Beguin
5733bc61cfdSLiam Beguin return regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_2,
5743bc61cfdSLiam Beguin FIELD_GET(0x0000ff, n));
575992a3552SLiam Beguin }
5763bc61cfdSLiam Beguin
5773bc61cfdSLiam Beguin static const struct clk_ops lmk04832_vco_ops = {
5783bc61cfdSLiam Beguin .is_enabled = lmk04832_vco_is_enabled,
5793bc61cfdSLiam Beguin .prepare = lmk04832_vco_prepare,
5803bc61cfdSLiam Beguin .unprepare = lmk04832_vco_unprepare,
5813bc61cfdSLiam Beguin .recalc_rate = lmk04832_vco_recalc_rate,
5823bc61cfdSLiam Beguin .round_rate = lmk04832_vco_round_rate,
5833bc61cfdSLiam Beguin .set_rate = lmk04832_vco_set_rate,
5843bc61cfdSLiam Beguin };
5853bc61cfdSLiam Beguin
5863bc61cfdSLiam Beguin /*
5873bc61cfdSLiam Beguin * lmk04832_register_vco - Initialize the internal VCO and clock distribution
5883bc61cfdSLiam Beguin * path in PLL2 single loop mode.
5893bc61cfdSLiam Beguin */
lmk04832_register_vco(struct lmk04832 * lmk)5903bc61cfdSLiam Beguin static int lmk04832_register_vco(struct lmk04832 *lmk)
5913bc61cfdSLiam Beguin {
5923bc61cfdSLiam Beguin const char *parent_names[1];
5933bc61cfdSLiam Beguin struct clk_init_data init;
5943bc61cfdSLiam Beguin int ret;
5953bc61cfdSLiam Beguin
5963bc61cfdSLiam Beguin init.name = "lmk-vco";
5973bc61cfdSLiam Beguin parent_names[0] = __clk_get_name(lmk->oscin);
5983bc61cfdSLiam Beguin init.parent_names = parent_names;
5993bc61cfdSLiam Beguin
6003bc61cfdSLiam Beguin init.ops = &lmk04832_vco_ops;
6013bc61cfdSLiam Beguin init.num_parents = 1;
6023bc61cfdSLiam Beguin
6033bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_VCO_OSCOUT,
6043bc61cfdSLiam Beguin LMK04832_BIT_VCO_MUX,
6053bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_VCO_MUX,
6063bc61cfdSLiam Beguin LMK04832_VAL_VCO_MUX_VCO1));
6073bc61cfdSLiam Beguin if (ret)
6083bc61cfdSLiam Beguin return ret;
6093bc61cfdSLiam Beguin
6103bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_FB_CTRL,
6113bc61cfdSLiam Beguin LMK04832_BIT_PLL2_RCLK_MUX |
6123bc61cfdSLiam Beguin LMK04832_BIT_PLL2_NCLK_MUX,
6133bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_PLL2_RCLK_MUX,
6143bc61cfdSLiam Beguin LMK04832_VAL_PLL2_RCLK_MUX_OSCIN)|
6153bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_PLL2_NCLK_MUX,
6163bc61cfdSLiam Beguin LMK04832_VAL_PLL2_NCLK_MUX_PLL2_P));
6173bc61cfdSLiam Beguin if (ret)
6183bc61cfdSLiam Beguin return ret;
6193bc61cfdSLiam Beguin
6203bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_MISC,
6213bc61cfdSLiam Beguin LMK04832_BIT_PLL2_MISC_REF_2X_EN,
6223bc61cfdSLiam Beguin LMK04832_BIT_PLL2_MISC_REF_2X_EN);
6233bc61cfdSLiam Beguin if (ret)
6243bc61cfdSLiam Beguin return ret;
6253bc61cfdSLiam Beguin
6263bc61cfdSLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_LD,
6273bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_PLL2_LD_MUX,
6283bc61cfdSLiam Beguin LMK04832_VAL_PLL2_LD_MUX_PLL2_DLD) |
6293bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_PLL2_LD_TYPE,
6303bc61cfdSLiam Beguin LMK04832_VAL_PLL2_LD_TYPE_OUT_PP));
6313bc61cfdSLiam Beguin if (ret)
6323bc61cfdSLiam Beguin return ret;
6333bc61cfdSLiam Beguin
6343bc61cfdSLiam Beguin lmk->vco.init = &init;
6353bc61cfdSLiam Beguin return devm_clk_hw_register(lmk->dev, &lmk->vco);
6363bc61cfdSLiam Beguin }
6373bc61cfdSLiam Beguin
lmk04832_clkout_set_ddly(struct lmk04832 * lmk,int id)6386181baa1SLiam Beguin static int lmk04832_clkout_set_ddly(struct lmk04832 *lmk, int id)
6396181baa1SLiam Beguin {
6406c634446SLiam Beguin const int dclk_div_adj[] = {0, 0, -2, -2, 0, 3, -1, 0};
6416181baa1SLiam Beguin unsigned int sclkx_y_ddly = 10;
6426181baa1SLiam Beguin unsigned int dclkx_y_ddly;
6436181baa1SLiam Beguin unsigned int dclkx_y_div;
6446181baa1SLiam Beguin unsigned int sysref_ddly;
6456181baa1SLiam Beguin unsigned int dclkx_y_hs;
6466181baa1SLiam Beguin unsigned int lsb, msb;
6476181baa1SLiam Beguin int ret;
6486181baa1SLiam Beguin
6496181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap,
6506181baa1SLiam Beguin LMK04832_REG_CLKOUT_CTRL2(id),
6516181baa1SLiam Beguin LMK04832_BIT_DCLKX_Y_DDLY_PD,
6526181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_DCLKX_Y_DDLY_PD, 0));
6536181baa1SLiam Beguin if (ret)
6546181baa1SLiam Beguin return ret;
6556181baa1SLiam Beguin
6566181baa1SLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_SYSREF_DDLY_LSB, &lsb);
6576181baa1SLiam Beguin if (ret)
6586181baa1SLiam Beguin return ret;
6596181baa1SLiam Beguin
6606181baa1SLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_SYSREF_DDLY_MSB, &msb);
6616181baa1SLiam Beguin if (ret)
6626181baa1SLiam Beguin return ret;
6636181baa1SLiam Beguin
6646181baa1SLiam Beguin sysref_ddly = FIELD_GET(LMK04832_BIT_SYSREF_DDLY_MSB, msb) << 8 | lsb;
6656181baa1SLiam Beguin
6666181baa1SLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(id), &lsb);
6676181baa1SLiam Beguin if (ret)
6686181baa1SLiam Beguin return ret;
6696181baa1SLiam Beguin
6706181baa1SLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(id), &msb);
6716181baa1SLiam Beguin if (ret)
6726181baa1SLiam Beguin return ret;
6736181baa1SLiam Beguin
6746181baa1SLiam Beguin dclkx_y_div = FIELD_GET(LMK04832_BIT_DCLK_DIV_MSB, msb) << 8 | lsb;
6756181baa1SLiam Beguin
6766181baa1SLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL3(id), &lsb);
6776181baa1SLiam Beguin if (ret)
6786181baa1SLiam Beguin return ret;
6796181baa1SLiam Beguin
6806181baa1SLiam Beguin dclkx_y_hs = FIELD_GET(LMK04832_BIT_DCLKX_Y_HS, lsb);
6816181baa1SLiam Beguin
6826181baa1SLiam Beguin dclkx_y_ddly = sysref_ddly + 1 -
6836181baa1SLiam Beguin dclk_div_adj[dclkx_y_div < 6 ? dclkx_y_div : 7] -
6846181baa1SLiam Beguin dclkx_y_hs + sclkx_y_ddly;
6856181baa1SLiam Beguin
6866181baa1SLiam Beguin if (dclkx_y_ddly < 7 || dclkx_y_ddly > 0x3fff) {
6876181baa1SLiam Beguin dev_err(lmk->dev, "DCLKX_Y_DDLY out of range (%d)\n",
6886181baa1SLiam Beguin dclkx_y_ddly);
6896181baa1SLiam Beguin return -EINVAL;
6906181baa1SLiam Beguin }
6916181baa1SLiam Beguin
6926181baa1SLiam Beguin ret = regmap_write(lmk->regmap,
6936181baa1SLiam Beguin LMK04832_REG_SCLKX_Y_DDLY(id),
6946181baa1SLiam Beguin FIELD_GET(LMK04832_BIT_SCLKX_Y_DDLY, sclkx_y_ddly));
6956181baa1SLiam Beguin if (ret)
6966181baa1SLiam Beguin return ret;
6976181baa1SLiam Beguin
6986181baa1SLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_CLKOUT_CTRL1(id),
6996181baa1SLiam Beguin FIELD_GET(0x00ff, dclkx_y_ddly));
7006181baa1SLiam Beguin if (ret)
7016181baa1SLiam Beguin return ret;
7026181baa1SLiam Beguin
7036181baa1SLiam Beguin dev_dbg(lmk->dev, "clkout%02u: sysref_ddly=%u, dclkx_y_ddly=%u, "
7046181baa1SLiam Beguin "dclk_div_adj=%+d, dclkx_y_hs=%u, sclkx_y_ddly=%u\n",
7056181baa1SLiam Beguin id, sysref_ddly, dclkx_y_ddly,
7066181baa1SLiam Beguin dclk_div_adj[dclkx_y_div < 6 ? dclkx_y_div : 7],
7076181baa1SLiam Beguin dclkx_y_hs, sclkx_y_ddly);
7086181baa1SLiam Beguin
7096181baa1SLiam Beguin return regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(id),
7106181baa1SLiam Beguin LMK04832_BIT_DCLKX_Y_DDLY_MSB,
7116181baa1SLiam Beguin FIELD_GET(0x0300, dclkx_y_ddly));
7126181baa1SLiam Beguin }
7136181baa1SLiam Beguin
7146181baa1SLiam Beguin /** lmk04832_sclk_sync - Establish deterministic phase relationship between sclk
7156181baa1SLiam Beguin * and dclk
7166181baa1SLiam Beguin *
7176181baa1SLiam Beguin * @lmk: Reference to the lmk device
7186181baa1SLiam Beguin *
7196181baa1SLiam Beguin * The synchronization sequence:
7206181baa1SLiam Beguin * - in the datasheet https://www.ti.com/lit/ds/symlink/lmk04832.pdf, p.31
7216181baa1SLiam Beguin * (8.3.3.1 How to enable SYSREF)
7226181baa1SLiam Beguin * - Ti forum: https://e2e.ti.com/support/clock-and-timing/f/48/t/970972
7236181baa1SLiam Beguin *
7246181baa1SLiam Beguin * Returns 0 or negative errno.
7256181baa1SLiam Beguin */
lmk04832_sclk_sync_sequence(struct lmk04832 * lmk)7266181baa1SLiam Beguin static int lmk04832_sclk_sync_sequence(struct lmk04832 *lmk)
7276181baa1SLiam Beguin {
7286181baa1SLiam Beguin int ret;
7296181baa1SLiam Beguin int i;
7306181baa1SLiam Beguin
7316181baa1SLiam Beguin /* 1. (optional) mute all sysref_outputs during synchronization */
7326181baa1SLiam Beguin /* 2. Enable and write device clock digital delay to applicable clocks */
7336181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD,
7346181baa1SLiam Beguin LMK04832_BIT_SYSREF_DDLY_PD,
7356181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYSREF_DDLY_PD, 0));
7366181baa1SLiam Beguin if (ret)
7376181baa1SLiam Beguin return ret;
7386181baa1SLiam Beguin
7396181baa1SLiam Beguin for (i = 0; i < lmk->clk_data->num; i += 2) {
7406181baa1SLiam Beguin ret = lmk04832_clkout_set_ddly(lmk, i);
7416181baa1SLiam Beguin if (ret)
7426181baa1SLiam Beguin return ret;
7436181baa1SLiam Beguin }
7446181baa1SLiam Beguin
7456181baa1SLiam Beguin /*
7466181baa1SLiam Beguin * 3. Configure SYNC_MODE to SYNC_PIN and SYSREF_MUX to Normal SYNC,
7476181baa1SLiam Beguin * and clear SYSREF_REQ_EN (see 6.)
7486181baa1SLiam Beguin */
7496181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT,
7506181baa1SLiam Beguin LMK04832_BIT_SYSREF_REQ_EN |
7516181baa1SLiam Beguin LMK04832_BIT_SYSREF_MUX,
7526181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYSREF_REQ_EN, 0) |
7536181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYSREF_MUX,
7546181baa1SLiam Beguin LMK04832_VAL_SYSREF_MUX_NORMAL_SYNC));
7556181baa1SLiam Beguin if (ret)
7566181baa1SLiam Beguin return ret;
7576181baa1SLiam Beguin
7586181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
7596181baa1SLiam Beguin LMK04832_BIT_SYNC_MODE,
7606181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_MODE,
7616181baa1SLiam Beguin LMK04832_VAL_SYNC_MODE_ON));
7626181baa1SLiam Beguin if (ret)
7636181baa1SLiam Beguin return ret;
7646181baa1SLiam Beguin
7656181baa1SLiam Beguin /* 4. Clear SYNXC_DISx or applicable clocks and clear SYNC_DISSYSREF */
7666181baa1SLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0x00);
7676181baa1SLiam Beguin if (ret)
7686181baa1SLiam Beguin return ret;
7696181baa1SLiam Beguin
7706181baa1SLiam Beguin /*
7716181baa1SLiam Beguin * 5. If SCLKX_Y_DDLY != 0, Set SYSREF_CLR=1 for at least 15 clock
7726181baa1SLiam Beguin * distribution path cycles (VCO cycles), then back to 0. In
7736181baa1SLiam Beguin * PLL2-only use case, this will be complete in less than one SPI
7746181baa1SLiam Beguin * transaction. If SYSREF local digital delay is not used, this step
7756181baa1SLiam Beguin * can be skipped.
7766181baa1SLiam Beguin */
7776181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
7786181baa1SLiam Beguin LMK04832_BIT_SYNC_CLR,
7796181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_CLR, 0x01));
7806181baa1SLiam Beguin if (ret)
7816181baa1SLiam Beguin return ret;
7826181baa1SLiam Beguin
7836181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
7846181baa1SLiam Beguin LMK04832_BIT_SYNC_CLR,
7856181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_CLR, 0x00));
7866181baa1SLiam Beguin if (ret)
7876181baa1SLiam Beguin return ret;
7886181baa1SLiam Beguin
7896181baa1SLiam Beguin /*
7906181baa1SLiam Beguin * 6. Toggle SYNC_POL state between inverted and not inverted.
7916181baa1SLiam Beguin * If you use an external signal on the SYNC pin instead of toggling
7926181baa1SLiam Beguin * SYNC_POL, make sure that SYSREF_REQ_EN=0 so that the SYSREF_MUX
7936181baa1SLiam Beguin * does not shift into continuous SYSREF mode.
7946181baa1SLiam Beguin */
7956181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
7966181baa1SLiam Beguin LMK04832_BIT_SYNC_POL,
7976181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_POL, 0x01));
7986181baa1SLiam Beguin if (ret)
7996181baa1SLiam Beguin return ret;
8006181baa1SLiam Beguin
8016181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
8026181baa1SLiam Beguin LMK04832_BIT_SYNC_POL,
8036181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_POL, 0x00));
8046181baa1SLiam Beguin if (ret)
8056181baa1SLiam Beguin return ret;
8066181baa1SLiam Beguin
8076181baa1SLiam Beguin /* 7. Set all SYNC_DISx=1, including SYNC_DISSYSREF */
8086181baa1SLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0xff);
8096181baa1SLiam Beguin if (ret)
8106181baa1SLiam Beguin return ret;
8116181baa1SLiam Beguin
8126181baa1SLiam Beguin /* 8. Restore state of SYNC_MODE and SYSREF_MUX to desired values */
8136181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT,
8146181baa1SLiam Beguin LMK04832_BIT_SYSREF_MUX,
8156181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYSREF_MUX,
8166181baa1SLiam Beguin lmk->sysref_mux));
8176181baa1SLiam Beguin if (ret)
8186181baa1SLiam Beguin return ret;
8196181baa1SLiam Beguin
8206181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
8216181baa1SLiam Beguin LMK04832_BIT_SYNC_MODE,
8226181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_MODE,
8236181baa1SLiam Beguin lmk->sync_mode));
8246181baa1SLiam Beguin if (ret)
8256181baa1SLiam Beguin return ret;
8266181baa1SLiam Beguin
8276181baa1SLiam Beguin /*
8286181baa1SLiam Beguin * 9. (optional) if SCLKx_y_DIS_MODE was used to mute SYSREF outputs
8296181baa1SLiam Beguin * during the SYNC event, restore SCLKx_y_DIS_MODE=0 for active state,
8306181baa1SLiam Beguin * or set SYSREF_GBL_PD=0 if SCLKx_y_DIS_MODE is set to a conditional
8316181baa1SLiam Beguin * option.
8326181baa1SLiam Beguin */
8336181baa1SLiam Beguin
8346181baa1SLiam Beguin /*
8356181baa1SLiam Beguin * 10. (optional) To reduce power consumption, after the synchronization
8366181baa1SLiam Beguin * event is complete, DCLKx_y_DDLY_PD=1 and SYSREF_DDLY_PD=1 disable the
8376181baa1SLiam Beguin * digital delay counters (which are only used immediately after the
8386181baa1SLiam Beguin * SYNC pulse to delay the output by some number of VCO counts).
8396181baa1SLiam Beguin */
8406181baa1SLiam Beguin
8416181baa1SLiam Beguin return ret;
8426181baa1SLiam Beguin }
8436181baa1SLiam Beguin
lmk04832_sclk_is_enabled(struct clk_hw * hw)8443bc61cfdSLiam Beguin static int lmk04832_sclk_is_enabled(struct clk_hw *hw)
8453bc61cfdSLiam Beguin {
8463bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk);
8473bc61cfdSLiam Beguin unsigned int tmp;
8483bc61cfdSLiam Beguin int ret;
8493bc61cfdSLiam Beguin
8503bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_MAIN_PD, &tmp);
8513bc61cfdSLiam Beguin if (ret)
8523bc61cfdSLiam Beguin return ret;
8533bc61cfdSLiam Beguin
8543bc61cfdSLiam Beguin return FIELD_GET(LMK04832_BIT_SYSREF_PD, tmp);
8553bc61cfdSLiam Beguin }
8563bc61cfdSLiam Beguin
lmk04832_sclk_prepare(struct clk_hw * hw)8573bc61cfdSLiam Beguin static int lmk04832_sclk_prepare(struct clk_hw *hw)
8583bc61cfdSLiam Beguin {
8593bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk);
8603bc61cfdSLiam Beguin
8613bc61cfdSLiam Beguin return regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD,
8623bc61cfdSLiam Beguin LMK04832_BIT_SYSREF_PD, 0x00);
8633bc61cfdSLiam Beguin }
8643bc61cfdSLiam Beguin
lmk04832_sclk_unprepare(struct clk_hw * hw)8653bc61cfdSLiam Beguin static void lmk04832_sclk_unprepare(struct clk_hw *hw)
8663bc61cfdSLiam Beguin {
8673bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk);
8683bc61cfdSLiam Beguin
8693bc61cfdSLiam Beguin regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD,
8703bc61cfdSLiam Beguin LMK04832_BIT_SYSREF_PD, LMK04832_BIT_SYSREF_PD);
8713bc61cfdSLiam Beguin }
8723bc61cfdSLiam Beguin
lmk04832_sclk_recalc_rate(struct clk_hw * hw,unsigned long prate)8733bc61cfdSLiam Beguin static unsigned long lmk04832_sclk_recalc_rate(struct clk_hw *hw,
8743bc61cfdSLiam Beguin unsigned long prate)
8753bc61cfdSLiam Beguin {
8763bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk);
8773bc61cfdSLiam Beguin unsigned int sysref_div;
8783bc61cfdSLiam Beguin u8 tmp[2];
8793bc61cfdSLiam Beguin int ret;
8803bc61cfdSLiam Beguin
8813bc61cfdSLiam Beguin ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_SYSREF_DIV_MSB, &tmp, 2);
8823bc61cfdSLiam Beguin if (ret)
8833bc61cfdSLiam Beguin return ret;
8843bc61cfdSLiam Beguin
8853bc61cfdSLiam Beguin sysref_div = FIELD_GET(LMK04832_BIT_SYSREF_DIV_MSB, tmp[0]) << 8 |
8863bc61cfdSLiam Beguin tmp[1];
8873bc61cfdSLiam Beguin
8883bc61cfdSLiam Beguin return DIV_ROUND_CLOSEST(prate, sysref_div);
8893bc61cfdSLiam Beguin }
8903bc61cfdSLiam Beguin
lmk04832_sclk_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)8913bc61cfdSLiam Beguin static long lmk04832_sclk_round_rate(struct clk_hw *hw, unsigned long rate,
8923bc61cfdSLiam Beguin unsigned long *prate)
8933bc61cfdSLiam Beguin {
8943bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk);
8953bc61cfdSLiam Beguin unsigned long sclk_rate;
8963bc61cfdSLiam Beguin unsigned int sysref_div;
8973bc61cfdSLiam Beguin
8983bc61cfdSLiam Beguin sysref_div = DIV_ROUND_CLOSEST(*prate, rate);
8993bc61cfdSLiam Beguin sclk_rate = DIV_ROUND_CLOSEST(*prate, sysref_div);
9003bc61cfdSLiam Beguin
9013bc61cfdSLiam Beguin if (sysref_div < 0x07 || sysref_div > 0x1fff) {
9023bc61cfdSLiam Beguin dev_err(lmk->dev, "SYSREF divider out of range\n");
9033bc61cfdSLiam Beguin return -EINVAL;
9043bc61cfdSLiam Beguin }
9053bc61cfdSLiam Beguin
9063bc61cfdSLiam Beguin if (rate != sclk_rate)
9073bc61cfdSLiam Beguin return -EINVAL;
9083bc61cfdSLiam Beguin
9093bc61cfdSLiam Beguin return sclk_rate;
9103bc61cfdSLiam Beguin }
9113bc61cfdSLiam Beguin
lmk04832_sclk_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long prate)9123bc61cfdSLiam Beguin static int lmk04832_sclk_set_rate(struct clk_hw *hw, unsigned long rate,
9133bc61cfdSLiam Beguin unsigned long prate)
9143bc61cfdSLiam Beguin {
9153bc61cfdSLiam Beguin struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk);
9163bc61cfdSLiam Beguin unsigned int sysref_div;
9173bc61cfdSLiam Beguin int ret;
9183bc61cfdSLiam Beguin
9193bc61cfdSLiam Beguin sysref_div = DIV_ROUND_CLOSEST(prate, rate);
9203bc61cfdSLiam Beguin
9213bc61cfdSLiam Beguin if (sysref_div < 0x07 || sysref_div > 0x1fff) {
9223bc61cfdSLiam Beguin dev_err(lmk->dev, "SYSREF divider out of range\n");
9233bc61cfdSLiam Beguin return -EINVAL;
9243bc61cfdSLiam Beguin }
9253bc61cfdSLiam Beguin
9263bc61cfdSLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DIV_MSB,
9273bc61cfdSLiam Beguin FIELD_GET(0x1f00, sysref_div));
9283bc61cfdSLiam Beguin if (ret)
9293bc61cfdSLiam Beguin return ret;
9303bc61cfdSLiam Beguin
9316181baa1SLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DIV_LSB,
9323bc61cfdSLiam Beguin FIELD_GET(0x00ff, sysref_div));
9336181baa1SLiam Beguin if (ret)
9346181baa1SLiam Beguin return ret;
9356181baa1SLiam Beguin
9366181baa1SLiam Beguin ret = lmk04832_sclk_sync_sequence(lmk);
9376181baa1SLiam Beguin if (ret)
9386181baa1SLiam Beguin dev_err(lmk->dev, "SYNC sequence failed\n");
9396181baa1SLiam Beguin
9406181baa1SLiam Beguin return ret;
9413bc61cfdSLiam Beguin }
9423bc61cfdSLiam Beguin
9433bc61cfdSLiam Beguin static const struct clk_ops lmk04832_sclk_ops = {
9443bc61cfdSLiam Beguin .is_enabled = lmk04832_sclk_is_enabled,
9453bc61cfdSLiam Beguin .prepare = lmk04832_sclk_prepare,
9463bc61cfdSLiam Beguin .unprepare = lmk04832_sclk_unprepare,
9473bc61cfdSLiam Beguin .recalc_rate = lmk04832_sclk_recalc_rate,
9483bc61cfdSLiam Beguin .round_rate = lmk04832_sclk_round_rate,
9493bc61cfdSLiam Beguin .set_rate = lmk04832_sclk_set_rate,
9503bc61cfdSLiam Beguin };
9513bc61cfdSLiam Beguin
lmk04832_register_sclk(struct lmk04832 * lmk)9523bc61cfdSLiam Beguin static int lmk04832_register_sclk(struct lmk04832 *lmk)
9533bc61cfdSLiam Beguin {
9543bc61cfdSLiam Beguin const char *parent_names[1];
9553bc61cfdSLiam Beguin struct clk_init_data init;
9563bc61cfdSLiam Beguin int ret;
9573bc61cfdSLiam Beguin
9583bc61cfdSLiam Beguin init.name = "lmk-sclk";
9593bc61cfdSLiam Beguin parent_names[0] = clk_hw_get_name(&lmk->vco);
9603bc61cfdSLiam Beguin init.parent_names = parent_names;
9613bc61cfdSLiam Beguin
9623bc61cfdSLiam Beguin init.ops = &lmk04832_sclk_ops;
9633bc61cfdSLiam Beguin init.flags = CLK_SET_RATE_PARENT;
9643bc61cfdSLiam Beguin init.num_parents = 1;
9653bc61cfdSLiam Beguin
9663bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT,
9673bc61cfdSLiam Beguin LMK04832_BIT_SYSREF_MUX,
9683bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_SYSREF_MUX,
9696181baa1SLiam Beguin lmk->sysref_mux));
9706181baa1SLiam Beguin if (ret)
9716181baa1SLiam Beguin return ret;
9726181baa1SLiam Beguin
9736181baa1SLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DDLY_LSB,
9746181baa1SLiam Beguin FIELD_GET(0x00ff, lmk->sysref_ddly));
9756181baa1SLiam Beguin if (ret)
9766181baa1SLiam Beguin return ret;
9776181baa1SLiam Beguin
9786181baa1SLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DDLY_MSB,
9796181baa1SLiam Beguin FIELD_GET(0x1f00, lmk->sysref_ddly));
9806181baa1SLiam Beguin if (ret)
9816181baa1SLiam Beguin return ret;
9826181baa1SLiam Beguin
9836181baa1SLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_PULSE_CNT,
9846181baa1SLiam Beguin ilog2(lmk->sysref_pulse_cnt));
9853bc61cfdSLiam Beguin if (ret)
9863bc61cfdSLiam Beguin return ret;
9873bc61cfdSLiam Beguin
9883bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD,
9896181baa1SLiam Beguin LMK04832_BIT_SYSREF_DDLY_PD |
9903bc61cfdSLiam Beguin LMK04832_BIT_SYSREF_PLSR_PD,
9916181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYSREF_DDLY_PD, 0) |
9926181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYSREF_PLSR_PD, 0));
9933bc61cfdSLiam Beguin if (ret)
9943bc61cfdSLiam Beguin return ret;
9953bc61cfdSLiam Beguin
9966181baa1SLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC,
9976181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_POL, 0) |
9986181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_EN, 1) |
9996181baa1SLiam Beguin FIELD_PREP(LMK04832_BIT_SYNC_MODE, lmk->sync_mode));
10003bc61cfdSLiam Beguin if (ret)
10013bc61cfdSLiam Beguin return ret;
10023bc61cfdSLiam Beguin
10033bc61cfdSLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0xff);
10043bc61cfdSLiam Beguin if (ret)
10053bc61cfdSLiam Beguin return ret;
10063bc61cfdSLiam Beguin
10073bc61cfdSLiam Beguin lmk->sclk.init = &init;
10083bc61cfdSLiam Beguin return devm_clk_hw_register(lmk->dev, &lmk->sclk);
10093bc61cfdSLiam Beguin }
10103bc61cfdSLiam Beguin
lmk04832_dclk_is_enabled(struct clk_hw * hw)10113bc61cfdSLiam Beguin static int lmk04832_dclk_is_enabled(struct clk_hw *hw)
10123bc61cfdSLiam Beguin {
10133bc61cfdSLiam Beguin struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw);
10143bc61cfdSLiam Beguin struct lmk04832 *lmk = dclk->lmk;
10153bc61cfdSLiam Beguin unsigned int tmp;
10163bc61cfdSLiam Beguin int ret;
10173bc61cfdSLiam Beguin
10183bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL3(dclk->id),
10193bc61cfdSLiam Beguin &tmp);
10203bc61cfdSLiam Beguin if (ret)
10213bc61cfdSLiam Beguin return ret;
10223bc61cfdSLiam Beguin
10233bc61cfdSLiam Beguin return !FIELD_GET(LMK04832_BIT_DCLKX_Y_PD, tmp);
10243bc61cfdSLiam Beguin }
10253bc61cfdSLiam Beguin
lmk04832_dclk_prepare(struct clk_hw * hw)10263bc61cfdSLiam Beguin static int lmk04832_dclk_prepare(struct clk_hw *hw)
10273bc61cfdSLiam Beguin {
10283bc61cfdSLiam Beguin struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw);
10293bc61cfdSLiam Beguin struct lmk04832 *lmk = dclk->lmk;
10303bc61cfdSLiam Beguin
10313bc61cfdSLiam Beguin return regmap_update_bits(lmk->regmap,
10323bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_CTRL3(dclk->id),
10333bc61cfdSLiam Beguin LMK04832_BIT_DCLKX_Y_PD, 0x00);
10343bc61cfdSLiam Beguin }
10353bc61cfdSLiam Beguin
lmk04832_dclk_unprepare(struct clk_hw * hw)10363bc61cfdSLiam Beguin static void lmk04832_dclk_unprepare(struct clk_hw *hw)
10373bc61cfdSLiam Beguin {
10383bc61cfdSLiam Beguin struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw);
10393bc61cfdSLiam Beguin struct lmk04832 *lmk = dclk->lmk;
10403bc61cfdSLiam Beguin
10413bc61cfdSLiam Beguin regmap_update_bits(lmk->regmap,
10423bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_CTRL3(dclk->id),
10433bc61cfdSLiam Beguin LMK04832_BIT_DCLKX_Y_PD, 0xff);
10443bc61cfdSLiam Beguin }
10453bc61cfdSLiam Beguin
lmk04832_dclk_recalc_rate(struct clk_hw * hw,unsigned long prate)10463bc61cfdSLiam Beguin static unsigned long lmk04832_dclk_recalc_rate(struct clk_hw *hw,
10473bc61cfdSLiam Beguin unsigned long prate)
10483bc61cfdSLiam Beguin {
10493bc61cfdSLiam Beguin struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw);
10503bc61cfdSLiam Beguin struct lmk04832 *lmk = dclk->lmk;
10513bc61cfdSLiam Beguin unsigned int dclk_div;
10523bc61cfdSLiam Beguin unsigned int lsb, msb;
10533bc61cfdSLiam Beguin unsigned long rate;
10543bc61cfdSLiam Beguin int ret;
10553bc61cfdSLiam Beguin
10563bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(dclk->id),
10573bc61cfdSLiam Beguin &lsb);
10583bc61cfdSLiam Beguin if (ret)
10593bc61cfdSLiam Beguin return ret;
10603bc61cfdSLiam Beguin
10613bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(dclk->id),
10623bc61cfdSLiam Beguin &msb);
10633bc61cfdSLiam Beguin if (ret)
10643bc61cfdSLiam Beguin return ret;
10653bc61cfdSLiam Beguin
10663bc61cfdSLiam Beguin dclk_div = FIELD_GET(LMK04832_BIT_DCLK_DIV_MSB, msb) << 8 | lsb;
10673bc61cfdSLiam Beguin rate = DIV_ROUND_CLOSEST(prate, dclk_div);
10683bc61cfdSLiam Beguin
10693bc61cfdSLiam Beguin return rate;
1070992a3552SLiam Beguin }
10713bc61cfdSLiam Beguin
lmk04832_dclk_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)10723bc61cfdSLiam Beguin static long lmk04832_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
10733bc61cfdSLiam Beguin unsigned long *prate)
10743bc61cfdSLiam Beguin {
10753bc61cfdSLiam Beguin struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw);
10763bc61cfdSLiam Beguin struct lmk04832 *lmk = dclk->lmk;
10773bc61cfdSLiam Beguin unsigned long dclk_rate;
10783bc61cfdSLiam Beguin unsigned int dclk_div;
10793bc61cfdSLiam Beguin
10803bc61cfdSLiam Beguin dclk_div = DIV_ROUND_CLOSEST(*prate, rate);
10813bc61cfdSLiam Beguin dclk_rate = DIV_ROUND_CLOSEST(*prate, dclk_div);
10823bc61cfdSLiam Beguin
10833bc61cfdSLiam Beguin if (dclk_div < 1 || dclk_div > 0x3ff) {
10843bc61cfdSLiam Beguin dev_err(lmk->dev, "%s_div out of range\n", clk_hw_get_name(hw));
10853bc61cfdSLiam Beguin return -EINVAL;
10863bc61cfdSLiam Beguin }
10873bc61cfdSLiam Beguin
10883bc61cfdSLiam Beguin if (rate != dclk_rate)
10893bc61cfdSLiam Beguin return -EINVAL;
10903bc61cfdSLiam Beguin
10913bc61cfdSLiam Beguin return dclk_rate;
1092992a3552SLiam Beguin }
10933bc61cfdSLiam Beguin
lmk04832_dclk_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long prate)10943bc61cfdSLiam Beguin static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
10953bc61cfdSLiam Beguin unsigned long prate)
10963bc61cfdSLiam Beguin {
10973bc61cfdSLiam Beguin struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw);
10983bc61cfdSLiam Beguin struct lmk04832 *lmk = dclk->lmk;
10993bc61cfdSLiam Beguin unsigned int dclk_div;
11003bc61cfdSLiam Beguin int ret;
11013bc61cfdSLiam Beguin
11023bc61cfdSLiam Beguin dclk_div = DIV_ROUND_CLOSEST(prate, rate);
11033bc61cfdSLiam Beguin
11043bc61cfdSLiam Beguin if (dclk_div > 0x3ff) {
11053bc61cfdSLiam Beguin dev_err(lmk->dev, "%s_div out of range\n", clk_hw_get_name(hw));
11063bc61cfdSLiam Beguin return -EINVAL;
11073bc61cfdSLiam Beguin }
11083bc61cfdSLiam Beguin
11092cdee50eSColin Ian King /* Enable Duty Cycle Correction */
11103bc61cfdSLiam Beguin if (dclk_div == 1) {
11113bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap,
11123bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_CTRL3(dclk->id),
11133bc61cfdSLiam Beguin LMK04832_BIT_DCLKX_Y_DCC,
11143bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_DCLKX_Y_DCC, 1));
11153bc61cfdSLiam Beguin if (ret)
11163bc61cfdSLiam Beguin return ret;
11173bc61cfdSLiam Beguin }
11183bc61cfdSLiam Beguin
11196181baa1SLiam Beguin /*
11206181baa1SLiam Beguin * While using Divide-by-2 or Divide-by-3 for DCLK_X_Y_DIV, SYNC
11216181baa1SLiam Beguin * procedure requires to first program Divide-by-4 and then back to
11226181baa1SLiam Beguin * Divide-by-2 or Divide-by-3 before doing SYNC.
11236181baa1SLiam Beguin */
11246181baa1SLiam Beguin if (dclk_div == 2 || dclk_div == 3) {
11256181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap,
11266181baa1SLiam Beguin LMK04832_REG_CLKOUT_CTRL2(dclk->id),
11276181baa1SLiam Beguin LMK04832_BIT_DCLK_DIV_MSB, 0x00);
11286181baa1SLiam Beguin if (ret)
11296181baa1SLiam Beguin return ret;
11306181baa1SLiam Beguin
11316181baa1SLiam Beguin ret = regmap_write(lmk->regmap,
11326181baa1SLiam Beguin LMK04832_REG_CLKOUT_CTRL0(dclk->id), 0x04);
11336181baa1SLiam Beguin if (ret)
11346181baa1SLiam Beguin return ret;
11356181baa1SLiam Beguin }
11366181baa1SLiam Beguin
11373bc61cfdSLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(dclk->id),
11383bc61cfdSLiam Beguin FIELD_GET(0x0ff, dclk_div));
11393bc61cfdSLiam Beguin if (ret)
11403bc61cfdSLiam Beguin return ret;
11413bc61cfdSLiam Beguin
11426181baa1SLiam Beguin ret = regmap_update_bits(lmk->regmap,
11433bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_CTRL2(dclk->id),
11443bc61cfdSLiam Beguin LMK04832_BIT_DCLK_DIV_MSB,
11453bc61cfdSLiam Beguin FIELD_GET(0x300, dclk_div));
11466181baa1SLiam Beguin if (ret)
11476181baa1SLiam Beguin return ret;
11486181baa1SLiam Beguin
11496181baa1SLiam Beguin ret = lmk04832_sclk_sync_sequence(lmk);
11506181baa1SLiam Beguin if (ret)
11516181baa1SLiam Beguin dev_err(lmk->dev, "SYNC sequence failed\n");
11526181baa1SLiam Beguin
11536181baa1SLiam Beguin return ret;
1154992a3552SLiam Beguin }
11553bc61cfdSLiam Beguin
11563bc61cfdSLiam Beguin static const struct clk_ops lmk04832_dclk_ops = {
11573bc61cfdSLiam Beguin .is_enabled = lmk04832_dclk_is_enabled,
11583bc61cfdSLiam Beguin .prepare = lmk04832_dclk_prepare,
11593bc61cfdSLiam Beguin .unprepare = lmk04832_dclk_unprepare,
11603bc61cfdSLiam Beguin .recalc_rate = lmk04832_dclk_recalc_rate,
11613bc61cfdSLiam Beguin .round_rate = lmk04832_dclk_round_rate,
11623bc61cfdSLiam Beguin .set_rate = lmk04832_dclk_set_rate,
11633bc61cfdSLiam Beguin };
11643bc61cfdSLiam Beguin
lmk04832_clkout_is_enabled(struct clk_hw * hw)11653bc61cfdSLiam Beguin static int lmk04832_clkout_is_enabled(struct clk_hw *hw)
11663bc61cfdSLiam Beguin {
11673bc61cfdSLiam Beguin struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw);
11683bc61cfdSLiam Beguin struct lmk04832 *lmk = clkout->lmk;
11693bc61cfdSLiam Beguin unsigned int clkoutx_y_pd;
11703bc61cfdSLiam Beguin unsigned int sclkx_y_pd;
11713bc61cfdSLiam Beguin unsigned int tmp;
11723bc61cfdSLiam Beguin u32 enabled;
11733bc61cfdSLiam Beguin int ret;
11743bc61cfdSLiam Beguin u8 fmt;
11753bc61cfdSLiam Beguin
11763bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(clkout->id),
11773bc61cfdSLiam Beguin &clkoutx_y_pd);
11783bc61cfdSLiam Beguin if (ret)
11793bc61cfdSLiam Beguin return ret;
11803bc61cfdSLiam Beguin
11813bc61cfdSLiam Beguin enabled = !FIELD_GET(LMK04832_BIT_CLKOUTX_Y_PD, clkoutx_y_pd);
11823bc61cfdSLiam Beguin
11833bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id),
11843bc61cfdSLiam Beguin &tmp);
11853bc61cfdSLiam Beguin if (ret)
11863bc61cfdSLiam Beguin return ret;
11873bc61cfdSLiam Beguin
11883bc61cfdSLiam Beguin if (FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp)) {
11893bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap,
11903bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_CTRL4(clkout->id),
11913bc61cfdSLiam Beguin &sclkx_y_pd);
11923bc61cfdSLiam Beguin if (ret)
11933bc61cfdSLiam Beguin return ret;
11943bc61cfdSLiam Beguin
11953bc61cfdSLiam Beguin enabled = enabled && !FIELD_GET(LMK04832_BIT_SCLK_PD, sclkx_y_pd);
11963bc61cfdSLiam Beguin }
11973bc61cfdSLiam Beguin
11983bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_FMT(clkout->id),
11993bc61cfdSLiam Beguin &tmp);
12003bc61cfdSLiam Beguin if (ret)
12013bc61cfdSLiam Beguin return ret;
12023bc61cfdSLiam Beguin
12033bc61cfdSLiam Beguin if (clkout->id % 2)
12043bc61cfdSLiam Beguin fmt = FIELD_GET(0xf0, tmp);
12053bc61cfdSLiam Beguin else
12063bc61cfdSLiam Beguin fmt = FIELD_GET(0x0f, tmp);
12073bc61cfdSLiam Beguin
12083bc61cfdSLiam Beguin return enabled && !fmt;
12093bc61cfdSLiam Beguin }
12103bc61cfdSLiam Beguin
lmk04832_clkout_prepare(struct clk_hw * hw)12113bc61cfdSLiam Beguin static int lmk04832_clkout_prepare(struct clk_hw *hw)
12123bc61cfdSLiam Beguin {
12133bc61cfdSLiam Beguin struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw);
12143bc61cfdSLiam Beguin struct lmk04832 *lmk = clkout->lmk;
12153bc61cfdSLiam Beguin unsigned int tmp;
12163bc61cfdSLiam Beguin int ret;
12173bc61cfdSLiam Beguin
12183bc61cfdSLiam Beguin if (clkout->format == LMK04832_VAL_CLKOUT_FMT_POWERDOWN)
12193bc61cfdSLiam Beguin dev_err(lmk->dev, "prepared %s but format is powerdown\n",
12203bc61cfdSLiam Beguin clk_hw_get_name(hw));
12213bc61cfdSLiam Beguin
12223bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap,
12233bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_CTRL2(clkout->id),
12243bc61cfdSLiam Beguin LMK04832_BIT_CLKOUTX_Y_PD, 0x00);
12253bc61cfdSLiam Beguin if (ret)
12263bc61cfdSLiam Beguin return ret;
12273bc61cfdSLiam Beguin
12283bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id),
12293bc61cfdSLiam Beguin &tmp);
12303bc61cfdSLiam Beguin if (ret)
12313bc61cfdSLiam Beguin return ret;
12323bc61cfdSLiam Beguin
12333bc61cfdSLiam Beguin if (FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp)) {
12343bc61cfdSLiam Beguin ret = regmap_update_bits(lmk->regmap,
12353bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_CTRL4(clkout->id),
12363bc61cfdSLiam Beguin LMK04832_BIT_SCLK_PD, 0x00);
12373bc61cfdSLiam Beguin if (ret)
12383bc61cfdSLiam Beguin return ret;
12393bc61cfdSLiam Beguin }
12403bc61cfdSLiam Beguin
12413bc61cfdSLiam Beguin return regmap_update_bits(lmk->regmap,
12423bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_FMT(clkout->id),
12433bc61cfdSLiam Beguin LMK04832_BIT_CLKOUT_FMT(clkout->id),
12443bc61cfdSLiam Beguin clkout->format << 4 * (clkout->id % 2));
12453bc61cfdSLiam Beguin }
12463bc61cfdSLiam Beguin
lmk04832_clkout_unprepare(struct clk_hw * hw)12473bc61cfdSLiam Beguin static void lmk04832_clkout_unprepare(struct clk_hw *hw)
12483bc61cfdSLiam Beguin {
12493bc61cfdSLiam Beguin struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw);
12503bc61cfdSLiam Beguin struct lmk04832 *lmk = clkout->lmk;
12513bc61cfdSLiam Beguin
12523bc61cfdSLiam Beguin regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_FMT(clkout->id),
12533bc61cfdSLiam Beguin LMK04832_BIT_CLKOUT_FMT(clkout->id),
12543bc61cfdSLiam Beguin 0x00);
12553bc61cfdSLiam Beguin }
12563bc61cfdSLiam Beguin
lmk04832_clkout_set_parent(struct clk_hw * hw,uint8_t index)12573bc61cfdSLiam Beguin static int lmk04832_clkout_set_parent(struct clk_hw *hw, uint8_t index)
12583bc61cfdSLiam Beguin {
12593bc61cfdSLiam Beguin struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw);
12603bc61cfdSLiam Beguin struct lmk04832 *lmk = clkout->lmk;
12613bc61cfdSLiam Beguin
12623bc61cfdSLiam Beguin return regmap_update_bits(lmk->regmap,
12633bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_SRC_MUX(clkout->id),
12643bc61cfdSLiam Beguin LMK04832_BIT_CLKOUT_SRC_MUX,
12653bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_CLKOUT_SRC_MUX,
12663bc61cfdSLiam Beguin index));
12673bc61cfdSLiam Beguin }
12683bc61cfdSLiam Beguin
lmk04832_clkout_get_parent(struct clk_hw * hw)12693bc61cfdSLiam Beguin static uint8_t lmk04832_clkout_get_parent(struct clk_hw *hw)
12703bc61cfdSLiam Beguin {
12713bc61cfdSLiam Beguin struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw);
12723bc61cfdSLiam Beguin struct lmk04832 *lmk = clkout->lmk;
12733bc61cfdSLiam Beguin unsigned int tmp;
12743bc61cfdSLiam Beguin int ret;
12753bc61cfdSLiam Beguin
12763bc61cfdSLiam Beguin ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id),
12773bc61cfdSLiam Beguin &tmp);
12783bc61cfdSLiam Beguin if (ret)
12793bc61cfdSLiam Beguin return ret;
12803bc61cfdSLiam Beguin
12813bc61cfdSLiam Beguin return FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp);
12823bc61cfdSLiam Beguin }
12833bc61cfdSLiam Beguin
12843bc61cfdSLiam Beguin static const struct clk_ops lmk04832_clkout_ops = {
12853bc61cfdSLiam Beguin .is_enabled = lmk04832_clkout_is_enabled,
12863bc61cfdSLiam Beguin .prepare = lmk04832_clkout_prepare,
12873bc61cfdSLiam Beguin .unprepare = lmk04832_clkout_unprepare,
128838bdfb21SMaxime Ripard .determine_rate = __clk_mux_determine_rate,
12893bc61cfdSLiam Beguin .set_parent = lmk04832_clkout_set_parent,
12903bc61cfdSLiam Beguin .get_parent = lmk04832_clkout_get_parent,
12913bc61cfdSLiam Beguin };
12923bc61cfdSLiam Beguin
lmk04832_register_clkout(struct lmk04832 * lmk,const int num)12933bc61cfdSLiam Beguin static int lmk04832_register_clkout(struct lmk04832 *lmk, const int num)
12943bc61cfdSLiam Beguin {
12953bc61cfdSLiam Beguin char name[] = "lmk-clkoutXX";
12963bc61cfdSLiam Beguin char dclk_name[] = "lmk-dclkXX_YY";
12973bc61cfdSLiam Beguin const char *parent_names[2];
12983bc61cfdSLiam Beguin struct clk_init_data init;
12993bc61cfdSLiam Beguin int dclk_num = num / 2;
13003bc61cfdSLiam Beguin int ret;
13013bc61cfdSLiam Beguin
13023bc61cfdSLiam Beguin if (num % 2 == 0) {
13033bc61cfdSLiam Beguin sprintf(dclk_name, "lmk-dclk%02d_%02d", num, num + 1);
13043bc61cfdSLiam Beguin init.name = dclk_name;
13053bc61cfdSLiam Beguin parent_names[0] = clk_hw_get_name(&lmk->vco);
1306f6d6c11fSMike Looijmans init.parent_names = parent_names;
13073bc61cfdSLiam Beguin init.ops = &lmk04832_dclk_ops;
13083bc61cfdSLiam Beguin init.flags = CLK_SET_RATE_PARENT;
13093bc61cfdSLiam Beguin init.num_parents = 1;
13103bc61cfdSLiam Beguin
13113bc61cfdSLiam Beguin lmk->dclk[dclk_num].id = num;
13123bc61cfdSLiam Beguin lmk->dclk[dclk_num].lmk = lmk;
13133bc61cfdSLiam Beguin lmk->dclk[dclk_num].hw.init = &init;
13143bc61cfdSLiam Beguin
13153bc61cfdSLiam Beguin ret = devm_clk_hw_register(lmk->dev, &lmk->dclk[dclk_num].hw);
13163bc61cfdSLiam Beguin if (ret)
13173bc61cfdSLiam Beguin return ret;
13183bc61cfdSLiam Beguin } else {
13193bc61cfdSLiam Beguin sprintf(dclk_name, "lmk-dclk%02d_%02d", num - 1, num);
13203bc61cfdSLiam Beguin }
13213bc61cfdSLiam Beguin
13223bc61cfdSLiam Beguin if (of_property_read_string_index(lmk->dev->of_node,
13233bc61cfdSLiam Beguin "clock-output-names",
13243bc61cfdSLiam Beguin num, &init.name)) {
13253bc61cfdSLiam Beguin sprintf(name, "lmk-clkout%02d", num);
13263bc61cfdSLiam Beguin init.name = name;
13273bc61cfdSLiam Beguin }
13283bc61cfdSLiam Beguin
13293bc61cfdSLiam Beguin parent_names[0] = dclk_name;
13303bc61cfdSLiam Beguin parent_names[1] = clk_hw_get_name(&lmk->sclk);
13313bc61cfdSLiam Beguin init.parent_names = parent_names;
13323bc61cfdSLiam Beguin init.ops = &lmk04832_clkout_ops;
13333bc61cfdSLiam Beguin init.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT;
13343bc61cfdSLiam Beguin init.num_parents = ARRAY_SIZE(parent_names);
13353bc61cfdSLiam Beguin
13363bc61cfdSLiam Beguin lmk->clkout[num].id = num;
13373bc61cfdSLiam Beguin lmk->clkout[num].lmk = lmk;
13383bc61cfdSLiam Beguin lmk->clkout[num].hw.init = &init;
13393bc61cfdSLiam Beguin lmk->clk_data->hws[num] = &lmk->clkout[num].hw;
13403bc61cfdSLiam Beguin
13413bc61cfdSLiam Beguin /* Set initial parent */
13423bc61cfdSLiam Beguin regmap_update_bits(lmk->regmap,
13433bc61cfdSLiam Beguin LMK04832_REG_CLKOUT_SRC_MUX(num),
13443bc61cfdSLiam Beguin LMK04832_BIT_CLKOUT_SRC_MUX,
13453bc61cfdSLiam Beguin FIELD_PREP(LMK04832_BIT_CLKOUT_SRC_MUX,
13463bc61cfdSLiam Beguin lmk->clkout[num].sysref));
13473bc61cfdSLiam Beguin
13483bc61cfdSLiam Beguin return devm_clk_hw_register(lmk->dev, &lmk->clkout[num].hw);
13493bc61cfdSLiam Beguin }
13503bc61cfdSLiam Beguin
lmk04832_set_spi_rdbk(const struct lmk04832 * lmk,const int rdbk_pin)13513bc61cfdSLiam Beguin static int lmk04832_set_spi_rdbk(const struct lmk04832 *lmk, const int rdbk_pin)
13523bc61cfdSLiam Beguin {
13533bc61cfdSLiam Beguin int reg;
13543bc61cfdSLiam Beguin int ret;
1355*6aa8dc69SMike Looijmans int val = FIELD_PREP(LMK04832_BIT_CLKIN_SEL_MUX,
1356*6aa8dc69SMike Looijmans LMK04832_VAL_CLKIN_SEL_MUX_SPI_RDBK) |
1357*6aa8dc69SMike Looijmans FIELD_PREP(LMK04832_BIT_CLKIN_SEL_TYPE,
1358*6aa8dc69SMike Looijmans LMK04832_VAL_CLKIN_SEL_TYPE_OUT);
13593bc61cfdSLiam Beguin
13603bc61cfdSLiam Beguin dev_info(lmk->dev, "setting up 4-wire mode\n");
13613bc61cfdSLiam Beguin ret = regmap_write(lmk->regmap, LMK04832_REG_RST3W,
13623bc61cfdSLiam Beguin LMK04832_BIT_SPI_3WIRE_DIS);
13633bc61cfdSLiam Beguin if (ret)
13643bc61cfdSLiam Beguin return ret;
13653bc61cfdSLiam Beguin
13663bc61cfdSLiam Beguin switch (rdbk_pin) {
13673bc61cfdSLiam Beguin case RDBK_CLKIN_SEL0:
13683bc61cfdSLiam Beguin reg = LMK04832_REG_CLKIN_SEL0;
13693bc61cfdSLiam Beguin break;
13703bc61cfdSLiam Beguin case RDBK_CLKIN_SEL1:
13713bc61cfdSLiam Beguin reg = LMK04832_REG_CLKIN_SEL1;
13723bc61cfdSLiam Beguin break;
13733bc61cfdSLiam Beguin case RDBK_RESET:
13743bc61cfdSLiam Beguin reg = LMK04832_REG_CLKIN_RST;
13753bc61cfdSLiam Beguin break;
1376*6aa8dc69SMike Looijmans case RDBK_PLL1_LD:
1377*6aa8dc69SMike Looijmans reg = LMK04832_REG_PLL1_LD;
1378*6aa8dc69SMike Looijmans val = FIELD_PREP(LMK04832_BIT_PLL1_LD_MUX,
1379*6aa8dc69SMike Looijmans LMK04832_VAL_PLL1_LD_MUX_SPI_RDBK) |
1380*6aa8dc69SMike Looijmans FIELD_PREP(LMK04832_BIT_PLL1_LD_TYPE,
1381*6aa8dc69SMike Looijmans LMK04832_VAL_PLL1_LD_TYPE_OUT_PP);
1382*6aa8dc69SMike Looijmans break;
13833bc61cfdSLiam Beguin default:
13843bc61cfdSLiam Beguin return -EINVAL;
13853bc61cfdSLiam Beguin }
13863bc61cfdSLiam Beguin
1387*6aa8dc69SMike Looijmans return regmap_write(lmk->regmap, reg, val);
13883bc61cfdSLiam Beguin }
13893bc61cfdSLiam Beguin
lmk04832_probe(struct spi_device * spi)13903bc61cfdSLiam Beguin static int lmk04832_probe(struct spi_device *spi)
13913bc61cfdSLiam Beguin {
13923bc61cfdSLiam Beguin const struct lmk04832_device_info *info;
13933bc61cfdSLiam Beguin int rdbk_pin = RDBK_CLKIN_SEL1;
13943bc61cfdSLiam Beguin struct device_node *child;
13953bc61cfdSLiam Beguin struct lmk04832 *lmk;
13963bc61cfdSLiam Beguin u8 tmp[3];
13973bc61cfdSLiam Beguin int ret;
13983bc61cfdSLiam Beguin int i;
13993bc61cfdSLiam Beguin
14003bc61cfdSLiam Beguin info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data];
14013bc61cfdSLiam Beguin
14023bc61cfdSLiam Beguin lmk = devm_kzalloc(&spi->dev, sizeof(struct lmk04832), GFP_KERNEL);
14033bc61cfdSLiam Beguin if (!lmk)
14043bc61cfdSLiam Beguin return -ENOMEM;
14053bc61cfdSLiam Beguin
14063bc61cfdSLiam Beguin lmk->dev = &spi->dev;
14073bc61cfdSLiam Beguin
14083bc61cfdSLiam Beguin lmk->oscin = devm_clk_get(lmk->dev, "oscin");
14093bc61cfdSLiam Beguin if (IS_ERR(lmk->oscin)) {
14103bc61cfdSLiam Beguin dev_err(lmk->dev, "failed to get oscin clock\n");
14113bc61cfdSLiam Beguin return PTR_ERR(lmk->oscin);
14123bc61cfdSLiam Beguin }
14133bc61cfdSLiam Beguin
14143bc61cfdSLiam Beguin ret = clk_prepare_enable(lmk->oscin);
14153bc61cfdSLiam Beguin if (ret)
14163bc61cfdSLiam Beguin return ret;
14173bc61cfdSLiam Beguin
14183bc61cfdSLiam Beguin lmk->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
14193bc61cfdSLiam Beguin GPIOD_OUT_LOW);
14203bc61cfdSLiam Beguin
14213bc61cfdSLiam Beguin lmk->dclk = devm_kcalloc(lmk->dev, info->num_channels >> 1,
14223bc61cfdSLiam Beguin sizeof(struct lmk_dclk), GFP_KERNEL);
1423b424f73bSWang Hai if (!lmk->dclk) {
1424b424f73bSWang Hai ret = -ENOMEM;
14253bc61cfdSLiam Beguin goto err_disable_oscin;
14263bc61cfdSLiam Beguin }
14273bc61cfdSLiam Beguin
14283bc61cfdSLiam Beguin lmk->clkout = devm_kcalloc(lmk->dev, info->num_channels,
14293bc61cfdSLiam Beguin sizeof(*lmk->clkout), GFP_KERNEL);
1430b424f73bSWang Hai if (!lmk->clkout) {
1431b424f73bSWang Hai ret = -ENOMEM;
14323bc61cfdSLiam Beguin goto err_disable_oscin;
14333bc61cfdSLiam Beguin }
14343bc61cfdSLiam Beguin
14353bc61cfdSLiam Beguin lmk->clk_data = devm_kzalloc(lmk->dev, struct_size(lmk->clk_data, hws,
14363bc61cfdSLiam Beguin info->num_channels),
14373bc61cfdSLiam Beguin GFP_KERNEL);
1438b424f73bSWang Hai if (!lmk->clk_data) {
1439b424f73bSWang Hai ret = -ENOMEM;
14403bc61cfdSLiam Beguin goto err_disable_oscin;
14413bc61cfdSLiam Beguin }
14423bc61cfdSLiam Beguin
14433bc61cfdSLiam Beguin device_property_read_u32(lmk->dev, "ti,vco-hz", &lmk->vco_rate);
14443bc61cfdSLiam Beguin
14456181baa1SLiam Beguin lmk->sysref_ddly = 8;
14466181baa1SLiam Beguin device_property_read_u32(lmk->dev, "ti,sysref-ddly", &lmk->sysref_ddly);
14476181baa1SLiam Beguin
14486181baa1SLiam Beguin lmk->sysref_mux = LMK04832_VAL_SYSREF_MUX_CONTINUOUS;
14496181baa1SLiam Beguin device_property_read_u32(lmk->dev, "ti,sysref-mux",
14506181baa1SLiam Beguin &lmk->sysref_mux);
14516181baa1SLiam Beguin
14526181baa1SLiam Beguin lmk->sync_mode = LMK04832_VAL_SYNC_MODE_OFF;
14536181baa1SLiam Beguin device_property_read_u32(lmk->dev, "ti,sync-mode",
14546181baa1SLiam Beguin &lmk->sync_mode);
14556181baa1SLiam Beguin
14566181baa1SLiam Beguin lmk->sysref_pulse_cnt = 4;
14576181baa1SLiam Beguin device_property_read_u32(lmk->dev, "ti,sysref-pulse-count",
14586181baa1SLiam Beguin &lmk->sysref_pulse_cnt);
14596181baa1SLiam Beguin
14603bc61cfdSLiam Beguin for_each_child_of_node(lmk->dev->of_node, child) {
14613bc61cfdSLiam Beguin int reg;
14623bc61cfdSLiam Beguin
14633bc61cfdSLiam Beguin ret = of_property_read_u32(child, "reg", ®);
14643bc61cfdSLiam Beguin if (ret) {
14653bc61cfdSLiam Beguin dev_err(lmk->dev, "missing reg property in child: %s\n",
14663bc61cfdSLiam Beguin child->full_name);
14673bc61cfdSLiam Beguin of_node_put(child);
14683bc61cfdSLiam Beguin goto err_disable_oscin;
14693bc61cfdSLiam Beguin }
14703bc61cfdSLiam Beguin
14713bc61cfdSLiam Beguin of_property_read_u32(child, "ti,clkout-fmt",
14723bc61cfdSLiam Beguin &lmk->clkout[reg].format);
14733bc61cfdSLiam Beguin
14743bc61cfdSLiam Beguin if (lmk->clkout[reg].format >= 0x0a && reg % 2 == 0
14753bc61cfdSLiam Beguin && reg != 8 && reg != 10)
14763bc61cfdSLiam Beguin dev_err(lmk->dev, "invalid format for clkout%02d\n",
14773bc61cfdSLiam Beguin reg);
14783bc61cfdSLiam Beguin
14793bc61cfdSLiam Beguin lmk->clkout[reg].sysref =
14803bc61cfdSLiam Beguin of_property_read_bool(child, "ti,clkout-sysref");
14813bc61cfdSLiam Beguin }
14823bc61cfdSLiam Beguin
14833bc61cfdSLiam Beguin lmk->regmap = devm_regmap_init_spi(spi, ®map_config);
14843bc61cfdSLiam Beguin if (IS_ERR(lmk->regmap)) {
14853bc61cfdSLiam Beguin dev_err(lmk->dev, "%s: regmap allocation failed: %ld\n",
14863bc61cfdSLiam Beguin
14873bc61cfdSLiam Beguin __func__, PTR_ERR(lmk->regmap));
14883bc61cfdSLiam Beguin ret = PTR_ERR(lmk->regmap);
14893bc61cfdSLiam Beguin goto err_disable_oscin;
14903bc61cfdSLiam Beguin }
14913bc61cfdSLiam Beguin
14923bc61cfdSLiam Beguin regmap_write(lmk->regmap, LMK04832_REG_RST3W, LMK04832_BIT_RESET);
14933bc61cfdSLiam Beguin
14943bc61cfdSLiam Beguin if (!(spi->mode & SPI_3WIRE)) {
14953bc61cfdSLiam Beguin device_property_read_u32(lmk->dev, "ti,spi-4wire-rdbk",
14963bc61cfdSLiam Beguin &rdbk_pin);
14973bc61cfdSLiam Beguin ret = lmk04832_set_spi_rdbk(lmk, rdbk_pin);
14983bc61cfdSLiam Beguin if (ret)
14993bc61cfdSLiam Beguin goto err_disable_oscin;
15003bc61cfdSLiam Beguin }
15013bc61cfdSLiam Beguin
15023bc61cfdSLiam Beguin regmap_bulk_read(lmk->regmap, LMK04832_REG_ID_PROD_MSB, &tmp, 3);
15033bc61cfdSLiam Beguin if ((tmp[0] << 8 | tmp[1]) != info->pid || tmp[2] != info->maskrev) {
15043bc61cfdSLiam Beguin dev_err(lmk->dev, "unsupported device type: pid 0x%04x, maskrev 0x%02x\n",
15053bc61cfdSLiam Beguin tmp[0] << 8 | tmp[1], tmp[2]);
15063bc61cfdSLiam Beguin ret = -EINVAL;
15073bc61cfdSLiam Beguin goto err_disable_oscin;
15083bc61cfdSLiam Beguin }
15093bc61cfdSLiam Beguin
15103bc61cfdSLiam Beguin ret = lmk04832_register_vco(lmk);
15113bc61cfdSLiam Beguin if (ret) {
15123bc61cfdSLiam Beguin dev_err(lmk->dev, "failed to init device clock path\n");
15133bc61cfdSLiam Beguin goto err_disable_oscin;
15143bc61cfdSLiam Beguin }
15153bc61cfdSLiam Beguin
15163bc61cfdSLiam Beguin if (lmk->vco_rate) {
15173bc61cfdSLiam Beguin dev_info(lmk->dev, "setting VCO rate to %u Hz\n", lmk->vco_rate);
15183bc61cfdSLiam Beguin ret = clk_set_rate(lmk->vco.clk, lmk->vco_rate);
15193bc61cfdSLiam Beguin if (ret) {
15203bc61cfdSLiam Beguin dev_err(lmk->dev, "failed to set VCO rate\n");
1521e63227c8SMike Looijmans goto err_disable_oscin;
15223bc61cfdSLiam Beguin }
15233bc61cfdSLiam Beguin }
15243bc61cfdSLiam Beguin
15253bc61cfdSLiam Beguin ret = lmk04832_register_sclk(lmk);
15263bc61cfdSLiam Beguin if (ret) {
15273bc61cfdSLiam Beguin dev_err(lmk->dev, "failed to init SYNC/SYSREF clock path\n");
1528e63227c8SMike Looijmans goto err_disable_oscin;
15293bc61cfdSLiam Beguin }
15303bc61cfdSLiam Beguin
15313bc61cfdSLiam Beguin for (i = 0; i < info->num_channels; i++) {
15323bc61cfdSLiam Beguin ret = lmk04832_register_clkout(lmk, i);
15333bc61cfdSLiam Beguin if (ret) {
15343bc61cfdSLiam Beguin dev_err(lmk->dev, "failed to register clk %d\n", i);
1535e63227c8SMike Looijmans goto err_disable_oscin;
15363bc61cfdSLiam Beguin }
15373bc61cfdSLiam Beguin }
15383bc61cfdSLiam Beguin
15393bc61cfdSLiam Beguin lmk->clk_data->num = info->num_channels;
154056fc9a34SLars-Peter Clausen ret = devm_of_clk_add_hw_provider(lmk->dev, of_clk_hw_onecell_get,
15413bc61cfdSLiam Beguin lmk->clk_data);
15423bc61cfdSLiam Beguin if (ret) {
15433bc61cfdSLiam Beguin dev_err(lmk->dev, "failed to add provider (%d)\n", ret);
1544e63227c8SMike Looijmans goto err_disable_oscin;
15453bc61cfdSLiam Beguin }
15463bc61cfdSLiam Beguin
15473bc61cfdSLiam Beguin spi_set_drvdata(spi, lmk);
15483bc61cfdSLiam Beguin
15493bc61cfdSLiam Beguin return 0;
15503bc61cfdSLiam Beguin
15513bc61cfdSLiam Beguin err_disable_oscin:
15523bc61cfdSLiam Beguin clk_disable_unprepare(lmk->oscin);
15533bc61cfdSLiam Beguin
15543bc61cfdSLiam Beguin return ret;
15553bc61cfdSLiam Beguin }
15563bc61cfdSLiam Beguin
lmk04832_remove(struct spi_device * spi)1557a0386bbaSUwe Kleine-König static void lmk04832_remove(struct spi_device *spi)
15583bc61cfdSLiam Beguin {
15593bc61cfdSLiam Beguin struct lmk04832 *lmk = spi_get_drvdata(spi);
15603bc61cfdSLiam Beguin
15613bc61cfdSLiam Beguin clk_disable_unprepare(lmk->oscin);
15623bc61cfdSLiam Beguin }
1563992a3552SLiam Beguin
15643bc61cfdSLiam Beguin static const struct spi_device_id lmk04832_id[] = {
15653bc61cfdSLiam Beguin { "lmk04832", LMK04832 },
1566bf68fdfdSStephen Boyd {}
15673bc61cfdSLiam Beguin };
15683bc61cfdSLiam Beguin MODULE_DEVICE_TABLE(spi, lmk04832_id);
15693bc61cfdSLiam Beguin
15703bc61cfdSLiam Beguin static const struct of_device_id lmk04832_of_id[] = {
15713bc61cfdSLiam Beguin { .compatible = "ti,lmk04832" },
1572bf68fdfdSStephen Boyd {}
15733bc61cfdSLiam Beguin };
1574bf68fdfdSStephen Boyd MODULE_DEVICE_TABLE(of, lmk04832_of_id);
15753bc61cfdSLiam Beguin
15763bc61cfdSLiam Beguin static struct spi_driver lmk04832_driver = {
15773bc61cfdSLiam Beguin .driver = {
15783bc61cfdSLiam Beguin .name = "lmk04832",
1579bf68fdfdSStephen Boyd .of_match_table = lmk04832_of_id,
15803bc61cfdSLiam Beguin },
15813bc61cfdSLiam Beguin .probe = lmk04832_probe,
15823bc61cfdSLiam Beguin .remove = lmk04832_remove,
15833bc61cfdSLiam Beguin .id_table = lmk04832_id,
15843bc61cfdSLiam Beguin };
15853bc61cfdSLiam Beguin module_spi_driver(lmk04832_driver);
15863bc61cfdSLiam Beguin
15873bc61cfdSLiam Beguin MODULE_AUTHOR("Liam Beguin <lvb@xiphos.com>");
15883bc61cfdSLiam Beguin MODULE_DESCRIPTION("Texas Instruments LMK04832");
15893bc61cfdSLiam Beguin MODULE_LICENSE("GPL v2");
1590