12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29abd5f05SSebastian Hesselbarth /*
3dd5e1280SJens Renner * clk-si5351.c: Skyworks / Silicon Labs Si5351A/B/C I2C Clock Generator
49abd5f05SSebastian Hesselbarth *
59abd5f05SSebastian Hesselbarth * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
69abd5f05SSebastian Hesselbarth * Rabeeh Khoury <rabeeh@solid-run.com>
79abd5f05SSebastian Hesselbarth *
89abd5f05SSebastian Hesselbarth * References:
99abd5f05SSebastian Hesselbarth * [1] "Si5351A/B/C Data Sheet"
10dd5e1280SJens Renner * https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/Si5351-B.pdf
11dd5e1280SJens Renner * [2] "AN619: Manually Generating an Si5351 Register Map"
12dd5e1280SJens Renner * https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/application-notes/AN619.pdf
139abd5f05SSebastian Hesselbarth */
149abd5f05SSebastian Hesselbarth
159abd5f05SSebastian Hesselbarth #include <linux/module.h>
169abd5f05SSebastian Hesselbarth #include <linux/kernel.h>
17608f9b6eSStephen Boyd #include <linux/clk.h>
189abd5f05SSebastian Hesselbarth #include <linux/clk-provider.h>
199abd5f05SSebastian Hesselbarth #include <linux/delay.h>
209abd5f05SSebastian Hesselbarth #include <linux/err.h>
219abd5f05SSebastian Hesselbarth #include <linux/errno.h>
229abd5f05SSebastian Hesselbarth #include <linux/rational.h>
239abd5f05SSebastian Hesselbarth #include <linux/i2c.h>
24a96cbb14SRob Herring #include <linux/of.h>
259abd5f05SSebastian Hesselbarth #include <linux/platform_data/si5351.h>
269abd5f05SSebastian Hesselbarth #include <linux/regmap.h>
279abd5f05SSebastian Hesselbarth #include <linux/slab.h>
289abd5f05SSebastian Hesselbarth #include <linux/string.h>
299abd5f05SSebastian Hesselbarth #include <asm/div64.h>
309abd5f05SSebastian Hesselbarth
319abd5f05SSebastian Hesselbarth #include "clk-si5351.h"
329abd5f05SSebastian Hesselbarth
339abd5f05SSebastian Hesselbarth struct si5351_driver_data;
349abd5f05SSebastian Hesselbarth
359abd5f05SSebastian Hesselbarth struct si5351_parameters {
369abd5f05SSebastian Hesselbarth unsigned long p1;
379abd5f05SSebastian Hesselbarth unsigned long p2;
389abd5f05SSebastian Hesselbarth unsigned long p3;
399abd5f05SSebastian Hesselbarth int valid;
409abd5f05SSebastian Hesselbarth };
419abd5f05SSebastian Hesselbarth
429abd5f05SSebastian Hesselbarth struct si5351_hw_data {
439abd5f05SSebastian Hesselbarth struct clk_hw hw;
449abd5f05SSebastian Hesselbarth struct si5351_driver_data *drvdata;
459abd5f05SSebastian Hesselbarth struct si5351_parameters params;
469abd5f05SSebastian Hesselbarth unsigned char num;
479abd5f05SSebastian Hesselbarth };
489abd5f05SSebastian Hesselbarth
499abd5f05SSebastian Hesselbarth struct si5351_driver_data {
509abd5f05SSebastian Hesselbarth enum si5351_variant variant;
519abd5f05SSebastian Hesselbarth struct i2c_client *client;
529abd5f05SSebastian Hesselbarth struct regmap *regmap;
539abd5f05SSebastian Hesselbarth
549abd5f05SSebastian Hesselbarth struct clk *pxtal;
559abd5f05SSebastian Hesselbarth const char *pxtal_name;
569abd5f05SSebastian Hesselbarth struct clk_hw xtal;
579abd5f05SSebastian Hesselbarth struct clk *pclkin;
589abd5f05SSebastian Hesselbarth const char *pclkin_name;
599abd5f05SSebastian Hesselbarth struct clk_hw clkin;
609abd5f05SSebastian Hesselbarth
619abd5f05SSebastian Hesselbarth struct si5351_hw_data pll[2];
629abd5f05SSebastian Hesselbarth struct si5351_hw_data *msynth;
639abd5f05SSebastian Hesselbarth struct si5351_hw_data *clkout;
644d89c3d5SStephen Boyd size_t num_clkout;
659abd5f05SSebastian Hesselbarth };
669abd5f05SSebastian Hesselbarth
678234caedSKrzysztof Kozlowski static const char * const si5351_input_names[] = {
689abd5f05SSebastian Hesselbarth "xtal", "clkin"
699abd5f05SSebastian Hesselbarth };
708234caedSKrzysztof Kozlowski static const char * const si5351_pll_names[] = {
71cdba9a4fSSergej Sawazki "si5351_plla", "si5351_pllb", "si5351_vxco"
729abd5f05SSebastian Hesselbarth };
738234caedSKrzysztof Kozlowski static const char * const si5351_msynth_names[] = {
749abd5f05SSebastian Hesselbarth "ms0", "ms1", "ms2", "ms3", "ms4", "ms5", "ms6", "ms7"
759abd5f05SSebastian Hesselbarth };
768234caedSKrzysztof Kozlowski static const char * const si5351_clkout_names[] = {
779abd5f05SSebastian Hesselbarth "clk0", "clk1", "clk2", "clk3", "clk4", "clk5", "clk6", "clk7"
789abd5f05SSebastian Hesselbarth };
799abd5f05SSebastian Hesselbarth
809abd5f05SSebastian Hesselbarth /*
819abd5f05SSebastian Hesselbarth * Si5351 i2c regmap
829abd5f05SSebastian Hesselbarth */
si5351_reg_read(struct si5351_driver_data * drvdata,u8 reg)839abd5f05SSebastian Hesselbarth static inline u8 si5351_reg_read(struct si5351_driver_data *drvdata, u8 reg)
849abd5f05SSebastian Hesselbarth {
859abd5f05SSebastian Hesselbarth u32 val;
869abd5f05SSebastian Hesselbarth int ret;
879abd5f05SSebastian Hesselbarth
889abd5f05SSebastian Hesselbarth ret = regmap_read(drvdata->regmap, reg, &val);
899abd5f05SSebastian Hesselbarth if (ret) {
909abd5f05SSebastian Hesselbarth dev_err(&drvdata->client->dev,
919abd5f05SSebastian Hesselbarth "unable to read from reg%02x\n", reg);
929abd5f05SSebastian Hesselbarth return 0;
939abd5f05SSebastian Hesselbarth }
949abd5f05SSebastian Hesselbarth
959abd5f05SSebastian Hesselbarth return (u8)val;
969abd5f05SSebastian Hesselbarth }
979abd5f05SSebastian Hesselbarth
si5351_bulk_read(struct si5351_driver_data * drvdata,u8 reg,u8 count,u8 * buf)989abd5f05SSebastian Hesselbarth static inline int si5351_bulk_read(struct si5351_driver_data *drvdata,
999abd5f05SSebastian Hesselbarth u8 reg, u8 count, u8 *buf)
1009abd5f05SSebastian Hesselbarth {
1019abd5f05SSebastian Hesselbarth return regmap_bulk_read(drvdata->regmap, reg, buf, count);
1029abd5f05SSebastian Hesselbarth }
1039abd5f05SSebastian Hesselbarth
si5351_reg_write(struct si5351_driver_data * drvdata,u8 reg,u8 val)1049abd5f05SSebastian Hesselbarth static inline int si5351_reg_write(struct si5351_driver_data *drvdata,
1059abd5f05SSebastian Hesselbarth u8 reg, u8 val)
1069abd5f05SSebastian Hesselbarth {
1079abd5f05SSebastian Hesselbarth return regmap_write(drvdata->regmap, reg, val);
1089abd5f05SSebastian Hesselbarth }
1099abd5f05SSebastian Hesselbarth
si5351_bulk_write(struct si5351_driver_data * drvdata,u8 reg,u8 count,const u8 * buf)1109abd5f05SSebastian Hesselbarth static inline int si5351_bulk_write(struct si5351_driver_data *drvdata,
1119abd5f05SSebastian Hesselbarth u8 reg, u8 count, const u8 *buf)
1129abd5f05SSebastian Hesselbarth {
1139abd5f05SSebastian Hesselbarth return regmap_raw_write(drvdata->regmap, reg, buf, count);
1149abd5f05SSebastian Hesselbarth }
1159abd5f05SSebastian Hesselbarth
si5351_set_bits(struct si5351_driver_data * drvdata,u8 reg,u8 mask,u8 val)1169abd5f05SSebastian Hesselbarth static inline int si5351_set_bits(struct si5351_driver_data *drvdata,
1179abd5f05SSebastian Hesselbarth u8 reg, u8 mask, u8 val)
1189abd5f05SSebastian Hesselbarth {
1199abd5f05SSebastian Hesselbarth return regmap_update_bits(drvdata->regmap, reg, mask, val);
1209abd5f05SSebastian Hesselbarth }
1219abd5f05SSebastian Hesselbarth
si5351_msynth_params_address(int num)1229abd5f05SSebastian Hesselbarth static inline u8 si5351_msynth_params_address(int num)
1239abd5f05SSebastian Hesselbarth {
1249abd5f05SSebastian Hesselbarth if (num > 5)
1259abd5f05SSebastian Hesselbarth return SI5351_CLK6_PARAMETERS + (num - 6);
1269abd5f05SSebastian Hesselbarth return SI5351_CLK0_PARAMETERS + (SI5351_PARAMETERS_LENGTH * num);
1279abd5f05SSebastian Hesselbarth }
1289abd5f05SSebastian Hesselbarth
si5351_read_parameters(struct si5351_driver_data * drvdata,u8 reg,struct si5351_parameters * params)1299abd5f05SSebastian Hesselbarth static void si5351_read_parameters(struct si5351_driver_data *drvdata,
1309abd5f05SSebastian Hesselbarth u8 reg, struct si5351_parameters *params)
1319abd5f05SSebastian Hesselbarth {
1329abd5f05SSebastian Hesselbarth u8 buf[SI5351_PARAMETERS_LENGTH];
1339abd5f05SSebastian Hesselbarth
1349abd5f05SSebastian Hesselbarth switch (reg) {
1359abd5f05SSebastian Hesselbarth case SI5351_CLK6_PARAMETERS:
1369abd5f05SSebastian Hesselbarth case SI5351_CLK7_PARAMETERS:
1379abd5f05SSebastian Hesselbarth buf[0] = si5351_reg_read(drvdata, reg);
1389abd5f05SSebastian Hesselbarth params->p1 = buf[0];
1399abd5f05SSebastian Hesselbarth params->p2 = 0;
1409abd5f05SSebastian Hesselbarth params->p3 = 1;
1419abd5f05SSebastian Hesselbarth break;
1429abd5f05SSebastian Hesselbarth default:
1439abd5f05SSebastian Hesselbarth si5351_bulk_read(drvdata, reg, SI5351_PARAMETERS_LENGTH, buf);
1449abd5f05SSebastian Hesselbarth params->p1 = ((buf[2] & 0x03) << 16) | (buf[3] << 8) | buf[4];
1459abd5f05SSebastian Hesselbarth params->p2 = ((buf[5] & 0x0f) << 16) | (buf[6] << 8) | buf[7];
1469abd5f05SSebastian Hesselbarth params->p3 = ((buf[5] & 0xf0) << 12) | (buf[0] << 8) | buf[1];
1479abd5f05SSebastian Hesselbarth }
1489abd5f05SSebastian Hesselbarth params->valid = 1;
1499abd5f05SSebastian Hesselbarth }
1509abd5f05SSebastian Hesselbarth
si5351_write_parameters(struct si5351_driver_data * drvdata,u8 reg,struct si5351_parameters * params)1519abd5f05SSebastian Hesselbarth static void si5351_write_parameters(struct si5351_driver_data *drvdata,
1529abd5f05SSebastian Hesselbarth u8 reg, struct si5351_parameters *params)
1539abd5f05SSebastian Hesselbarth {
1549abd5f05SSebastian Hesselbarth u8 buf[SI5351_PARAMETERS_LENGTH];
1559abd5f05SSebastian Hesselbarth
1569abd5f05SSebastian Hesselbarth switch (reg) {
1579abd5f05SSebastian Hesselbarth case SI5351_CLK6_PARAMETERS:
1589abd5f05SSebastian Hesselbarth case SI5351_CLK7_PARAMETERS:
1599abd5f05SSebastian Hesselbarth buf[0] = params->p1 & 0xff;
1609abd5f05SSebastian Hesselbarth si5351_reg_write(drvdata, reg, buf[0]);
1619abd5f05SSebastian Hesselbarth break;
1629abd5f05SSebastian Hesselbarth default:
1639abd5f05SSebastian Hesselbarth buf[0] = ((params->p3 & 0x0ff00) >> 8) & 0xff;
1649abd5f05SSebastian Hesselbarth buf[1] = params->p3 & 0xff;
1659abd5f05SSebastian Hesselbarth /* save rdiv and divby4 */
1669abd5f05SSebastian Hesselbarth buf[2] = si5351_reg_read(drvdata, reg + 2) & ~0x03;
1679abd5f05SSebastian Hesselbarth buf[2] |= ((params->p1 & 0x30000) >> 16) & 0x03;
1689abd5f05SSebastian Hesselbarth buf[3] = ((params->p1 & 0x0ff00) >> 8) & 0xff;
1699abd5f05SSebastian Hesselbarth buf[4] = params->p1 & 0xff;
1709abd5f05SSebastian Hesselbarth buf[5] = ((params->p3 & 0xf0000) >> 12) |
1719abd5f05SSebastian Hesselbarth ((params->p2 & 0xf0000) >> 16);
1729abd5f05SSebastian Hesselbarth buf[6] = ((params->p2 & 0x0ff00) >> 8) & 0xff;
1739abd5f05SSebastian Hesselbarth buf[7] = params->p2 & 0xff;
1749abd5f05SSebastian Hesselbarth si5351_bulk_write(drvdata, reg, SI5351_PARAMETERS_LENGTH, buf);
1759abd5f05SSebastian Hesselbarth }
1769abd5f05SSebastian Hesselbarth }
1779abd5f05SSebastian Hesselbarth
si5351_regmap_is_volatile(struct device * dev,unsigned int reg)1789abd5f05SSebastian Hesselbarth static bool si5351_regmap_is_volatile(struct device *dev, unsigned int reg)
1799abd5f05SSebastian Hesselbarth {
1809abd5f05SSebastian Hesselbarth switch (reg) {
1819abd5f05SSebastian Hesselbarth case SI5351_DEVICE_STATUS:
1829abd5f05SSebastian Hesselbarth case SI5351_INTERRUPT_STATUS:
1839abd5f05SSebastian Hesselbarth case SI5351_PLL_RESET:
1849abd5f05SSebastian Hesselbarth return true;
1859abd5f05SSebastian Hesselbarth }
1869abd5f05SSebastian Hesselbarth return false;
1879abd5f05SSebastian Hesselbarth }
1889abd5f05SSebastian Hesselbarth
si5351_regmap_is_writeable(struct device * dev,unsigned int reg)1899abd5f05SSebastian Hesselbarth static bool si5351_regmap_is_writeable(struct device *dev, unsigned int reg)
1909abd5f05SSebastian Hesselbarth {
1919abd5f05SSebastian Hesselbarth /* reserved registers */
1929abd5f05SSebastian Hesselbarth if (reg >= 4 && reg <= 8)
1939abd5f05SSebastian Hesselbarth return false;
1949abd5f05SSebastian Hesselbarth if (reg >= 10 && reg <= 14)
1959abd5f05SSebastian Hesselbarth return false;
1969abd5f05SSebastian Hesselbarth if (reg >= 173 && reg <= 176)
1979abd5f05SSebastian Hesselbarth return false;
1989abd5f05SSebastian Hesselbarth if (reg >= 178 && reg <= 182)
1999abd5f05SSebastian Hesselbarth return false;
2009abd5f05SSebastian Hesselbarth /* read-only */
2019abd5f05SSebastian Hesselbarth if (reg == SI5351_DEVICE_STATUS)
2029abd5f05SSebastian Hesselbarth return false;
2039abd5f05SSebastian Hesselbarth return true;
2049abd5f05SSebastian Hesselbarth }
2059abd5f05SSebastian Hesselbarth
2068234caedSKrzysztof Kozlowski static const struct regmap_config si5351_regmap_config = {
2079abd5f05SSebastian Hesselbarth .reg_bits = 8,
2089abd5f05SSebastian Hesselbarth .val_bits = 8,
2099abd5f05SSebastian Hesselbarth .cache_type = REGCACHE_RBTREE,
2109abd5f05SSebastian Hesselbarth .max_register = 187,
2119abd5f05SSebastian Hesselbarth .writeable_reg = si5351_regmap_is_writeable,
2129abd5f05SSebastian Hesselbarth .volatile_reg = si5351_regmap_is_volatile,
2139abd5f05SSebastian Hesselbarth };
2149abd5f05SSebastian Hesselbarth
2159abd5f05SSebastian Hesselbarth /*
2169abd5f05SSebastian Hesselbarth * Si5351 xtal clock input
2179abd5f05SSebastian Hesselbarth */
si5351_xtal_prepare(struct clk_hw * hw)2189abd5f05SSebastian Hesselbarth static int si5351_xtal_prepare(struct clk_hw *hw)
2199abd5f05SSebastian Hesselbarth {
2209abd5f05SSebastian Hesselbarth struct si5351_driver_data *drvdata =
2219abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_driver_data, xtal);
2229abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE,
2239abd5f05SSebastian Hesselbarth SI5351_XTAL_ENABLE, SI5351_XTAL_ENABLE);
2249abd5f05SSebastian Hesselbarth return 0;
2259abd5f05SSebastian Hesselbarth }
2269abd5f05SSebastian Hesselbarth
si5351_xtal_unprepare(struct clk_hw * hw)2279abd5f05SSebastian Hesselbarth static void si5351_xtal_unprepare(struct clk_hw *hw)
2289abd5f05SSebastian Hesselbarth {
2299abd5f05SSebastian Hesselbarth struct si5351_driver_data *drvdata =
2309abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_driver_data, xtal);
2319abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE,
2329abd5f05SSebastian Hesselbarth SI5351_XTAL_ENABLE, 0);
2339abd5f05SSebastian Hesselbarth }
2349abd5f05SSebastian Hesselbarth
2359abd5f05SSebastian Hesselbarth static const struct clk_ops si5351_xtal_ops = {
2369abd5f05SSebastian Hesselbarth .prepare = si5351_xtal_prepare,
2379abd5f05SSebastian Hesselbarth .unprepare = si5351_xtal_unprepare,
2389abd5f05SSebastian Hesselbarth };
2399abd5f05SSebastian Hesselbarth
2409abd5f05SSebastian Hesselbarth /*
2419abd5f05SSebastian Hesselbarth * Si5351 clkin clock input (Si5351C only)
2429abd5f05SSebastian Hesselbarth */
si5351_clkin_prepare(struct clk_hw * hw)2439abd5f05SSebastian Hesselbarth static int si5351_clkin_prepare(struct clk_hw *hw)
2449abd5f05SSebastian Hesselbarth {
2459abd5f05SSebastian Hesselbarth struct si5351_driver_data *drvdata =
2469abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_driver_data, clkin);
2479abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE,
2489abd5f05SSebastian Hesselbarth SI5351_CLKIN_ENABLE, SI5351_CLKIN_ENABLE);
2499abd5f05SSebastian Hesselbarth return 0;
2509abd5f05SSebastian Hesselbarth }
2519abd5f05SSebastian Hesselbarth
si5351_clkin_unprepare(struct clk_hw * hw)2529abd5f05SSebastian Hesselbarth static void si5351_clkin_unprepare(struct clk_hw *hw)
2539abd5f05SSebastian Hesselbarth {
2549abd5f05SSebastian Hesselbarth struct si5351_driver_data *drvdata =
2559abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_driver_data, clkin);
2569abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE,
2579abd5f05SSebastian Hesselbarth SI5351_CLKIN_ENABLE, 0);
2589abd5f05SSebastian Hesselbarth }
2599abd5f05SSebastian Hesselbarth
2609abd5f05SSebastian Hesselbarth /*
2619abd5f05SSebastian Hesselbarth * CMOS clock source constraints:
2629abd5f05SSebastian Hesselbarth * The input frequency range of the PLL is 10Mhz to 40MHz.
2639abd5f05SSebastian Hesselbarth * If CLKIN is >40MHz, the input divider must be used.
2649abd5f05SSebastian Hesselbarth */
si5351_clkin_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)2659abd5f05SSebastian Hesselbarth static unsigned long si5351_clkin_recalc_rate(struct clk_hw *hw,
2669abd5f05SSebastian Hesselbarth unsigned long parent_rate)
2679abd5f05SSebastian Hesselbarth {
2689abd5f05SSebastian Hesselbarth struct si5351_driver_data *drvdata =
2699abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_driver_data, clkin);
2709abd5f05SSebastian Hesselbarth unsigned long rate;
2719abd5f05SSebastian Hesselbarth unsigned char idiv;
2729abd5f05SSebastian Hesselbarth
2739abd5f05SSebastian Hesselbarth rate = parent_rate;
2749abd5f05SSebastian Hesselbarth if (parent_rate > 160000000) {
2759abd5f05SSebastian Hesselbarth idiv = SI5351_CLKIN_DIV_8;
2769abd5f05SSebastian Hesselbarth rate /= 8;
2779abd5f05SSebastian Hesselbarth } else if (parent_rate > 80000000) {
2789abd5f05SSebastian Hesselbarth idiv = SI5351_CLKIN_DIV_4;
2799abd5f05SSebastian Hesselbarth rate /= 4;
2809abd5f05SSebastian Hesselbarth } else if (parent_rate > 40000000) {
2819abd5f05SSebastian Hesselbarth idiv = SI5351_CLKIN_DIV_2;
2829abd5f05SSebastian Hesselbarth rate /= 2;
2839abd5f05SSebastian Hesselbarth } else {
2849abd5f05SSebastian Hesselbarth idiv = SI5351_CLKIN_DIV_1;
2859abd5f05SSebastian Hesselbarth }
2869abd5f05SSebastian Hesselbarth
2879abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE,
2889abd5f05SSebastian Hesselbarth SI5351_CLKIN_DIV_MASK, idiv);
2899abd5f05SSebastian Hesselbarth
2909abd5f05SSebastian Hesselbarth dev_dbg(&drvdata->client->dev, "%s - clkin div = %d, rate = %lu\n",
2919abd5f05SSebastian Hesselbarth __func__, (1 << (idiv >> 6)), rate);
2929abd5f05SSebastian Hesselbarth
2939abd5f05SSebastian Hesselbarth return rate;
2949abd5f05SSebastian Hesselbarth }
2959abd5f05SSebastian Hesselbarth
2969abd5f05SSebastian Hesselbarth static const struct clk_ops si5351_clkin_ops = {
2979abd5f05SSebastian Hesselbarth .prepare = si5351_clkin_prepare,
2989abd5f05SSebastian Hesselbarth .unprepare = si5351_clkin_unprepare,
2999abd5f05SSebastian Hesselbarth .recalc_rate = si5351_clkin_recalc_rate,
3009abd5f05SSebastian Hesselbarth };
3019abd5f05SSebastian Hesselbarth
3029abd5f05SSebastian Hesselbarth /*
3039abd5f05SSebastian Hesselbarth * Si5351 vxco clock input (Si5351B only)
3049abd5f05SSebastian Hesselbarth */
3059abd5f05SSebastian Hesselbarth
si5351_vxco_prepare(struct clk_hw * hw)3069abd5f05SSebastian Hesselbarth static int si5351_vxco_prepare(struct clk_hw *hw)
3079abd5f05SSebastian Hesselbarth {
3089abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
3099abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
3109abd5f05SSebastian Hesselbarth
3119abd5f05SSebastian Hesselbarth dev_warn(&hwdata->drvdata->client->dev, "VXCO currently unsupported\n");
3129abd5f05SSebastian Hesselbarth
3139abd5f05SSebastian Hesselbarth return 0;
3149abd5f05SSebastian Hesselbarth }
3159abd5f05SSebastian Hesselbarth
si5351_vxco_unprepare(struct clk_hw * hw)3169abd5f05SSebastian Hesselbarth static void si5351_vxco_unprepare(struct clk_hw *hw)
3179abd5f05SSebastian Hesselbarth {
3189abd5f05SSebastian Hesselbarth }
3199abd5f05SSebastian Hesselbarth
si5351_vxco_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)3209abd5f05SSebastian Hesselbarth static unsigned long si5351_vxco_recalc_rate(struct clk_hw *hw,
3219abd5f05SSebastian Hesselbarth unsigned long parent_rate)
3229abd5f05SSebastian Hesselbarth {
3239abd5f05SSebastian Hesselbarth return 0;
3249abd5f05SSebastian Hesselbarth }
3259abd5f05SSebastian Hesselbarth
si5351_vxco_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent)3269abd5f05SSebastian Hesselbarth static int si5351_vxco_set_rate(struct clk_hw *hw, unsigned long rate,
3279abd5f05SSebastian Hesselbarth unsigned long parent)
3289abd5f05SSebastian Hesselbarth {
3299abd5f05SSebastian Hesselbarth return 0;
3309abd5f05SSebastian Hesselbarth }
3319abd5f05SSebastian Hesselbarth
3329abd5f05SSebastian Hesselbarth static const struct clk_ops si5351_vxco_ops = {
3339abd5f05SSebastian Hesselbarth .prepare = si5351_vxco_prepare,
3349abd5f05SSebastian Hesselbarth .unprepare = si5351_vxco_unprepare,
3359abd5f05SSebastian Hesselbarth .recalc_rate = si5351_vxco_recalc_rate,
3369abd5f05SSebastian Hesselbarth .set_rate = si5351_vxco_set_rate,
3379abd5f05SSebastian Hesselbarth };
3389abd5f05SSebastian Hesselbarth
3399abd5f05SSebastian Hesselbarth /*
3409abd5f05SSebastian Hesselbarth * Si5351 pll a/b
3419abd5f05SSebastian Hesselbarth *
3429abd5f05SSebastian Hesselbarth * Feedback Multisynth Divider Equations [2]
3439abd5f05SSebastian Hesselbarth *
3449abd5f05SSebastian Hesselbarth * fVCO = fIN * (a + b/c)
3459abd5f05SSebastian Hesselbarth *
3469abd5f05SSebastian Hesselbarth * with 15 + 0/1048575 <= (a + b/c) <= 90 + 0/1048575 and
3479abd5f05SSebastian Hesselbarth * fIN = fXTAL or fIN = fCLKIN/CLKIN_DIV
3489abd5f05SSebastian Hesselbarth *
3499abd5f05SSebastian Hesselbarth * Feedback Multisynth Register Equations
3509abd5f05SSebastian Hesselbarth *
3519abd5f05SSebastian Hesselbarth * (1) MSNx_P1[17:0] = 128 * a + floor(128 * b/c) - 512
3529abd5f05SSebastian Hesselbarth * (2) MSNx_P2[19:0] = 128 * b - c * floor(128 * b/c) = (128*b) mod c
3539abd5f05SSebastian Hesselbarth * (3) MSNx_P3[19:0] = c
3549abd5f05SSebastian Hesselbarth *
3559abd5f05SSebastian Hesselbarth * Transposing (2) yields: (4) floor(128 * b/c) = (128 * b / MSNx_P2)/c
3569abd5f05SSebastian Hesselbarth *
3579abd5f05SSebastian Hesselbarth * Using (4) on (1) yields:
3589abd5f05SSebastian Hesselbarth * MSNx_P1 = 128 * a + (128 * b/MSNx_P2)/c - 512
3599abd5f05SSebastian Hesselbarth * MSNx_P1 + 512 + MSNx_P2/c = 128 * a + 128 * b/c
3609abd5f05SSebastian Hesselbarth *
3619abd5f05SSebastian Hesselbarth * a + b/c = (MSNx_P1 + MSNx_P2/MSNx_P3 + 512)/128
3629abd5f05SSebastian Hesselbarth * = (MSNx_P1*MSNx_P3 + MSNx_P2 + 512*MSNx_P3)/(128*MSNx_P3)
3639abd5f05SSebastian Hesselbarth *
3649abd5f05SSebastian Hesselbarth */
_si5351_pll_reparent(struct si5351_driver_data * drvdata,int num,enum si5351_pll_src parent)3659abd5f05SSebastian Hesselbarth static int _si5351_pll_reparent(struct si5351_driver_data *drvdata,
3669abd5f05SSebastian Hesselbarth int num, enum si5351_pll_src parent)
3679abd5f05SSebastian Hesselbarth {
3689abd5f05SSebastian Hesselbarth u8 mask = (num == 0) ? SI5351_PLLA_SOURCE : SI5351_PLLB_SOURCE;
3699abd5f05SSebastian Hesselbarth
3709abd5f05SSebastian Hesselbarth if (parent == SI5351_PLL_SRC_DEFAULT)
3719abd5f05SSebastian Hesselbarth return 0;
3729abd5f05SSebastian Hesselbarth
3739abd5f05SSebastian Hesselbarth if (num > 2)
3749abd5f05SSebastian Hesselbarth return -EINVAL;
3759abd5f05SSebastian Hesselbarth
3769abd5f05SSebastian Hesselbarth if (drvdata->variant != SI5351_VARIANT_C &&
3779abd5f05SSebastian Hesselbarth parent != SI5351_PLL_SRC_XTAL)
3789abd5f05SSebastian Hesselbarth return -EINVAL;
3799abd5f05SSebastian Hesselbarth
3809abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE, mask,
3819abd5f05SSebastian Hesselbarth (parent == SI5351_PLL_SRC_XTAL) ? 0 : mask);
3829abd5f05SSebastian Hesselbarth return 0;
3839abd5f05SSebastian Hesselbarth }
3849abd5f05SSebastian Hesselbarth
si5351_pll_get_parent(struct clk_hw * hw)3859abd5f05SSebastian Hesselbarth static unsigned char si5351_pll_get_parent(struct clk_hw *hw)
3869abd5f05SSebastian Hesselbarth {
3879abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
3889abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
3899abd5f05SSebastian Hesselbarth u8 mask = (hwdata->num == 0) ? SI5351_PLLA_SOURCE : SI5351_PLLB_SOURCE;
3909abd5f05SSebastian Hesselbarth u8 val;
3919abd5f05SSebastian Hesselbarth
3929abd5f05SSebastian Hesselbarth val = si5351_reg_read(hwdata->drvdata, SI5351_PLL_INPUT_SOURCE);
3939abd5f05SSebastian Hesselbarth
3949abd5f05SSebastian Hesselbarth return (val & mask) ? 1 : 0;
3959abd5f05SSebastian Hesselbarth }
3969abd5f05SSebastian Hesselbarth
si5351_pll_set_parent(struct clk_hw * hw,u8 index)3979abd5f05SSebastian Hesselbarth static int si5351_pll_set_parent(struct clk_hw *hw, u8 index)
3989abd5f05SSebastian Hesselbarth {
3999abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
4009abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
4019abd5f05SSebastian Hesselbarth
4029abd5f05SSebastian Hesselbarth if (hwdata->drvdata->variant != SI5351_VARIANT_C &&
4039abd5f05SSebastian Hesselbarth index > 0)
4049abd5f05SSebastian Hesselbarth return -EPERM;
4059abd5f05SSebastian Hesselbarth
4069abd5f05SSebastian Hesselbarth if (index > 1)
4079abd5f05SSebastian Hesselbarth return -EINVAL;
4089abd5f05SSebastian Hesselbarth
4099abd5f05SSebastian Hesselbarth return _si5351_pll_reparent(hwdata->drvdata, hwdata->num,
4109abd5f05SSebastian Hesselbarth (index == 0) ? SI5351_PLL_SRC_XTAL :
4119abd5f05SSebastian Hesselbarth SI5351_PLL_SRC_CLKIN);
4129abd5f05SSebastian Hesselbarth }
4139abd5f05SSebastian Hesselbarth
si5351_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)4149abd5f05SSebastian Hesselbarth static unsigned long si5351_pll_recalc_rate(struct clk_hw *hw,
4159abd5f05SSebastian Hesselbarth unsigned long parent_rate)
4169abd5f05SSebastian Hesselbarth {
4179abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
4189abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
4199abd5f05SSebastian Hesselbarth u8 reg = (hwdata->num == 0) ? SI5351_PLLA_PARAMETERS :
4209abd5f05SSebastian Hesselbarth SI5351_PLLB_PARAMETERS;
4219abd5f05SSebastian Hesselbarth unsigned long long rate;
4229abd5f05SSebastian Hesselbarth
4239abd5f05SSebastian Hesselbarth if (!hwdata->params.valid)
4249abd5f05SSebastian Hesselbarth si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params);
4259abd5f05SSebastian Hesselbarth
4269abd5f05SSebastian Hesselbarth if (hwdata->params.p3 == 0)
4279abd5f05SSebastian Hesselbarth return parent_rate;
4289abd5f05SSebastian Hesselbarth
4299abd5f05SSebastian Hesselbarth /* fVCO = fIN * (P1*P3 + 512*P3 + P2)/(128*P3) */
4309abd5f05SSebastian Hesselbarth rate = hwdata->params.p1 * hwdata->params.p3;
4319abd5f05SSebastian Hesselbarth rate += 512 * hwdata->params.p3;
4329abd5f05SSebastian Hesselbarth rate += hwdata->params.p2;
4339abd5f05SSebastian Hesselbarth rate *= parent_rate;
4349abd5f05SSebastian Hesselbarth do_div(rate, 128 * hwdata->params.p3);
4359abd5f05SSebastian Hesselbarth
4369abd5f05SSebastian Hesselbarth dev_dbg(&hwdata->drvdata->client->dev,
4379abd5f05SSebastian Hesselbarth "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
43844f22a5dSStephen Boyd __func__, clk_hw_get_name(hw),
4399abd5f05SSebastian Hesselbarth hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
4409abd5f05SSebastian Hesselbarth parent_rate, (unsigned long)rate);
4419abd5f05SSebastian Hesselbarth
4429abd5f05SSebastian Hesselbarth return (unsigned long)rate;
4439abd5f05SSebastian Hesselbarth }
4449abd5f05SSebastian Hesselbarth
si5351_pll_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)44508add3c1SMaxime Ripard static int si5351_pll_determine_rate(struct clk_hw *hw,
44608add3c1SMaxime Ripard struct clk_rate_request *req)
4479abd5f05SSebastian Hesselbarth {
4489abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
4499abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
45008add3c1SMaxime Ripard unsigned long rate = req->rate;
4519abd5f05SSebastian Hesselbarth unsigned long rfrac, denom, a, b, c;
4529abd5f05SSebastian Hesselbarth unsigned long long lltmp;
4539abd5f05SSebastian Hesselbarth
4549abd5f05SSebastian Hesselbarth if (rate < SI5351_PLL_VCO_MIN)
4559abd5f05SSebastian Hesselbarth rate = SI5351_PLL_VCO_MIN;
4569abd5f05SSebastian Hesselbarth if (rate > SI5351_PLL_VCO_MAX)
4579abd5f05SSebastian Hesselbarth rate = SI5351_PLL_VCO_MAX;
4589abd5f05SSebastian Hesselbarth
4599abd5f05SSebastian Hesselbarth /* determine integer part of feedback equation */
46008add3c1SMaxime Ripard a = rate / req->best_parent_rate;
4619abd5f05SSebastian Hesselbarth
4629abd5f05SSebastian Hesselbarth if (a < SI5351_PLL_A_MIN)
46308add3c1SMaxime Ripard rate = req->best_parent_rate * SI5351_PLL_A_MIN;
4649abd5f05SSebastian Hesselbarth if (a > SI5351_PLL_A_MAX)
46508add3c1SMaxime Ripard rate = req->best_parent_rate * SI5351_PLL_A_MAX;
4669abd5f05SSebastian Hesselbarth
4679abd5f05SSebastian Hesselbarth /* find best approximation for b/c = fVCO mod fIN */
4689abd5f05SSebastian Hesselbarth denom = 1000 * 1000;
46908add3c1SMaxime Ripard lltmp = rate % (req->best_parent_rate);
4709abd5f05SSebastian Hesselbarth lltmp *= denom;
47108add3c1SMaxime Ripard do_div(lltmp, req->best_parent_rate);
4729abd5f05SSebastian Hesselbarth rfrac = (unsigned long)lltmp;
4739abd5f05SSebastian Hesselbarth
4749abd5f05SSebastian Hesselbarth b = 0;
4759abd5f05SSebastian Hesselbarth c = 1;
4769abd5f05SSebastian Hesselbarth if (rfrac)
4779abd5f05SSebastian Hesselbarth rational_best_approximation(rfrac, denom,
4789abd5f05SSebastian Hesselbarth SI5351_PLL_B_MAX, SI5351_PLL_C_MAX, &b, &c);
4799abd5f05SSebastian Hesselbarth
4809abd5f05SSebastian Hesselbarth /* calculate parameters */
4819abd5f05SSebastian Hesselbarth hwdata->params.p3 = c;
4829abd5f05SSebastian Hesselbarth hwdata->params.p2 = (128 * b) % c;
4839abd5f05SSebastian Hesselbarth hwdata->params.p1 = 128 * a;
4849abd5f05SSebastian Hesselbarth hwdata->params.p1 += (128 * b / c);
4859abd5f05SSebastian Hesselbarth hwdata->params.p1 -= 512;
4869abd5f05SSebastian Hesselbarth
4879abd5f05SSebastian Hesselbarth /* recalculate rate by fIN * (a + b/c) */
48808add3c1SMaxime Ripard lltmp = req->best_parent_rate;
4899abd5f05SSebastian Hesselbarth lltmp *= b;
4909abd5f05SSebastian Hesselbarth do_div(lltmp, c);
4919abd5f05SSebastian Hesselbarth
4929abd5f05SSebastian Hesselbarth rate = (unsigned long)lltmp;
49308add3c1SMaxime Ripard rate += req->best_parent_rate * a;
4949abd5f05SSebastian Hesselbarth
4959abd5f05SSebastian Hesselbarth dev_dbg(&hwdata->drvdata->client->dev,
4969abd5f05SSebastian Hesselbarth "%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = %lu\n",
49744f22a5dSStephen Boyd __func__, clk_hw_get_name(hw), a, b, c,
49808add3c1SMaxime Ripard req->best_parent_rate, rate);
4999abd5f05SSebastian Hesselbarth
50008add3c1SMaxime Ripard req->rate = rate;
50108add3c1SMaxime Ripard return 0;
5029abd5f05SSebastian Hesselbarth }
5039abd5f05SSebastian Hesselbarth
si5351_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)5049abd5f05SSebastian Hesselbarth static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
5059abd5f05SSebastian Hesselbarth unsigned long parent_rate)
5069abd5f05SSebastian Hesselbarth {
5079abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
5089abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
5098b84c2ceSAlvin Šipraga struct si5351_platform_data *pdata =
5108b84c2ceSAlvin Šipraga hwdata->drvdata->client->dev.platform_data;
5119abd5f05SSebastian Hesselbarth u8 reg = (hwdata->num == 0) ? SI5351_PLLA_PARAMETERS :
5129abd5f05SSebastian Hesselbarth SI5351_PLLB_PARAMETERS;
5139abd5f05SSebastian Hesselbarth
5149abd5f05SSebastian Hesselbarth /* write multisynth parameters */
5159abd5f05SSebastian Hesselbarth si5351_write_parameters(hwdata->drvdata, reg, &hwdata->params);
5169abd5f05SSebastian Hesselbarth
5179abd5f05SSebastian Hesselbarth /* plla/pllb ctrl is in clk6/clk7 ctrl registers */
5189abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_CLK6_CTRL + hwdata->num,
5199abd5f05SSebastian Hesselbarth SI5351_CLK_INTEGER_MODE,
5209abd5f05SSebastian Hesselbarth (hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0);
5219abd5f05SSebastian Hesselbarth
52273c950daSRussell King /* Do a pll soft reset on the affected pll */
5238b84c2ceSAlvin Šipraga if (pdata->pll_reset[hwdata->num])
52473c950daSRussell King si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET,
52573c950daSRussell King hwdata->num == 0 ? SI5351_PLL_RESET_A :
52673c950daSRussell King SI5351_PLL_RESET_B);
52773c950daSRussell King
5289abd5f05SSebastian Hesselbarth dev_dbg(&hwdata->drvdata->client->dev,
5299abd5f05SSebastian Hesselbarth "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
53044f22a5dSStephen Boyd __func__, clk_hw_get_name(hw),
5319abd5f05SSebastian Hesselbarth hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
5329abd5f05SSebastian Hesselbarth parent_rate, rate);
5339abd5f05SSebastian Hesselbarth
5349abd5f05SSebastian Hesselbarth return 0;
5359abd5f05SSebastian Hesselbarth }
5369abd5f05SSebastian Hesselbarth
5379abd5f05SSebastian Hesselbarth static const struct clk_ops si5351_pll_ops = {
5389abd5f05SSebastian Hesselbarth .set_parent = si5351_pll_set_parent,
5399abd5f05SSebastian Hesselbarth .get_parent = si5351_pll_get_parent,
5409abd5f05SSebastian Hesselbarth .recalc_rate = si5351_pll_recalc_rate,
54108add3c1SMaxime Ripard .determine_rate = si5351_pll_determine_rate,
5429abd5f05SSebastian Hesselbarth .set_rate = si5351_pll_set_rate,
5439abd5f05SSebastian Hesselbarth };
5449abd5f05SSebastian Hesselbarth
5459abd5f05SSebastian Hesselbarth /*
5469abd5f05SSebastian Hesselbarth * Si5351 multisync divider
5479abd5f05SSebastian Hesselbarth *
5489abd5f05SSebastian Hesselbarth * for fOUT <= 150 MHz:
5499abd5f05SSebastian Hesselbarth *
5509abd5f05SSebastian Hesselbarth * fOUT = (fIN * (a + b/c)) / CLKOUTDIV
5519abd5f05SSebastian Hesselbarth *
5529abd5f05SSebastian Hesselbarth * with 6 + 0/1048575 <= (a + b/c) <= 1800 + 0/1048575 and
5539abd5f05SSebastian Hesselbarth * fIN = fVCO0, fVCO1
5549abd5f05SSebastian Hesselbarth *
5559abd5f05SSebastian Hesselbarth * Output Clock Multisynth Register Equations
5569abd5f05SSebastian Hesselbarth *
5579abd5f05SSebastian Hesselbarth * MSx_P1[17:0] = 128 * a + floor(128 * b/c) - 512
5589abd5f05SSebastian Hesselbarth * MSx_P2[19:0] = 128 * b - c * floor(128 * b/c) = (128*b) mod c
5599abd5f05SSebastian Hesselbarth * MSx_P3[19:0] = c
5609abd5f05SSebastian Hesselbarth *
5612073b5e9SSergej Sawazki * MS[6,7] are integer (P1) divide only, P1 = divide value,
5622073b5e9SSergej Sawazki * P2 and P3 are not applicable
5639abd5f05SSebastian Hesselbarth *
5649abd5f05SSebastian Hesselbarth * for 150MHz < fOUT <= 160MHz:
5659abd5f05SSebastian Hesselbarth *
5669abd5f05SSebastian Hesselbarth * MSx_P1 = 0, MSx_P2 = 0, MSx_P3 = 1, MSx_INT = 1, MSx_DIVBY4 = 11b
5679abd5f05SSebastian Hesselbarth */
_si5351_msynth_reparent(struct si5351_driver_data * drvdata,int num,enum si5351_multisynth_src parent)5689abd5f05SSebastian Hesselbarth static int _si5351_msynth_reparent(struct si5351_driver_data *drvdata,
5699abd5f05SSebastian Hesselbarth int num, enum si5351_multisynth_src parent)
5709abd5f05SSebastian Hesselbarth {
5719abd5f05SSebastian Hesselbarth if (parent == SI5351_MULTISYNTH_SRC_DEFAULT)
5729abd5f05SSebastian Hesselbarth return 0;
5739abd5f05SSebastian Hesselbarth
5749abd5f05SSebastian Hesselbarth if (num > 8)
5759abd5f05SSebastian Hesselbarth return -EINVAL;
5769abd5f05SSebastian Hesselbarth
5779abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_CLK0_CTRL + num, SI5351_CLK_PLL_SELECT,
5789abd5f05SSebastian Hesselbarth (parent == SI5351_MULTISYNTH_SRC_VCO0) ? 0 :
5799abd5f05SSebastian Hesselbarth SI5351_CLK_PLL_SELECT);
5809abd5f05SSebastian Hesselbarth return 0;
5819abd5f05SSebastian Hesselbarth }
5829abd5f05SSebastian Hesselbarth
si5351_msynth_get_parent(struct clk_hw * hw)5839abd5f05SSebastian Hesselbarth static unsigned char si5351_msynth_get_parent(struct clk_hw *hw)
5849abd5f05SSebastian Hesselbarth {
5859abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
5869abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
5879abd5f05SSebastian Hesselbarth u8 val;
5889abd5f05SSebastian Hesselbarth
5899abd5f05SSebastian Hesselbarth val = si5351_reg_read(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num);
5909abd5f05SSebastian Hesselbarth
5919abd5f05SSebastian Hesselbarth return (val & SI5351_CLK_PLL_SELECT) ? 1 : 0;
5929abd5f05SSebastian Hesselbarth }
5939abd5f05SSebastian Hesselbarth
si5351_msynth_set_parent(struct clk_hw * hw,u8 index)5949abd5f05SSebastian Hesselbarth static int si5351_msynth_set_parent(struct clk_hw *hw, u8 index)
5959abd5f05SSebastian Hesselbarth {
5969abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
5979abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
5989abd5f05SSebastian Hesselbarth
5999abd5f05SSebastian Hesselbarth return _si5351_msynth_reparent(hwdata->drvdata, hwdata->num,
6009abd5f05SSebastian Hesselbarth (index == 0) ? SI5351_MULTISYNTH_SRC_VCO0 :
6019abd5f05SSebastian Hesselbarth SI5351_MULTISYNTH_SRC_VCO1);
6029abd5f05SSebastian Hesselbarth }
6039abd5f05SSebastian Hesselbarth
si5351_msynth_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)6049abd5f05SSebastian Hesselbarth static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
6059abd5f05SSebastian Hesselbarth unsigned long parent_rate)
6069abd5f05SSebastian Hesselbarth {
6079abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
6089abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
6099abd5f05SSebastian Hesselbarth u8 reg = si5351_msynth_params_address(hwdata->num);
6109abd5f05SSebastian Hesselbarth unsigned long long rate;
6119abd5f05SSebastian Hesselbarth unsigned long m;
6129abd5f05SSebastian Hesselbarth
6139abd5f05SSebastian Hesselbarth if (!hwdata->params.valid)
6149abd5f05SSebastian Hesselbarth si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params);
6159abd5f05SSebastian Hesselbarth
6169abd5f05SSebastian Hesselbarth /*
6179abd5f05SSebastian Hesselbarth * multisync0-5: fOUT = (128 * P3 * fIN) / (P1*P3 + P2 + 512*P3)
6189abd5f05SSebastian Hesselbarth * multisync6-7: fOUT = fIN / P1
6199abd5f05SSebastian Hesselbarth */
6209abd5f05SSebastian Hesselbarth rate = parent_rate;
6219abd5f05SSebastian Hesselbarth if (hwdata->num > 5) {
6229abd5f05SSebastian Hesselbarth m = hwdata->params.p1;
62345b03d3eSSergej Sawazki } else if (hwdata->params.p3 == 0) {
62445b03d3eSSergej Sawazki return parent_rate;
6259abd5f05SSebastian Hesselbarth } else if ((si5351_reg_read(hwdata->drvdata, reg + 2) &
6269abd5f05SSebastian Hesselbarth SI5351_OUTPUT_CLK_DIVBY4) == SI5351_OUTPUT_CLK_DIVBY4) {
6279abd5f05SSebastian Hesselbarth m = 4;
6289abd5f05SSebastian Hesselbarth } else {
6299abd5f05SSebastian Hesselbarth rate *= 128 * hwdata->params.p3;
6309abd5f05SSebastian Hesselbarth m = hwdata->params.p1 * hwdata->params.p3;
6319abd5f05SSebastian Hesselbarth m += hwdata->params.p2;
6329abd5f05SSebastian Hesselbarth m += 512 * hwdata->params.p3;
6339abd5f05SSebastian Hesselbarth }
6349abd5f05SSebastian Hesselbarth
6359abd5f05SSebastian Hesselbarth if (m == 0)
6369abd5f05SSebastian Hesselbarth return 0;
6379abd5f05SSebastian Hesselbarth do_div(rate, m);
6389abd5f05SSebastian Hesselbarth
6399abd5f05SSebastian Hesselbarth dev_dbg(&hwdata->drvdata->client->dev,
6409abd5f05SSebastian Hesselbarth "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, m = %lu, parent_rate = %lu, rate = %lu\n",
64144f22a5dSStephen Boyd __func__, clk_hw_get_name(hw),
6429abd5f05SSebastian Hesselbarth hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
6439abd5f05SSebastian Hesselbarth m, parent_rate, (unsigned long)rate);
6449abd5f05SSebastian Hesselbarth
6459abd5f05SSebastian Hesselbarth return (unsigned long)rate;
6469abd5f05SSebastian Hesselbarth }
6479abd5f05SSebastian Hesselbarth
si5351_msynth_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)6484ab2bf81SMaxime Ripard static int si5351_msynth_determine_rate(struct clk_hw *hw,
6494ab2bf81SMaxime Ripard struct clk_rate_request *req)
6509abd5f05SSebastian Hesselbarth {
6519abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
6529abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
6534ab2bf81SMaxime Ripard unsigned long rate = req->rate;
6549abd5f05SSebastian Hesselbarth unsigned long long lltmp;
6559abd5f05SSebastian Hesselbarth unsigned long a, b, c;
6569abd5f05SSebastian Hesselbarth int divby4;
6579abd5f05SSebastian Hesselbarth
6589abd5f05SSebastian Hesselbarth /* multisync6-7 can only handle freqencies < 150MHz */
6599abd5f05SSebastian Hesselbarth if (hwdata->num >= 6 && rate > SI5351_MULTISYNTH67_MAX_FREQ)
6609abd5f05SSebastian Hesselbarth rate = SI5351_MULTISYNTH67_MAX_FREQ;
6619abd5f05SSebastian Hesselbarth
6629abd5f05SSebastian Hesselbarth /* multisync frequency is 1MHz .. 160MHz */
6639abd5f05SSebastian Hesselbarth if (rate > SI5351_MULTISYNTH_MAX_FREQ)
6649abd5f05SSebastian Hesselbarth rate = SI5351_MULTISYNTH_MAX_FREQ;
6659abd5f05SSebastian Hesselbarth if (rate < SI5351_MULTISYNTH_MIN_FREQ)
6669abd5f05SSebastian Hesselbarth rate = SI5351_MULTISYNTH_MIN_FREQ;
6679abd5f05SSebastian Hesselbarth
6689abd5f05SSebastian Hesselbarth divby4 = 0;
6699abd5f05SSebastian Hesselbarth if (rate > SI5351_MULTISYNTH_DIVBY4_FREQ)
6709abd5f05SSebastian Hesselbarth divby4 = 1;
6719abd5f05SSebastian Hesselbarth
6729abd5f05SSebastian Hesselbarth /* multisync can set pll */
67398d8a60eSStephen Boyd if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
6749abd5f05SSebastian Hesselbarth /*
6759abd5f05SSebastian Hesselbarth * find largest integer divider for max
6769abd5f05SSebastian Hesselbarth * vco frequency and given target rate
6779abd5f05SSebastian Hesselbarth */
6789abd5f05SSebastian Hesselbarth if (divby4 == 0) {
6799abd5f05SSebastian Hesselbarth lltmp = SI5351_PLL_VCO_MAX;
6809abd5f05SSebastian Hesselbarth do_div(lltmp, rate);
6819abd5f05SSebastian Hesselbarth a = (unsigned long)lltmp;
6829abd5f05SSebastian Hesselbarth } else
6839abd5f05SSebastian Hesselbarth a = 4;
6849abd5f05SSebastian Hesselbarth
6859abd5f05SSebastian Hesselbarth b = 0;
6869abd5f05SSebastian Hesselbarth c = 1;
6879abd5f05SSebastian Hesselbarth
6884ab2bf81SMaxime Ripard req->best_parent_rate = a * rate;
6892073b5e9SSergej Sawazki } else if (hwdata->num >= 6) {
6902073b5e9SSergej Sawazki /* determine the closest integer divider */
6914ab2bf81SMaxime Ripard a = DIV_ROUND_CLOSEST(req->best_parent_rate, rate);
6922073b5e9SSergej Sawazki if (a < SI5351_MULTISYNTH_A_MIN)
6932073b5e9SSergej Sawazki a = SI5351_MULTISYNTH_A_MIN;
6942073b5e9SSergej Sawazki if (a > SI5351_MULTISYNTH67_A_MAX)
6952073b5e9SSergej Sawazki a = SI5351_MULTISYNTH67_A_MAX;
6962073b5e9SSergej Sawazki
6972073b5e9SSergej Sawazki b = 0;
6982073b5e9SSergej Sawazki c = 1;
6999abd5f05SSebastian Hesselbarth } else {
7009abd5f05SSebastian Hesselbarth unsigned long rfrac, denom;
7019abd5f05SSebastian Hesselbarth
7029abd5f05SSebastian Hesselbarth /* disable divby4 */
7039abd5f05SSebastian Hesselbarth if (divby4) {
7049abd5f05SSebastian Hesselbarth rate = SI5351_MULTISYNTH_DIVBY4_FREQ;
7059abd5f05SSebastian Hesselbarth divby4 = 0;
7069abd5f05SSebastian Hesselbarth }
7079abd5f05SSebastian Hesselbarth
7089abd5f05SSebastian Hesselbarth /* determine integer part of divider equation */
7094ab2bf81SMaxime Ripard a = req->best_parent_rate / rate;
7109abd5f05SSebastian Hesselbarth if (a < SI5351_MULTISYNTH_A_MIN)
7119abd5f05SSebastian Hesselbarth a = SI5351_MULTISYNTH_A_MIN;
7122073b5e9SSergej Sawazki if (a > SI5351_MULTISYNTH_A_MAX)
7139abd5f05SSebastian Hesselbarth a = SI5351_MULTISYNTH_A_MAX;
7149abd5f05SSebastian Hesselbarth
7159abd5f05SSebastian Hesselbarth /* find best approximation for b/c = fVCO mod fOUT */
7169abd5f05SSebastian Hesselbarth denom = 1000 * 1000;
7174ab2bf81SMaxime Ripard lltmp = req->best_parent_rate % rate;
7189abd5f05SSebastian Hesselbarth lltmp *= denom;
7199abd5f05SSebastian Hesselbarth do_div(lltmp, rate);
7209abd5f05SSebastian Hesselbarth rfrac = (unsigned long)lltmp;
7219abd5f05SSebastian Hesselbarth
7229abd5f05SSebastian Hesselbarth b = 0;
7239abd5f05SSebastian Hesselbarth c = 1;
7249abd5f05SSebastian Hesselbarth if (rfrac)
7259abd5f05SSebastian Hesselbarth rational_best_approximation(rfrac, denom,
7269abd5f05SSebastian Hesselbarth SI5351_MULTISYNTH_B_MAX, SI5351_MULTISYNTH_C_MAX,
7279abd5f05SSebastian Hesselbarth &b, &c);
7289abd5f05SSebastian Hesselbarth }
7299abd5f05SSebastian Hesselbarth
7309abd5f05SSebastian Hesselbarth /* recalculate rate by fOUT = fIN / (a + b/c) */
7314ab2bf81SMaxime Ripard lltmp = req->best_parent_rate;
7329abd5f05SSebastian Hesselbarth lltmp *= c;
7339abd5f05SSebastian Hesselbarth do_div(lltmp, a * c + b);
7349abd5f05SSebastian Hesselbarth rate = (unsigned long)lltmp;
7359abd5f05SSebastian Hesselbarth
7369abd5f05SSebastian Hesselbarth /* calculate parameters */
7379abd5f05SSebastian Hesselbarth if (divby4) {
7389abd5f05SSebastian Hesselbarth hwdata->params.p3 = 1;
7399abd5f05SSebastian Hesselbarth hwdata->params.p2 = 0;
7409abd5f05SSebastian Hesselbarth hwdata->params.p1 = 0;
7412073b5e9SSergej Sawazki } else if (hwdata->num >= 6) {
7422073b5e9SSergej Sawazki hwdata->params.p3 = 0;
7432073b5e9SSergej Sawazki hwdata->params.p2 = 0;
7442073b5e9SSergej Sawazki hwdata->params.p1 = a;
7459abd5f05SSebastian Hesselbarth } else {
7469abd5f05SSebastian Hesselbarth hwdata->params.p3 = c;
7479abd5f05SSebastian Hesselbarth hwdata->params.p2 = (128 * b) % c;
7489abd5f05SSebastian Hesselbarth hwdata->params.p1 = 128 * a;
7499abd5f05SSebastian Hesselbarth hwdata->params.p1 += (128 * b / c);
7509abd5f05SSebastian Hesselbarth hwdata->params.p1 -= 512;
7519abd5f05SSebastian Hesselbarth }
7529abd5f05SSebastian Hesselbarth
7539abd5f05SSebastian Hesselbarth dev_dbg(&hwdata->drvdata->client->dev,
7549abd5f05SSebastian Hesselbarth "%s - %s: a = %lu, b = %lu, c = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
75544f22a5dSStephen Boyd __func__, clk_hw_get_name(hw), a, b, c, divby4,
7564ab2bf81SMaxime Ripard req->best_parent_rate, rate);
7579abd5f05SSebastian Hesselbarth
7584ab2bf81SMaxime Ripard req->rate = rate;
7594ab2bf81SMaxime Ripard
7604ab2bf81SMaxime Ripard return 0;
7619abd5f05SSebastian Hesselbarth }
7629abd5f05SSebastian Hesselbarth
si5351_msynth_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)7639abd5f05SSebastian Hesselbarth static int si5351_msynth_set_rate(struct clk_hw *hw, unsigned long rate,
7649abd5f05SSebastian Hesselbarth unsigned long parent_rate)
7659abd5f05SSebastian Hesselbarth {
7669abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
7679abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
7689abd5f05SSebastian Hesselbarth u8 reg = si5351_msynth_params_address(hwdata->num);
7699abd5f05SSebastian Hesselbarth int divby4 = 0;
7709abd5f05SSebastian Hesselbarth
7719abd5f05SSebastian Hesselbarth /* write multisynth parameters */
7729abd5f05SSebastian Hesselbarth si5351_write_parameters(hwdata->drvdata, reg, &hwdata->params);
7739abd5f05SSebastian Hesselbarth
7749abd5f05SSebastian Hesselbarth if (rate > SI5351_MULTISYNTH_DIVBY4_FREQ)
7759abd5f05SSebastian Hesselbarth divby4 = 1;
7769abd5f05SSebastian Hesselbarth
7779abd5f05SSebastian Hesselbarth /* enable/disable integer mode and divby4 on multisynth0-5 */
7789abd5f05SSebastian Hesselbarth if (hwdata->num < 6) {
7799abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, reg + 2,
7809abd5f05SSebastian Hesselbarth SI5351_OUTPUT_CLK_DIVBY4,
7819abd5f05SSebastian Hesselbarth (divby4) ? SI5351_OUTPUT_CLK_DIVBY4 : 0);
7829abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num,
7839abd5f05SSebastian Hesselbarth SI5351_CLK_INTEGER_MODE,
7849abd5f05SSebastian Hesselbarth (hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0);
7859abd5f05SSebastian Hesselbarth }
7869abd5f05SSebastian Hesselbarth
7879abd5f05SSebastian Hesselbarth dev_dbg(&hwdata->drvdata->client->dev,
7889abd5f05SSebastian Hesselbarth "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
78944f22a5dSStephen Boyd __func__, clk_hw_get_name(hw),
7909abd5f05SSebastian Hesselbarth hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
7919abd5f05SSebastian Hesselbarth divby4, parent_rate, rate);
7929abd5f05SSebastian Hesselbarth
7939abd5f05SSebastian Hesselbarth return 0;
7949abd5f05SSebastian Hesselbarth }
7959abd5f05SSebastian Hesselbarth
7969abd5f05SSebastian Hesselbarth static const struct clk_ops si5351_msynth_ops = {
7979abd5f05SSebastian Hesselbarth .set_parent = si5351_msynth_set_parent,
7989abd5f05SSebastian Hesselbarth .get_parent = si5351_msynth_get_parent,
7999abd5f05SSebastian Hesselbarth .recalc_rate = si5351_msynth_recalc_rate,
8004ab2bf81SMaxime Ripard .determine_rate = si5351_msynth_determine_rate,
8019abd5f05SSebastian Hesselbarth .set_rate = si5351_msynth_set_rate,
8029abd5f05SSebastian Hesselbarth };
8039abd5f05SSebastian Hesselbarth
8049abd5f05SSebastian Hesselbarth /*
8059abd5f05SSebastian Hesselbarth * Si5351 clkout divider
8069abd5f05SSebastian Hesselbarth */
_si5351_clkout_reparent(struct si5351_driver_data * drvdata,int num,enum si5351_clkout_src parent)8079abd5f05SSebastian Hesselbarth static int _si5351_clkout_reparent(struct si5351_driver_data *drvdata,
8089abd5f05SSebastian Hesselbarth int num, enum si5351_clkout_src parent)
8099abd5f05SSebastian Hesselbarth {
8109abd5f05SSebastian Hesselbarth u8 val;
8119abd5f05SSebastian Hesselbarth
8129abd5f05SSebastian Hesselbarth if (num > 8)
8139abd5f05SSebastian Hesselbarth return -EINVAL;
8149abd5f05SSebastian Hesselbarth
8159abd5f05SSebastian Hesselbarth switch (parent) {
8169abd5f05SSebastian Hesselbarth case SI5351_CLKOUT_SRC_MSYNTH_N:
8179abd5f05SSebastian Hesselbarth val = SI5351_CLK_INPUT_MULTISYNTH_N;
8189abd5f05SSebastian Hesselbarth break;
8199abd5f05SSebastian Hesselbarth case SI5351_CLKOUT_SRC_MSYNTH_0_4:
8209abd5f05SSebastian Hesselbarth /* clk0/clk4 can only connect to its own multisync */
8219abd5f05SSebastian Hesselbarth if (num == 0 || num == 4)
8229abd5f05SSebastian Hesselbarth val = SI5351_CLK_INPUT_MULTISYNTH_N;
8239abd5f05SSebastian Hesselbarth else
8249abd5f05SSebastian Hesselbarth val = SI5351_CLK_INPUT_MULTISYNTH_0_4;
8259abd5f05SSebastian Hesselbarth break;
8269abd5f05SSebastian Hesselbarth case SI5351_CLKOUT_SRC_XTAL:
8279abd5f05SSebastian Hesselbarth val = SI5351_CLK_INPUT_XTAL;
8289abd5f05SSebastian Hesselbarth break;
8299abd5f05SSebastian Hesselbarth case SI5351_CLKOUT_SRC_CLKIN:
8309abd5f05SSebastian Hesselbarth if (drvdata->variant != SI5351_VARIANT_C)
8319abd5f05SSebastian Hesselbarth return -EINVAL;
8329abd5f05SSebastian Hesselbarth
8339abd5f05SSebastian Hesselbarth val = SI5351_CLK_INPUT_CLKIN;
8349abd5f05SSebastian Hesselbarth break;
8359abd5f05SSebastian Hesselbarth default:
8369abd5f05SSebastian Hesselbarth return 0;
8379abd5f05SSebastian Hesselbarth }
8389abd5f05SSebastian Hesselbarth
8399abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_CLK0_CTRL + num,
8409abd5f05SSebastian Hesselbarth SI5351_CLK_INPUT_MASK, val);
8419abd5f05SSebastian Hesselbarth return 0;
8429abd5f05SSebastian Hesselbarth }
8439abd5f05SSebastian Hesselbarth
_si5351_clkout_set_drive_strength(struct si5351_driver_data * drvdata,int num,enum si5351_drive_strength drive)8449abd5f05SSebastian Hesselbarth static int _si5351_clkout_set_drive_strength(
8459abd5f05SSebastian Hesselbarth struct si5351_driver_data *drvdata, int num,
8469abd5f05SSebastian Hesselbarth enum si5351_drive_strength drive)
8479abd5f05SSebastian Hesselbarth {
8489abd5f05SSebastian Hesselbarth u8 mask;
8499abd5f05SSebastian Hesselbarth
8509abd5f05SSebastian Hesselbarth if (num > 8)
8519abd5f05SSebastian Hesselbarth return -EINVAL;
8529abd5f05SSebastian Hesselbarth
8539abd5f05SSebastian Hesselbarth switch (drive) {
8549abd5f05SSebastian Hesselbarth case SI5351_DRIVE_2MA:
8559abd5f05SSebastian Hesselbarth mask = SI5351_CLK_DRIVE_STRENGTH_2MA;
8569abd5f05SSebastian Hesselbarth break;
8579abd5f05SSebastian Hesselbarth case SI5351_DRIVE_4MA:
8589abd5f05SSebastian Hesselbarth mask = SI5351_CLK_DRIVE_STRENGTH_4MA;
8599abd5f05SSebastian Hesselbarth break;
8609abd5f05SSebastian Hesselbarth case SI5351_DRIVE_6MA:
8619abd5f05SSebastian Hesselbarth mask = SI5351_CLK_DRIVE_STRENGTH_6MA;
8629abd5f05SSebastian Hesselbarth break;
8639abd5f05SSebastian Hesselbarth case SI5351_DRIVE_8MA:
8649abd5f05SSebastian Hesselbarth mask = SI5351_CLK_DRIVE_STRENGTH_8MA;
8659abd5f05SSebastian Hesselbarth break;
8669abd5f05SSebastian Hesselbarth default:
8679abd5f05SSebastian Hesselbarth return 0;
8689abd5f05SSebastian Hesselbarth }
8699abd5f05SSebastian Hesselbarth
8709abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_CLK0_CTRL + num,
8719abd5f05SSebastian Hesselbarth SI5351_CLK_DRIVE_STRENGTH_MASK, mask);
8729abd5f05SSebastian Hesselbarth return 0;
8739abd5f05SSebastian Hesselbarth }
8749abd5f05SSebastian Hesselbarth
_si5351_clkout_set_disable_state(struct si5351_driver_data * drvdata,int num,enum si5351_disable_state state)8751a0483d2SSebastian Hesselbarth static int _si5351_clkout_set_disable_state(
8761a0483d2SSebastian Hesselbarth struct si5351_driver_data *drvdata, int num,
8771a0483d2SSebastian Hesselbarth enum si5351_disable_state state)
8781a0483d2SSebastian Hesselbarth {
8791a0483d2SSebastian Hesselbarth u8 reg = (num < 4) ? SI5351_CLK3_0_DISABLE_STATE :
8801a0483d2SSebastian Hesselbarth SI5351_CLK7_4_DISABLE_STATE;
8811a0483d2SSebastian Hesselbarth u8 shift = (num < 4) ? (2 * num) : (2 * (num-4));
8821a0483d2SSebastian Hesselbarth u8 mask = SI5351_CLK_DISABLE_STATE_MASK << shift;
8831a0483d2SSebastian Hesselbarth u8 val;
8841a0483d2SSebastian Hesselbarth
8851a0483d2SSebastian Hesselbarth if (num > 8)
8861a0483d2SSebastian Hesselbarth return -EINVAL;
8871a0483d2SSebastian Hesselbarth
8881a0483d2SSebastian Hesselbarth switch (state) {
8891a0483d2SSebastian Hesselbarth case SI5351_DISABLE_LOW:
8901a0483d2SSebastian Hesselbarth val = SI5351_CLK_DISABLE_STATE_LOW;
8911a0483d2SSebastian Hesselbarth break;
8921a0483d2SSebastian Hesselbarth case SI5351_DISABLE_HIGH:
8931a0483d2SSebastian Hesselbarth val = SI5351_CLK_DISABLE_STATE_HIGH;
8941a0483d2SSebastian Hesselbarth break;
8951a0483d2SSebastian Hesselbarth case SI5351_DISABLE_FLOATING:
8961a0483d2SSebastian Hesselbarth val = SI5351_CLK_DISABLE_STATE_FLOAT;
8971a0483d2SSebastian Hesselbarth break;
8981a0483d2SSebastian Hesselbarth case SI5351_DISABLE_NEVER:
8991a0483d2SSebastian Hesselbarth val = SI5351_CLK_DISABLE_STATE_NEVER;
9001a0483d2SSebastian Hesselbarth break;
9011a0483d2SSebastian Hesselbarth default:
9021a0483d2SSebastian Hesselbarth return 0;
9031a0483d2SSebastian Hesselbarth }
9041a0483d2SSebastian Hesselbarth
9051a0483d2SSebastian Hesselbarth si5351_set_bits(drvdata, reg, mask, val << shift);
9061a0483d2SSebastian Hesselbarth
9071a0483d2SSebastian Hesselbarth return 0;
9081a0483d2SSebastian Hesselbarth }
9091a0483d2SSebastian Hesselbarth
_si5351_clkout_reset_pll(struct si5351_driver_data * drvdata,int num)9100136f852SWu Fengguang static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num)
911b26ff127SSergej Sawazki {
912b26ff127SSergej Sawazki u8 val = si5351_reg_read(drvdata, SI5351_CLK0_CTRL + num);
9135142cbceSSascha Hauer u8 mask = val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B :
9145142cbceSSascha Hauer SI5351_PLL_RESET_A;
9155142cbceSSascha Hauer unsigned int v;
9165142cbceSSascha Hauer int err;
917b26ff127SSergej Sawazki
918b26ff127SSergej Sawazki switch (val & SI5351_CLK_INPUT_MASK) {
919b26ff127SSergej Sawazki case SI5351_CLK_INPUT_XTAL:
920b26ff127SSergej Sawazki case SI5351_CLK_INPUT_CLKIN:
921b26ff127SSergej Sawazki return; /* pll not used, no need to reset */
922b26ff127SSergej Sawazki }
923b26ff127SSergej Sawazki
9245142cbceSSascha Hauer si5351_reg_write(drvdata, SI5351_PLL_RESET, mask);
9255142cbceSSascha Hauer
9265142cbceSSascha Hauer err = regmap_read_poll_timeout(drvdata->regmap, SI5351_PLL_RESET, v,
9275142cbceSSascha Hauer !(v & mask), 0, 20000);
9285142cbceSSascha Hauer if (err < 0)
9295142cbceSSascha Hauer dev_err(&drvdata->client->dev, "Reset bit didn't clear\n");
930b26ff127SSergej Sawazki
931b26ff127SSergej Sawazki dev_dbg(&drvdata->client->dev, "%s - %s: pll = %d\n",
932b26ff127SSergej Sawazki __func__, clk_hw_get_name(&drvdata->clkout[num].hw),
933b26ff127SSergej Sawazki (val & SI5351_CLK_PLL_SELECT) ? 1 : 0);
934b26ff127SSergej Sawazki }
935b26ff127SSergej Sawazki
si5351_clkout_prepare(struct clk_hw * hw)9369abd5f05SSebastian Hesselbarth static int si5351_clkout_prepare(struct clk_hw *hw)
9379abd5f05SSebastian Hesselbarth {
9389abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
9399abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
940b26ff127SSergej Sawazki struct si5351_platform_data *pdata =
941b26ff127SSergej Sawazki hwdata->drvdata->client->dev.platform_data;
9429abd5f05SSebastian Hesselbarth
9439abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num,
9449abd5f05SSebastian Hesselbarth SI5351_CLK_POWERDOWN, 0);
945b26ff127SSergej Sawazki
946b26ff127SSergej Sawazki /*
947b26ff127SSergej Sawazki * Do a pll soft reset on the parent pll -- needed to get a
948b26ff127SSergej Sawazki * deterministic phase relationship between the output clocks.
949b26ff127SSergej Sawazki */
950b26ff127SSergej Sawazki if (pdata->clkout[hwdata->num].pll_reset)
951b26ff127SSergej Sawazki _si5351_clkout_reset_pll(hwdata->drvdata, hwdata->num);
952b26ff127SSergej Sawazki
9539abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_OUTPUT_ENABLE_CTRL,
9549abd5f05SSebastian Hesselbarth (1 << hwdata->num), 0);
9559abd5f05SSebastian Hesselbarth return 0;
9569abd5f05SSebastian Hesselbarth }
9579abd5f05SSebastian Hesselbarth
si5351_clkout_unprepare(struct clk_hw * hw)9589abd5f05SSebastian Hesselbarth static void si5351_clkout_unprepare(struct clk_hw *hw)
9599abd5f05SSebastian Hesselbarth {
9609abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
9619abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
9629abd5f05SSebastian Hesselbarth
9639abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num,
9649abd5f05SSebastian Hesselbarth SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN);
9659abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_OUTPUT_ENABLE_CTRL,
9669abd5f05SSebastian Hesselbarth (1 << hwdata->num), (1 << hwdata->num));
9679abd5f05SSebastian Hesselbarth }
9689abd5f05SSebastian Hesselbarth
si5351_clkout_get_parent(struct clk_hw * hw)9699abd5f05SSebastian Hesselbarth static u8 si5351_clkout_get_parent(struct clk_hw *hw)
9709abd5f05SSebastian Hesselbarth {
9719abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
9729abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
9739abd5f05SSebastian Hesselbarth int index = 0;
9749abd5f05SSebastian Hesselbarth unsigned char val;
9759abd5f05SSebastian Hesselbarth
9769abd5f05SSebastian Hesselbarth val = si5351_reg_read(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num);
9779abd5f05SSebastian Hesselbarth switch (val & SI5351_CLK_INPUT_MASK) {
9789abd5f05SSebastian Hesselbarth case SI5351_CLK_INPUT_MULTISYNTH_N:
9799abd5f05SSebastian Hesselbarth index = 0;
9809abd5f05SSebastian Hesselbarth break;
9819abd5f05SSebastian Hesselbarth case SI5351_CLK_INPUT_MULTISYNTH_0_4:
9829abd5f05SSebastian Hesselbarth index = 1;
9839abd5f05SSebastian Hesselbarth break;
9849abd5f05SSebastian Hesselbarth case SI5351_CLK_INPUT_XTAL:
9859abd5f05SSebastian Hesselbarth index = 2;
9869abd5f05SSebastian Hesselbarth break;
9879abd5f05SSebastian Hesselbarth case SI5351_CLK_INPUT_CLKIN:
9889abd5f05SSebastian Hesselbarth index = 3;
9899abd5f05SSebastian Hesselbarth break;
9909abd5f05SSebastian Hesselbarth }
9919abd5f05SSebastian Hesselbarth
9929abd5f05SSebastian Hesselbarth return index;
9939abd5f05SSebastian Hesselbarth }
9949abd5f05SSebastian Hesselbarth
si5351_clkout_set_parent(struct clk_hw * hw,u8 index)9959abd5f05SSebastian Hesselbarth static int si5351_clkout_set_parent(struct clk_hw *hw, u8 index)
9969abd5f05SSebastian Hesselbarth {
9979abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
9989abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
9999abd5f05SSebastian Hesselbarth enum si5351_clkout_src parent = SI5351_CLKOUT_SRC_DEFAULT;
10009abd5f05SSebastian Hesselbarth
10019abd5f05SSebastian Hesselbarth switch (index) {
10029abd5f05SSebastian Hesselbarth case 0:
10039abd5f05SSebastian Hesselbarth parent = SI5351_CLKOUT_SRC_MSYNTH_N;
10049abd5f05SSebastian Hesselbarth break;
10059abd5f05SSebastian Hesselbarth case 1:
10069abd5f05SSebastian Hesselbarth parent = SI5351_CLKOUT_SRC_MSYNTH_0_4;
10079abd5f05SSebastian Hesselbarth break;
10089abd5f05SSebastian Hesselbarth case 2:
10099abd5f05SSebastian Hesselbarth parent = SI5351_CLKOUT_SRC_XTAL;
10109abd5f05SSebastian Hesselbarth break;
10119abd5f05SSebastian Hesselbarth case 3:
10129abd5f05SSebastian Hesselbarth parent = SI5351_CLKOUT_SRC_CLKIN;
10139abd5f05SSebastian Hesselbarth break;
10149abd5f05SSebastian Hesselbarth }
10159abd5f05SSebastian Hesselbarth
10169abd5f05SSebastian Hesselbarth return _si5351_clkout_reparent(hwdata->drvdata, hwdata->num, parent);
10179abd5f05SSebastian Hesselbarth }
10189abd5f05SSebastian Hesselbarth
si5351_clkout_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)10199abd5f05SSebastian Hesselbarth static unsigned long si5351_clkout_recalc_rate(struct clk_hw *hw,
10209abd5f05SSebastian Hesselbarth unsigned long parent_rate)
10219abd5f05SSebastian Hesselbarth {
10229abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
10239abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
10249abd5f05SSebastian Hesselbarth unsigned char reg;
10259abd5f05SSebastian Hesselbarth unsigned char rdiv;
10269abd5f05SSebastian Hesselbarth
102767e1e226SMarek Belisko if (hwdata->num <= 5)
10289abd5f05SSebastian Hesselbarth reg = si5351_msynth_params_address(hwdata->num) + 2;
10299abd5f05SSebastian Hesselbarth else
10309abd5f05SSebastian Hesselbarth reg = SI5351_CLK6_7_OUTPUT_DIVIDER;
10319abd5f05SSebastian Hesselbarth
10329abd5f05SSebastian Hesselbarth rdiv = si5351_reg_read(hwdata->drvdata, reg);
10339abd5f05SSebastian Hesselbarth if (hwdata->num == 6) {
10349abd5f05SSebastian Hesselbarth rdiv &= SI5351_OUTPUT_CLK6_DIV_MASK;
10359abd5f05SSebastian Hesselbarth } else {
10369abd5f05SSebastian Hesselbarth rdiv &= SI5351_OUTPUT_CLK_DIV_MASK;
10379abd5f05SSebastian Hesselbarth rdiv >>= SI5351_OUTPUT_CLK_DIV_SHIFT;
10389abd5f05SSebastian Hesselbarth }
10399abd5f05SSebastian Hesselbarth
10409abd5f05SSebastian Hesselbarth return parent_rate >> rdiv;
10419abd5f05SSebastian Hesselbarth }
10429abd5f05SSebastian Hesselbarth
si5351_clkout_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)1043c8bfcfcbSMaxime Ripard static int si5351_clkout_determine_rate(struct clk_hw *hw,
1044c8bfcfcbSMaxime Ripard struct clk_rate_request *req)
10459abd5f05SSebastian Hesselbarth {
10469abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
10479abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
1048c8bfcfcbSMaxime Ripard unsigned long rate = req->rate;
10499abd5f05SSebastian Hesselbarth unsigned char rdiv;
10509abd5f05SSebastian Hesselbarth
10519abd5f05SSebastian Hesselbarth /* clkout6/7 can only handle output freqencies < 150MHz */
10529abd5f05SSebastian Hesselbarth if (hwdata->num >= 6 && rate > SI5351_CLKOUT67_MAX_FREQ)
10539abd5f05SSebastian Hesselbarth rate = SI5351_CLKOUT67_MAX_FREQ;
10549abd5f05SSebastian Hesselbarth
10559abd5f05SSebastian Hesselbarth /* clkout freqency is 8kHz - 160MHz */
10569abd5f05SSebastian Hesselbarth if (rate > SI5351_CLKOUT_MAX_FREQ)
10579abd5f05SSebastian Hesselbarth rate = SI5351_CLKOUT_MAX_FREQ;
10589abd5f05SSebastian Hesselbarth if (rate < SI5351_CLKOUT_MIN_FREQ)
10599abd5f05SSebastian Hesselbarth rate = SI5351_CLKOUT_MIN_FREQ;
10609abd5f05SSebastian Hesselbarth
10619abd5f05SSebastian Hesselbarth /* request frequency if multisync master */
106298d8a60eSStephen Boyd if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
10639abd5f05SSebastian Hesselbarth /* use r divider for frequencies below 1MHz */
10649abd5f05SSebastian Hesselbarth rdiv = SI5351_OUTPUT_CLK_DIV_1;
10659abd5f05SSebastian Hesselbarth while (rate < SI5351_MULTISYNTH_MIN_FREQ &&
10669abd5f05SSebastian Hesselbarth rdiv < SI5351_OUTPUT_CLK_DIV_128) {
10679abd5f05SSebastian Hesselbarth rdiv += 1;
10689abd5f05SSebastian Hesselbarth rate *= 2;
10699abd5f05SSebastian Hesselbarth }
1070c8bfcfcbSMaxime Ripard req->best_parent_rate = rate;
10719abd5f05SSebastian Hesselbarth } else {
10729abd5f05SSebastian Hesselbarth unsigned long new_rate, new_err, err;
10739abd5f05SSebastian Hesselbarth
10749abd5f05SSebastian Hesselbarth /* round to closed rdiv */
10759abd5f05SSebastian Hesselbarth rdiv = SI5351_OUTPUT_CLK_DIV_1;
1076c8bfcfcbSMaxime Ripard new_rate = req->best_parent_rate;
10779abd5f05SSebastian Hesselbarth err = abs(new_rate - rate);
10789abd5f05SSebastian Hesselbarth do {
10799abd5f05SSebastian Hesselbarth new_rate >>= 1;
10809abd5f05SSebastian Hesselbarth new_err = abs(new_rate - rate);
10819abd5f05SSebastian Hesselbarth if (new_err > err || rdiv == SI5351_OUTPUT_CLK_DIV_128)
10829abd5f05SSebastian Hesselbarth break;
10839abd5f05SSebastian Hesselbarth rdiv++;
10849abd5f05SSebastian Hesselbarth err = new_err;
10859abd5f05SSebastian Hesselbarth } while (1);
10869abd5f05SSebastian Hesselbarth }
1087c8bfcfcbSMaxime Ripard rate = req->best_parent_rate >> rdiv;
10889abd5f05SSebastian Hesselbarth
10899abd5f05SSebastian Hesselbarth dev_dbg(&hwdata->drvdata->client->dev,
10909abd5f05SSebastian Hesselbarth "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
109144f22a5dSStephen Boyd __func__, clk_hw_get_name(hw), (1 << rdiv),
1092c8bfcfcbSMaxime Ripard req->best_parent_rate, rate);
10939abd5f05SSebastian Hesselbarth
1094c8bfcfcbSMaxime Ripard req->rate = rate;
1095c8bfcfcbSMaxime Ripard return 0;
10969abd5f05SSebastian Hesselbarth }
10979abd5f05SSebastian Hesselbarth
si5351_clkout_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)10989abd5f05SSebastian Hesselbarth static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
10999abd5f05SSebastian Hesselbarth unsigned long parent_rate)
11009abd5f05SSebastian Hesselbarth {
11019abd5f05SSebastian Hesselbarth struct si5351_hw_data *hwdata =
11029abd5f05SSebastian Hesselbarth container_of(hw, struct si5351_hw_data, hw);
11039abd5f05SSebastian Hesselbarth unsigned long new_rate, new_err, err;
11049abd5f05SSebastian Hesselbarth unsigned char rdiv;
11059abd5f05SSebastian Hesselbarth
11069abd5f05SSebastian Hesselbarth /* round to closed rdiv */
11079abd5f05SSebastian Hesselbarth rdiv = SI5351_OUTPUT_CLK_DIV_1;
11089abd5f05SSebastian Hesselbarth new_rate = parent_rate;
11099abd5f05SSebastian Hesselbarth err = abs(new_rate - rate);
11109abd5f05SSebastian Hesselbarth do {
11119abd5f05SSebastian Hesselbarth new_rate >>= 1;
11129abd5f05SSebastian Hesselbarth new_err = abs(new_rate - rate);
11139abd5f05SSebastian Hesselbarth if (new_err > err || rdiv == SI5351_OUTPUT_CLK_DIV_128)
11149abd5f05SSebastian Hesselbarth break;
11159abd5f05SSebastian Hesselbarth rdiv++;
11169abd5f05SSebastian Hesselbarth err = new_err;
11179abd5f05SSebastian Hesselbarth } while (1);
11189abd5f05SSebastian Hesselbarth
11199abd5f05SSebastian Hesselbarth /* write output divider */
11209abd5f05SSebastian Hesselbarth switch (hwdata->num) {
11219abd5f05SSebastian Hesselbarth case 6:
11229abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_CLK6_7_OUTPUT_DIVIDER,
11239abd5f05SSebastian Hesselbarth SI5351_OUTPUT_CLK6_DIV_MASK, rdiv);
11249abd5f05SSebastian Hesselbarth break;
11259abd5f05SSebastian Hesselbarth case 7:
11269abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_CLK6_7_OUTPUT_DIVIDER,
11279abd5f05SSebastian Hesselbarth SI5351_OUTPUT_CLK_DIV_MASK,
11289abd5f05SSebastian Hesselbarth rdiv << SI5351_OUTPUT_CLK_DIV_SHIFT);
11299abd5f05SSebastian Hesselbarth break;
11309abd5f05SSebastian Hesselbarth default:
11319abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata,
11329abd5f05SSebastian Hesselbarth si5351_msynth_params_address(hwdata->num) + 2,
11339abd5f05SSebastian Hesselbarth SI5351_OUTPUT_CLK_DIV_MASK,
11349abd5f05SSebastian Hesselbarth rdiv << SI5351_OUTPUT_CLK_DIV_SHIFT);
11359abd5f05SSebastian Hesselbarth }
11369abd5f05SSebastian Hesselbarth
11379abd5f05SSebastian Hesselbarth /* powerup clkout */
11389abd5f05SSebastian Hesselbarth si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num,
11399abd5f05SSebastian Hesselbarth SI5351_CLK_POWERDOWN, 0);
11409abd5f05SSebastian Hesselbarth
11419abd5f05SSebastian Hesselbarth dev_dbg(&hwdata->drvdata->client->dev,
11429abd5f05SSebastian Hesselbarth "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
114344f22a5dSStephen Boyd __func__, clk_hw_get_name(hw), (1 << rdiv),
11449abd5f05SSebastian Hesselbarth parent_rate, rate);
11459abd5f05SSebastian Hesselbarth
11469abd5f05SSebastian Hesselbarth return 0;
11479abd5f05SSebastian Hesselbarth }
11489abd5f05SSebastian Hesselbarth
11499abd5f05SSebastian Hesselbarth static const struct clk_ops si5351_clkout_ops = {
11509abd5f05SSebastian Hesselbarth .prepare = si5351_clkout_prepare,
11519abd5f05SSebastian Hesselbarth .unprepare = si5351_clkout_unprepare,
11529abd5f05SSebastian Hesselbarth .set_parent = si5351_clkout_set_parent,
11539abd5f05SSebastian Hesselbarth .get_parent = si5351_clkout_get_parent,
11549abd5f05SSebastian Hesselbarth .recalc_rate = si5351_clkout_recalc_rate,
1155c8bfcfcbSMaxime Ripard .determine_rate = si5351_clkout_determine_rate,
11569abd5f05SSebastian Hesselbarth .set_rate = si5351_clkout_set_rate,
11579abd5f05SSebastian Hesselbarth };
11589abd5f05SSebastian Hesselbarth
11599abd5f05SSebastian Hesselbarth /*
11609abd5f05SSebastian Hesselbarth * Si5351 i2c probe and DT
11619abd5f05SSebastian Hesselbarth */
11629abd5f05SSebastian Hesselbarth #ifdef CONFIG_OF
11639abd5f05SSebastian Hesselbarth static const struct of_device_id si5351_dt_ids[] = {
11649abd5f05SSebastian Hesselbarth { .compatible = "silabs,si5351a", .data = (void *)SI5351_VARIANT_A, },
11659abd5f05SSebastian Hesselbarth { .compatible = "silabs,si5351a-msop",
11669abd5f05SSebastian Hesselbarth .data = (void *)SI5351_VARIANT_A3, },
11679abd5f05SSebastian Hesselbarth { .compatible = "silabs,si5351b", .data = (void *)SI5351_VARIANT_B, },
11689abd5f05SSebastian Hesselbarth { .compatible = "silabs,si5351c", .data = (void *)SI5351_VARIANT_C, },
11699abd5f05SSebastian Hesselbarth { }
11709abd5f05SSebastian Hesselbarth };
11719abd5f05SSebastian Hesselbarth MODULE_DEVICE_TABLE(of, si5351_dt_ids);
11729abd5f05SSebastian Hesselbarth
si5351_dt_parse(struct i2c_client * client,enum si5351_variant variant)11739d43dc7fSSebastian Hesselbarth static int si5351_dt_parse(struct i2c_client *client,
11749d43dc7fSSebastian Hesselbarth enum si5351_variant variant)
11759abd5f05SSebastian Hesselbarth {
11769abd5f05SSebastian Hesselbarth struct device_node *child, *np = client->dev.of_node;
11779abd5f05SSebastian Hesselbarth struct si5351_platform_data *pdata;
1178*914ef7d1SLuca Ceresoli u32 array[4];
1179*914ef7d1SLuca Ceresoli int sz, i;
11809abd5f05SSebastian Hesselbarth int num = 0;
11819abd5f05SSebastian Hesselbarth u32 val;
11829abd5f05SSebastian Hesselbarth
11839abd5f05SSebastian Hesselbarth if (np == NULL)
11849abd5f05SSebastian Hesselbarth return 0;
11859abd5f05SSebastian Hesselbarth
11869abd5f05SSebastian Hesselbarth pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
11879abd5f05SSebastian Hesselbarth if (!pdata)
11889abd5f05SSebastian Hesselbarth return -ENOMEM;
11899abd5f05SSebastian Hesselbarth
11909abd5f05SSebastian Hesselbarth /*
11919abd5f05SSebastian Hesselbarth * property silabs,pll-source : <num src>, [<..>]
11929abd5f05SSebastian Hesselbarth * allow to selectively set pll source
11939abd5f05SSebastian Hesselbarth */
1194*914ef7d1SLuca Ceresoli sz = of_property_read_variable_u32_array(np, "silabs,pll-source", array, 2, 4);
1195*914ef7d1SLuca Ceresoli sz = (sz == -EINVAL) ? 0 : sz; /* Missing property is OK */
1196*914ef7d1SLuca Ceresoli if (sz < 0)
1197*914ef7d1SLuca Ceresoli return dev_err_probe(&client->dev, sz, "invalid pll-source\n");
1198*914ef7d1SLuca Ceresoli if (sz % 2)
1199*914ef7d1SLuca Ceresoli return dev_err_probe(&client->dev, -EINVAL,
1200*914ef7d1SLuca Ceresoli "missing pll-source for pll %d\n", array[sz - 1]);
1201*914ef7d1SLuca Ceresoli
1202*914ef7d1SLuca Ceresoli for (i = 0; i < sz; i += 2) {
1203*914ef7d1SLuca Ceresoli num = array[i];
1204*914ef7d1SLuca Ceresoli val = array[i + 1];
1205*914ef7d1SLuca Ceresoli
12069abd5f05SSebastian Hesselbarth if (num >= 2) {
12079abd5f05SSebastian Hesselbarth dev_err(&client->dev,
12089abd5f05SSebastian Hesselbarth "invalid pll %d on pll-source prop\n", num);
12099abd5f05SSebastian Hesselbarth return -EINVAL;
12109abd5f05SSebastian Hesselbarth }
12119abd5f05SSebastian Hesselbarth
12129abd5f05SSebastian Hesselbarth switch (val) {
12139abd5f05SSebastian Hesselbarth case 0:
12149abd5f05SSebastian Hesselbarth pdata->pll_src[num] = SI5351_PLL_SRC_XTAL;
12159abd5f05SSebastian Hesselbarth break;
12169abd5f05SSebastian Hesselbarth case 1:
12179d43dc7fSSebastian Hesselbarth if (variant != SI5351_VARIANT_C) {
12189abd5f05SSebastian Hesselbarth dev_err(&client->dev,
12199abd5f05SSebastian Hesselbarth "invalid parent %d for pll %d\n",
12209abd5f05SSebastian Hesselbarth val, num);
12219abd5f05SSebastian Hesselbarth return -EINVAL;
12229abd5f05SSebastian Hesselbarth }
12239abd5f05SSebastian Hesselbarth pdata->pll_src[num] = SI5351_PLL_SRC_CLKIN;
12249abd5f05SSebastian Hesselbarth break;
12259abd5f05SSebastian Hesselbarth default:
12269abd5f05SSebastian Hesselbarth dev_err(&client->dev,
12279abd5f05SSebastian Hesselbarth "invalid parent %d for pll %d\n", val, num);
12289abd5f05SSebastian Hesselbarth return -EINVAL;
12299abd5f05SSebastian Hesselbarth }
12309abd5f05SSebastian Hesselbarth }
12319abd5f05SSebastian Hesselbarth
12328b84c2ceSAlvin Šipraga /*
12338b84c2ceSAlvin Šipraga * Parse PLL reset mode. For compatibility with older device trees, the
12348b84c2ceSAlvin Šipraga * default is to always reset a PLL after setting its rate.
12358b84c2ceSAlvin Šipraga */
12368b84c2ceSAlvin Šipraga pdata->pll_reset[0] = true;
12378b84c2ceSAlvin Šipraga pdata->pll_reset[1] = true;
12388b84c2ceSAlvin Šipraga
1239*914ef7d1SLuca Ceresoli sz = of_property_read_variable_u32_array(np, "silabs,pll-reset-mode", array, 2, 4);
1240*914ef7d1SLuca Ceresoli sz = (sz == -EINVAL) ? 0 : sz; /* Missing property is OK */
1241*914ef7d1SLuca Ceresoli if (sz < 0)
1242*914ef7d1SLuca Ceresoli return dev_err_probe(&client->dev, sz, "invalid pll-reset-mode\n");
1243*914ef7d1SLuca Ceresoli if (sz % 2)
1244*914ef7d1SLuca Ceresoli return dev_err_probe(&client->dev, -EINVAL,
1245*914ef7d1SLuca Ceresoli "missing pll-reset-mode for pll %d\n", array[sz - 1]);
1246*914ef7d1SLuca Ceresoli
1247*914ef7d1SLuca Ceresoli for (i = 0; i < sz; i += 2) {
1248*914ef7d1SLuca Ceresoli num = array[i];
1249*914ef7d1SLuca Ceresoli val = array[i + 1];
1250*914ef7d1SLuca Ceresoli
12518b84c2ceSAlvin Šipraga if (num >= 2) {
12528b84c2ceSAlvin Šipraga dev_err(&client->dev,
12538b84c2ceSAlvin Šipraga "invalid pll %d on pll-reset-mode prop\n", num);
12548b84c2ceSAlvin Šipraga return -EINVAL;
12558b84c2ceSAlvin Šipraga }
12568b84c2ceSAlvin Šipraga
12578b84c2ceSAlvin Šipraga
12588b84c2ceSAlvin Šipraga switch (val) {
12598b84c2ceSAlvin Šipraga case 0:
12608b84c2ceSAlvin Šipraga /* Reset PLL whenever its rate is adjusted */
12618b84c2ceSAlvin Šipraga pdata->pll_reset[num] = true;
12628b84c2ceSAlvin Šipraga break;
12638b84c2ceSAlvin Šipraga case 1:
12648b84c2ceSAlvin Šipraga /* Don't reset PLL whenever its rate is adjusted */
12658b84c2ceSAlvin Šipraga pdata->pll_reset[num] = false;
12668b84c2ceSAlvin Šipraga break;
12678b84c2ceSAlvin Šipraga default:
12688b84c2ceSAlvin Šipraga dev_err(&client->dev,
12698b84c2ceSAlvin Šipraga "invalid pll-reset-mode %d for pll %d\n", val,
12708b84c2ceSAlvin Šipraga num);
12718b84c2ceSAlvin Šipraga return -EINVAL;
12728b84c2ceSAlvin Šipraga }
12738b84c2ceSAlvin Šipraga }
12748b84c2ceSAlvin Šipraga
12759abd5f05SSebastian Hesselbarth /* per clkout properties */
12769abd5f05SSebastian Hesselbarth for_each_child_of_node(np, child) {
12779abd5f05SSebastian Hesselbarth if (of_property_read_u32(child, "reg", &num)) {
1278e665f029SRob Herring dev_err(&client->dev, "missing reg property of %pOFn\n",
1279e665f029SRob Herring child);
1280a1bdfbafSJulia Lawall goto put_child;
12819abd5f05SSebastian Hesselbarth }
12829abd5f05SSebastian Hesselbarth
12839abd5f05SSebastian Hesselbarth if (num >= 8 ||
12849d43dc7fSSebastian Hesselbarth (variant == SI5351_VARIANT_A3 && num >= 3)) {
12859abd5f05SSebastian Hesselbarth dev_err(&client->dev, "invalid clkout %d\n", num);
1286a1bdfbafSJulia Lawall goto put_child;
12879abd5f05SSebastian Hesselbarth }
12889abd5f05SSebastian Hesselbarth
12899abd5f05SSebastian Hesselbarth if (!of_property_read_u32(child, "silabs,multisynth-source",
12909abd5f05SSebastian Hesselbarth &val)) {
12919abd5f05SSebastian Hesselbarth switch (val) {
12929abd5f05SSebastian Hesselbarth case 0:
12939abd5f05SSebastian Hesselbarth pdata->clkout[num].multisynth_src =
12949abd5f05SSebastian Hesselbarth SI5351_MULTISYNTH_SRC_VCO0;
12959abd5f05SSebastian Hesselbarth break;
12969abd5f05SSebastian Hesselbarth case 1:
12979abd5f05SSebastian Hesselbarth pdata->clkout[num].multisynth_src =
12989abd5f05SSebastian Hesselbarth SI5351_MULTISYNTH_SRC_VCO1;
12999abd5f05SSebastian Hesselbarth break;
13009abd5f05SSebastian Hesselbarth default:
13019abd5f05SSebastian Hesselbarth dev_err(&client->dev,
13029abd5f05SSebastian Hesselbarth "invalid parent %d for multisynth %d\n",
13039abd5f05SSebastian Hesselbarth val, num);
1304a1bdfbafSJulia Lawall goto put_child;
13059abd5f05SSebastian Hesselbarth }
13069abd5f05SSebastian Hesselbarth }
13079abd5f05SSebastian Hesselbarth
13089abd5f05SSebastian Hesselbarth if (!of_property_read_u32(child, "silabs,clock-source", &val)) {
13099abd5f05SSebastian Hesselbarth switch (val) {
13109abd5f05SSebastian Hesselbarth case 0:
13119abd5f05SSebastian Hesselbarth pdata->clkout[num].clkout_src =
13129abd5f05SSebastian Hesselbarth SI5351_CLKOUT_SRC_MSYNTH_N;
13139abd5f05SSebastian Hesselbarth break;
13149abd5f05SSebastian Hesselbarth case 1:
13159abd5f05SSebastian Hesselbarth pdata->clkout[num].clkout_src =
13169abd5f05SSebastian Hesselbarth SI5351_CLKOUT_SRC_MSYNTH_0_4;
13179abd5f05SSebastian Hesselbarth break;
13189abd5f05SSebastian Hesselbarth case 2:
13199abd5f05SSebastian Hesselbarth pdata->clkout[num].clkout_src =
13209abd5f05SSebastian Hesselbarth SI5351_CLKOUT_SRC_XTAL;
13219abd5f05SSebastian Hesselbarth break;
13229abd5f05SSebastian Hesselbarth case 3:
13239d43dc7fSSebastian Hesselbarth if (variant != SI5351_VARIANT_C) {
13249abd5f05SSebastian Hesselbarth dev_err(&client->dev,
13259abd5f05SSebastian Hesselbarth "invalid parent %d for clkout %d\n",
13269abd5f05SSebastian Hesselbarth val, num);
1327a1bdfbafSJulia Lawall goto put_child;
13289abd5f05SSebastian Hesselbarth }
13299abd5f05SSebastian Hesselbarth pdata->clkout[num].clkout_src =
13309abd5f05SSebastian Hesselbarth SI5351_CLKOUT_SRC_CLKIN;
13319abd5f05SSebastian Hesselbarth break;
13329abd5f05SSebastian Hesselbarth default:
13339abd5f05SSebastian Hesselbarth dev_err(&client->dev,
13349abd5f05SSebastian Hesselbarth "invalid parent %d for clkout %d\n",
13359abd5f05SSebastian Hesselbarth val, num);
1336a1bdfbafSJulia Lawall goto put_child;
13379abd5f05SSebastian Hesselbarth }
13389abd5f05SSebastian Hesselbarth }
13399abd5f05SSebastian Hesselbarth
13409abd5f05SSebastian Hesselbarth if (!of_property_read_u32(child, "silabs,drive-strength",
13419abd5f05SSebastian Hesselbarth &val)) {
13429abd5f05SSebastian Hesselbarth switch (val) {
13439abd5f05SSebastian Hesselbarth case SI5351_DRIVE_2MA:
13449abd5f05SSebastian Hesselbarth case SI5351_DRIVE_4MA:
13459abd5f05SSebastian Hesselbarth case SI5351_DRIVE_6MA:
13469abd5f05SSebastian Hesselbarth case SI5351_DRIVE_8MA:
13479abd5f05SSebastian Hesselbarth pdata->clkout[num].drive = val;
13489abd5f05SSebastian Hesselbarth break;
13499abd5f05SSebastian Hesselbarth default:
13509abd5f05SSebastian Hesselbarth dev_err(&client->dev,
13519abd5f05SSebastian Hesselbarth "invalid drive strength %d for clkout %d\n",
13529abd5f05SSebastian Hesselbarth val, num);
1353a1bdfbafSJulia Lawall goto put_child;
13549abd5f05SSebastian Hesselbarth }
13559abd5f05SSebastian Hesselbarth }
13569abd5f05SSebastian Hesselbarth
13571a0483d2SSebastian Hesselbarth if (!of_property_read_u32(child, "silabs,disable-state",
13581a0483d2SSebastian Hesselbarth &val)) {
13591a0483d2SSebastian Hesselbarth switch (val) {
13601a0483d2SSebastian Hesselbarth case 0:
13611a0483d2SSebastian Hesselbarth pdata->clkout[num].disable_state =
13621a0483d2SSebastian Hesselbarth SI5351_DISABLE_LOW;
13631a0483d2SSebastian Hesselbarth break;
13641a0483d2SSebastian Hesselbarth case 1:
13651a0483d2SSebastian Hesselbarth pdata->clkout[num].disable_state =
13661a0483d2SSebastian Hesselbarth SI5351_DISABLE_HIGH;
13671a0483d2SSebastian Hesselbarth break;
13681a0483d2SSebastian Hesselbarth case 2:
13691a0483d2SSebastian Hesselbarth pdata->clkout[num].disable_state =
13701a0483d2SSebastian Hesselbarth SI5351_DISABLE_FLOATING;
13711a0483d2SSebastian Hesselbarth break;
13721a0483d2SSebastian Hesselbarth case 3:
13731a0483d2SSebastian Hesselbarth pdata->clkout[num].disable_state =
13741a0483d2SSebastian Hesselbarth SI5351_DISABLE_NEVER;
13751a0483d2SSebastian Hesselbarth break;
13761a0483d2SSebastian Hesselbarth default:
13771a0483d2SSebastian Hesselbarth dev_err(&client->dev,
13781a0483d2SSebastian Hesselbarth "invalid disable state %d for clkout %d\n",
13791a0483d2SSebastian Hesselbarth val, num);
1380a1bdfbafSJulia Lawall goto put_child;
13811a0483d2SSebastian Hesselbarth }
13821a0483d2SSebastian Hesselbarth }
13831a0483d2SSebastian Hesselbarth
13849abd5f05SSebastian Hesselbarth if (!of_property_read_u32(child, "clock-frequency", &val))
13859abd5f05SSebastian Hesselbarth pdata->clkout[num].rate = val;
13869abd5f05SSebastian Hesselbarth
13879abd5f05SSebastian Hesselbarth pdata->clkout[num].pll_master =
13889abd5f05SSebastian Hesselbarth of_property_read_bool(child, "silabs,pll-master");
138951279ef9SSergej Sawazki
139051279ef9SSergej Sawazki pdata->clkout[num].pll_reset =
139151279ef9SSergej Sawazki of_property_read_bool(child, "silabs,pll-reset");
13929abd5f05SSebastian Hesselbarth }
13939abd5f05SSebastian Hesselbarth client->dev.platform_data = pdata;
13949abd5f05SSebastian Hesselbarth
13959abd5f05SSebastian Hesselbarth return 0;
1396a1bdfbafSJulia Lawall put_child:
1397a1bdfbafSJulia Lawall of_node_put(child);
1398a1bdfbafSJulia Lawall return -EINVAL;
13999abd5f05SSebastian Hesselbarth }
14004d89c3d5SStephen Boyd
14014d89c3d5SStephen Boyd static struct clk_hw *
si53351_of_clk_get(struct of_phandle_args * clkspec,void * data)14024d89c3d5SStephen Boyd si53351_of_clk_get(struct of_phandle_args *clkspec, void *data)
14034d89c3d5SStephen Boyd {
14044d89c3d5SStephen Boyd struct si5351_driver_data *drvdata = data;
14054d89c3d5SStephen Boyd unsigned int idx = clkspec->args[0];
14064d89c3d5SStephen Boyd
14074d89c3d5SStephen Boyd if (idx >= drvdata->num_clkout) {
14084d89c3d5SStephen Boyd pr_err("%s: invalid index %u\n", __func__, idx);
14094d89c3d5SStephen Boyd return ERR_PTR(-EINVAL);
14104d89c3d5SStephen Boyd }
14114d89c3d5SStephen Boyd
14124d89c3d5SStephen Boyd return &drvdata->clkout[idx].hw;
14134d89c3d5SStephen Boyd }
14149abd5f05SSebastian Hesselbarth #else
si5351_dt_parse(struct i2c_client * client,enum si5351_variant variant)1415d30492adSLinus Torvalds static int si5351_dt_parse(struct i2c_client *client, enum si5351_variant variant)
14169abd5f05SSebastian Hesselbarth {
14179abd5f05SSebastian Hesselbarth return 0;
14189abd5f05SSebastian Hesselbarth }
14194d89c3d5SStephen Boyd
14204d89c3d5SStephen Boyd static struct clk_hw *
si53351_of_clk_get(struct of_phandle_args * clkspec,void * data)14214d89c3d5SStephen Boyd si53351_of_clk_get(struct of_phandle_args *clkspec, void *data)
14224d89c3d5SStephen Boyd {
14234d89c3d5SStephen Boyd return NULL;
14244d89c3d5SStephen Boyd }
14259abd5f05SSebastian Hesselbarth #endif /* CONFIG_OF */
14269abd5f05SSebastian Hesselbarth
1427ca3ebd20SStephen Kitt static const struct i2c_device_id si5351_i2c_ids[] = {
1428ca3ebd20SStephen Kitt { "si5351a", SI5351_VARIANT_A },
1429ca3ebd20SStephen Kitt { "si5351a-msop", SI5351_VARIANT_A3 },
1430ca3ebd20SStephen Kitt { "si5351b", SI5351_VARIANT_B },
1431ca3ebd20SStephen Kitt { "si5351c", SI5351_VARIANT_C },
1432ca3ebd20SStephen Kitt { }
1433ca3ebd20SStephen Kitt };
1434ca3ebd20SStephen Kitt MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids);
1435ca3ebd20SStephen Kitt
si5351_i2c_probe(struct i2c_client * client)1436ca3ebd20SStephen Kitt static int si5351_i2c_probe(struct i2c_client *client)
14379abd5f05SSebastian Hesselbarth {
1438ca3ebd20SStephen Kitt const struct i2c_device_id *id = i2c_match_id(si5351_i2c_ids, client);
14399d43dc7fSSebastian Hesselbarth enum si5351_variant variant = (enum si5351_variant)id->driver_data;
14409abd5f05SSebastian Hesselbarth struct si5351_platform_data *pdata;
14419abd5f05SSebastian Hesselbarth struct si5351_driver_data *drvdata;
14429abd5f05SSebastian Hesselbarth struct clk_init_data init;
14439abd5f05SSebastian Hesselbarth const char *parent_names[4];
14449abd5f05SSebastian Hesselbarth u8 num_parents, num_clocks;
14459abd5f05SSebastian Hesselbarth int ret, n;
14469abd5f05SSebastian Hesselbarth
14479d43dc7fSSebastian Hesselbarth ret = si5351_dt_parse(client, variant);
14489abd5f05SSebastian Hesselbarth if (ret)
14499abd5f05SSebastian Hesselbarth return ret;
14509abd5f05SSebastian Hesselbarth
14519abd5f05SSebastian Hesselbarth pdata = client->dev.platform_data;
14529abd5f05SSebastian Hesselbarth if (!pdata)
14539abd5f05SSebastian Hesselbarth return -EINVAL;
14549abd5f05SSebastian Hesselbarth
14559abd5f05SSebastian Hesselbarth drvdata = devm_kzalloc(&client->dev, sizeof(*drvdata), GFP_KERNEL);
145656f2150aSMarkus Elfring if (!drvdata)
14579abd5f05SSebastian Hesselbarth return -ENOMEM;
14589abd5f05SSebastian Hesselbarth
14599abd5f05SSebastian Hesselbarth i2c_set_clientdata(client, drvdata);
14609abd5f05SSebastian Hesselbarth drvdata->client = client;
14619d43dc7fSSebastian Hesselbarth drvdata->variant = variant;
14620cd3be6eSSebastian Hesselbarth drvdata->pxtal = devm_clk_get(&client->dev, "xtal");
14630cd3be6eSSebastian Hesselbarth drvdata->pclkin = devm_clk_get(&client->dev, "clkin");
14640cd3be6eSSebastian Hesselbarth
14650cd3be6eSSebastian Hesselbarth if (PTR_ERR(drvdata->pxtal) == -EPROBE_DEFER ||
14660cd3be6eSSebastian Hesselbarth PTR_ERR(drvdata->pclkin) == -EPROBE_DEFER)
14670cd3be6eSSebastian Hesselbarth return -EPROBE_DEFER;
14680cd3be6eSSebastian Hesselbarth
14690cd3be6eSSebastian Hesselbarth /*
14700cd3be6eSSebastian Hesselbarth * Check for valid parent clock: VARIANT_A and VARIANT_B need XTAL,
14710cd3be6eSSebastian Hesselbarth * VARIANT_C can have CLKIN instead.
14720cd3be6eSSebastian Hesselbarth */
14730cd3be6eSSebastian Hesselbarth if (IS_ERR(drvdata->pxtal) &&
14740cd3be6eSSebastian Hesselbarth (drvdata->variant != SI5351_VARIANT_C || IS_ERR(drvdata->pclkin))) {
14750cd3be6eSSebastian Hesselbarth dev_err(&client->dev, "missing parent clock\n");
14760cd3be6eSSebastian Hesselbarth return -EINVAL;
14770cd3be6eSSebastian Hesselbarth }
14789abd5f05SSebastian Hesselbarth
14799abd5f05SSebastian Hesselbarth drvdata->regmap = devm_regmap_init_i2c(client, &si5351_regmap_config);
14809abd5f05SSebastian Hesselbarth if (IS_ERR(drvdata->regmap)) {
14819abd5f05SSebastian Hesselbarth dev_err(&client->dev, "failed to allocate register map\n");
14829abd5f05SSebastian Hesselbarth return PTR_ERR(drvdata->regmap);
14839abd5f05SSebastian Hesselbarth }
14849abd5f05SSebastian Hesselbarth
14859abd5f05SSebastian Hesselbarth /* Disable interrupts */
14869abd5f05SSebastian Hesselbarth si5351_reg_write(drvdata, SI5351_INTERRUPT_MASK, 0xf0);
14879abd5f05SSebastian Hesselbarth /* Ensure pll select is on XTAL for Si5351A/B */
14889abd5f05SSebastian Hesselbarth if (drvdata->variant != SI5351_VARIANT_C)
14899abd5f05SSebastian Hesselbarth si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE,
14909abd5f05SSebastian Hesselbarth SI5351_PLLA_SOURCE | SI5351_PLLB_SOURCE, 0);
14919abd5f05SSebastian Hesselbarth
14929abd5f05SSebastian Hesselbarth /* setup clock configuration */
14939abd5f05SSebastian Hesselbarth for (n = 0; n < 2; n++) {
14949abd5f05SSebastian Hesselbarth ret = _si5351_pll_reparent(drvdata, n, pdata->pll_src[n]);
14959abd5f05SSebastian Hesselbarth if (ret) {
14969abd5f05SSebastian Hesselbarth dev_err(&client->dev,
14979abd5f05SSebastian Hesselbarth "failed to reparent pll %d to %d\n",
14989abd5f05SSebastian Hesselbarth n, pdata->pll_src[n]);
14999abd5f05SSebastian Hesselbarth return ret;
15009abd5f05SSebastian Hesselbarth }
15019abd5f05SSebastian Hesselbarth }
15029abd5f05SSebastian Hesselbarth
15039abd5f05SSebastian Hesselbarth for (n = 0; n < 8; n++) {
15049abd5f05SSebastian Hesselbarth ret = _si5351_msynth_reparent(drvdata, n,
15059abd5f05SSebastian Hesselbarth pdata->clkout[n].multisynth_src);
15069abd5f05SSebastian Hesselbarth if (ret) {
15079abd5f05SSebastian Hesselbarth dev_err(&client->dev,
15089abd5f05SSebastian Hesselbarth "failed to reparent multisynth %d to %d\n",
15099abd5f05SSebastian Hesselbarth n, pdata->clkout[n].multisynth_src);
15109abd5f05SSebastian Hesselbarth return ret;
15119abd5f05SSebastian Hesselbarth }
15129abd5f05SSebastian Hesselbarth
15139abd5f05SSebastian Hesselbarth ret = _si5351_clkout_reparent(drvdata, n,
15149abd5f05SSebastian Hesselbarth pdata->clkout[n].clkout_src);
15159abd5f05SSebastian Hesselbarth if (ret) {
15169abd5f05SSebastian Hesselbarth dev_err(&client->dev,
15179abd5f05SSebastian Hesselbarth "failed to reparent clkout %d to %d\n",
15189abd5f05SSebastian Hesselbarth n, pdata->clkout[n].clkout_src);
15199abd5f05SSebastian Hesselbarth return ret;
15209abd5f05SSebastian Hesselbarth }
15219abd5f05SSebastian Hesselbarth
15229abd5f05SSebastian Hesselbarth ret = _si5351_clkout_set_drive_strength(drvdata, n,
15239abd5f05SSebastian Hesselbarth pdata->clkout[n].drive);
15249abd5f05SSebastian Hesselbarth if (ret) {
15259abd5f05SSebastian Hesselbarth dev_err(&client->dev,
15269abd5f05SSebastian Hesselbarth "failed set drive strength of clkout%d to %d\n",
15279abd5f05SSebastian Hesselbarth n, pdata->clkout[n].drive);
15289abd5f05SSebastian Hesselbarth return ret;
15299abd5f05SSebastian Hesselbarth }
15301a0483d2SSebastian Hesselbarth
15311a0483d2SSebastian Hesselbarth ret = _si5351_clkout_set_disable_state(drvdata, n,
15321a0483d2SSebastian Hesselbarth pdata->clkout[n].disable_state);
15331a0483d2SSebastian Hesselbarth if (ret) {
15341a0483d2SSebastian Hesselbarth dev_err(&client->dev,
15351a0483d2SSebastian Hesselbarth "failed set disable state of clkout%d to %d\n",
15361a0483d2SSebastian Hesselbarth n, pdata->clkout[n].disable_state);
15371a0483d2SSebastian Hesselbarth return ret;
15381a0483d2SSebastian Hesselbarth }
15399abd5f05SSebastian Hesselbarth }
15409abd5f05SSebastian Hesselbarth
15419abd5f05SSebastian Hesselbarth /* register xtal input clock gate */
15429abd5f05SSebastian Hesselbarth memset(&init, 0, sizeof(init));
15439abd5f05SSebastian Hesselbarth init.name = si5351_input_names[0];
15449abd5f05SSebastian Hesselbarth init.ops = &si5351_xtal_ops;
15459abd5f05SSebastian Hesselbarth init.flags = 0;
15469abd5f05SSebastian Hesselbarth if (!IS_ERR(drvdata->pxtal)) {
15479abd5f05SSebastian Hesselbarth drvdata->pxtal_name = __clk_get_name(drvdata->pxtal);
15489abd5f05SSebastian Hesselbarth init.parent_names = &drvdata->pxtal_name;
15499abd5f05SSebastian Hesselbarth init.num_parents = 1;
15509abd5f05SSebastian Hesselbarth }
15519abd5f05SSebastian Hesselbarth drvdata->xtal.init = &init;
15524d89c3d5SStephen Boyd ret = devm_clk_hw_register(&client->dev, &drvdata->xtal);
15534d89c3d5SStephen Boyd if (ret) {
15549abd5f05SSebastian Hesselbarth dev_err(&client->dev, "unable to register %s\n", init.name);
15551fffaf6aSSergej Sawazki return ret;
15569abd5f05SSebastian Hesselbarth }
15579abd5f05SSebastian Hesselbarth
15589abd5f05SSebastian Hesselbarth /* register clkin input clock gate */
15599abd5f05SSebastian Hesselbarth if (drvdata->variant == SI5351_VARIANT_C) {
15609abd5f05SSebastian Hesselbarth memset(&init, 0, sizeof(init));
15619abd5f05SSebastian Hesselbarth init.name = si5351_input_names[1];
15629abd5f05SSebastian Hesselbarth init.ops = &si5351_clkin_ops;
15639abd5f05SSebastian Hesselbarth if (!IS_ERR(drvdata->pclkin)) {
15649abd5f05SSebastian Hesselbarth drvdata->pclkin_name = __clk_get_name(drvdata->pclkin);
15659abd5f05SSebastian Hesselbarth init.parent_names = &drvdata->pclkin_name;
15669abd5f05SSebastian Hesselbarth init.num_parents = 1;
15679abd5f05SSebastian Hesselbarth }
15689abd5f05SSebastian Hesselbarth drvdata->clkin.init = &init;
15694d89c3d5SStephen Boyd ret = devm_clk_hw_register(&client->dev, &drvdata->clkin);
15704d89c3d5SStephen Boyd if (ret) {
15719abd5f05SSebastian Hesselbarth dev_err(&client->dev, "unable to register %s\n",
15729abd5f05SSebastian Hesselbarth init.name);
15731fffaf6aSSergej Sawazki return ret;
15749abd5f05SSebastian Hesselbarth }
15759abd5f05SSebastian Hesselbarth }
15769abd5f05SSebastian Hesselbarth
15779abd5f05SSebastian Hesselbarth /* Si5351C allows to mux either xtal or clkin to PLL input */
15789abd5f05SSebastian Hesselbarth num_parents = (drvdata->variant == SI5351_VARIANT_C) ? 2 : 1;
15799abd5f05SSebastian Hesselbarth parent_names[0] = si5351_input_names[0];
15809abd5f05SSebastian Hesselbarth parent_names[1] = si5351_input_names[1];
15819abd5f05SSebastian Hesselbarth
15829abd5f05SSebastian Hesselbarth /* register PLLA */
15839abd5f05SSebastian Hesselbarth drvdata->pll[0].num = 0;
15849abd5f05SSebastian Hesselbarth drvdata->pll[0].drvdata = drvdata;
15859abd5f05SSebastian Hesselbarth drvdata->pll[0].hw.init = &init;
15869abd5f05SSebastian Hesselbarth memset(&init, 0, sizeof(init));
15879abd5f05SSebastian Hesselbarth init.name = si5351_pll_names[0];
15889abd5f05SSebastian Hesselbarth init.ops = &si5351_pll_ops;
15899abd5f05SSebastian Hesselbarth init.flags = 0;
15909abd5f05SSebastian Hesselbarth init.parent_names = parent_names;
15919abd5f05SSebastian Hesselbarth init.num_parents = num_parents;
15924d89c3d5SStephen Boyd ret = devm_clk_hw_register(&client->dev, &drvdata->pll[0].hw);
15934d89c3d5SStephen Boyd if (ret) {
15949abd5f05SSebastian Hesselbarth dev_err(&client->dev, "unable to register %s\n", init.name);
15951fffaf6aSSergej Sawazki return ret;
15969abd5f05SSebastian Hesselbarth }
15979abd5f05SSebastian Hesselbarth
15989abd5f05SSebastian Hesselbarth /* register PLLB or VXCO (Si5351B) */
15999abd5f05SSebastian Hesselbarth drvdata->pll[1].num = 1;
16009abd5f05SSebastian Hesselbarth drvdata->pll[1].drvdata = drvdata;
16019abd5f05SSebastian Hesselbarth drvdata->pll[1].hw.init = &init;
16029abd5f05SSebastian Hesselbarth memset(&init, 0, sizeof(init));
16039abd5f05SSebastian Hesselbarth if (drvdata->variant == SI5351_VARIANT_B) {
16049abd5f05SSebastian Hesselbarth init.name = si5351_pll_names[2];
16059abd5f05SSebastian Hesselbarth init.ops = &si5351_vxco_ops;
1606803c4331SStephen Boyd init.flags = 0;
16079abd5f05SSebastian Hesselbarth init.parent_names = NULL;
16089abd5f05SSebastian Hesselbarth init.num_parents = 0;
16099abd5f05SSebastian Hesselbarth } else {
16109abd5f05SSebastian Hesselbarth init.name = si5351_pll_names[1];
16119abd5f05SSebastian Hesselbarth init.ops = &si5351_pll_ops;
16129abd5f05SSebastian Hesselbarth init.flags = 0;
16139abd5f05SSebastian Hesselbarth init.parent_names = parent_names;
16149abd5f05SSebastian Hesselbarth init.num_parents = num_parents;
16159abd5f05SSebastian Hesselbarth }
16164d89c3d5SStephen Boyd ret = devm_clk_hw_register(&client->dev, &drvdata->pll[1].hw);
16174d89c3d5SStephen Boyd if (ret) {
16189abd5f05SSebastian Hesselbarth dev_err(&client->dev, "unable to register %s\n", init.name);
16191fffaf6aSSergej Sawazki return ret;
16209abd5f05SSebastian Hesselbarth }
16219abd5f05SSebastian Hesselbarth
16229abd5f05SSebastian Hesselbarth /* register clk multisync and clk out divider */
16239abd5f05SSebastian Hesselbarth num_clocks = (drvdata->variant == SI5351_VARIANT_A3) ? 3 : 8;
16249abd5f05SSebastian Hesselbarth parent_names[0] = si5351_pll_names[0];
16259abd5f05SSebastian Hesselbarth if (drvdata->variant == SI5351_VARIANT_B)
16269abd5f05SSebastian Hesselbarth parent_names[1] = si5351_pll_names[2];
16279abd5f05SSebastian Hesselbarth else
16289abd5f05SSebastian Hesselbarth parent_names[1] = si5351_pll_names[1];
16299abd5f05SSebastian Hesselbarth
16309a78b169SMarkus Elfring drvdata->msynth = devm_kcalloc(&client->dev, num_clocks,
16319abd5f05SSebastian Hesselbarth sizeof(*drvdata->msynth), GFP_KERNEL);
16329a78b169SMarkus Elfring drvdata->clkout = devm_kcalloc(&client->dev, num_clocks,
16339abd5f05SSebastian Hesselbarth sizeof(*drvdata->clkout), GFP_KERNEL);
16344d89c3d5SStephen Boyd drvdata->num_clkout = num_clocks;
16359abd5f05SSebastian Hesselbarth
16364d89c3d5SStephen Boyd if (WARN_ON(!drvdata->msynth || !drvdata->clkout)) {
16370cd3be6eSSebastian Hesselbarth ret = -ENOMEM;
16381fffaf6aSSergej Sawazki return ret;
16390cd3be6eSSebastian Hesselbarth }
16409abd5f05SSebastian Hesselbarth
16419abd5f05SSebastian Hesselbarth for (n = 0; n < num_clocks; n++) {
16429abd5f05SSebastian Hesselbarth drvdata->msynth[n].num = n;
16439abd5f05SSebastian Hesselbarth drvdata->msynth[n].drvdata = drvdata;
16449abd5f05SSebastian Hesselbarth drvdata->msynth[n].hw.init = &init;
16459abd5f05SSebastian Hesselbarth memset(&init, 0, sizeof(init));
16469abd5f05SSebastian Hesselbarth init.name = si5351_msynth_names[n];
16479abd5f05SSebastian Hesselbarth init.ops = &si5351_msynth_ops;
16489abd5f05SSebastian Hesselbarth init.flags = 0;
16499abd5f05SSebastian Hesselbarth if (pdata->clkout[n].pll_master)
16509abd5f05SSebastian Hesselbarth init.flags |= CLK_SET_RATE_PARENT;
16519abd5f05SSebastian Hesselbarth init.parent_names = parent_names;
16529abd5f05SSebastian Hesselbarth init.num_parents = 2;
16534d89c3d5SStephen Boyd ret = devm_clk_hw_register(&client->dev,
16544d89c3d5SStephen Boyd &drvdata->msynth[n].hw);
16554d89c3d5SStephen Boyd if (ret) {
16569abd5f05SSebastian Hesselbarth dev_err(&client->dev, "unable to register %s\n",
16579abd5f05SSebastian Hesselbarth init.name);
16581fffaf6aSSergej Sawazki return ret;
16599abd5f05SSebastian Hesselbarth }
16609abd5f05SSebastian Hesselbarth }
16619abd5f05SSebastian Hesselbarth
16629abd5f05SSebastian Hesselbarth num_parents = (drvdata->variant == SI5351_VARIANT_C) ? 4 : 3;
16639abd5f05SSebastian Hesselbarth parent_names[2] = si5351_input_names[0];
16649abd5f05SSebastian Hesselbarth parent_names[3] = si5351_input_names[1];
16659abd5f05SSebastian Hesselbarth for (n = 0; n < num_clocks; n++) {
16669abd5f05SSebastian Hesselbarth parent_names[0] = si5351_msynth_names[n];
16679abd5f05SSebastian Hesselbarth parent_names[1] = (n < 4) ? si5351_msynth_names[0] :
16689abd5f05SSebastian Hesselbarth si5351_msynth_names[4];
16699abd5f05SSebastian Hesselbarth
16709abd5f05SSebastian Hesselbarth drvdata->clkout[n].num = n;
16719abd5f05SSebastian Hesselbarth drvdata->clkout[n].drvdata = drvdata;
16729abd5f05SSebastian Hesselbarth drvdata->clkout[n].hw.init = &init;
16739abd5f05SSebastian Hesselbarth memset(&init, 0, sizeof(init));
16749abd5f05SSebastian Hesselbarth init.name = si5351_clkout_names[n];
16759abd5f05SSebastian Hesselbarth init.ops = &si5351_clkout_ops;
16769abd5f05SSebastian Hesselbarth init.flags = 0;
16779abd5f05SSebastian Hesselbarth if (pdata->clkout[n].clkout_src == SI5351_CLKOUT_SRC_MSYNTH_N)
16789abd5f05SSebastian Hesselbarth init.flags |= CLK_SET_RATE_PARENT;
16799abd5f05SSebastian Hesselbarth init.parent_names = parent_names;
16809abd5f05SSebastian Hesselbarth init.num_parents = num_parents;
16814d89c3d5SStephen Boyd ret = devm_clk_hw_register(&client->dev,
16824d89c3d5SStephen Boyd &drvdata->clkout[n].hw);
16834d89c3d5SStephen Boyd if (ret) {
16849abd5f05SSebastian Hesselbarth dev_err(&client->dev, "unable to register %s\n",
16859abd5f05SSebastian Hesselbarth init.name);
16861fffaf6aSSergej Sawazki return ret;
16879abd5f05SSebastian Hesselbarth }
16886532cb71SMarek Belisko
16896532cb71SMarek Belisko /* set initial clkout rate */
16906532cb71SMarek Belisko if (pdata->clkout[n].rate != 0) {
16916532cb71SMarek Belisko int ret;
16924d89c3d5SStephen Boyd ret = clk_set_rate(drvdata->clkout[n].hw.clk,
16934d89c3d5SStephen Boyd pdata->clkout[n].rate);
16946532cb71SMarek Belisko if (ret != 0) {
16956532cb71SMarek Belisko dev_err(&client->dev, "Cannot set rate : %d\n",
16966532cb71SMarek Belisko ret);
16976532cb71SMarek Belisko }
16986532cb71SMarek Belisko }
16999abd5f05SSebastian Hesselbarth }
17009abd5f05SSebastian Hesselbarth
1701361dde3cSLars-Peter Clausen ret = devm_of_clk_add_hw_provider(&client->dev, si53351_of_clk_get,
17024d89c3d5SStephen Boyd drvdata);
17039abd5f05SSebastian Hesselbarth if (ret) {
17049abd5f05SSebastian Hesselbarth dev_err(&client->dev, "unable to add clk provider\n");
17051fffaf6aSSergej Sawazki return ret;
17069abd5f05SSebastian Hesselbarth }
17079abd5f05SSebastian Hesselbarth
17089abd5f05SSebastian Hesselbarth return 0;
17099abd5f05SSebastian Hesselbarth }
17109abd5f05SSebastian Hesselbarth
17119abd5f05SSebastian Hesselbarth static struct i2c_driver si5351_driver = {
17129abd5f05SSebastian Hesselbarth .driver = {
17139abd5f05SSebastian Hesselbarth .name = "si5351",
17149abd5f05SSebastian Hesselbarth .of_match_table = of_match_ptr(si5351_dt_ids),
17159abd5f05SSebastian Hesselbarth },
171662279db5SUwe Kleine-König .probe = si5351_i2c_probe,
17179abd5f05SSebastian Hesselbarth .id_table = si5351_i2c_ids,
17189abd5f05SSebastian Hesselbarth };
17199abd5f05SSebastian Hesselbarth module_i2c_driver(si5351_driver);
17209abd5f05SSebastian Hesselbarth
17219abd5f05SSebastian Hesselbarth MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com");
17229abd5f05SSebastian Hesselbarth MODULE_DESCRIPTION("Silicon Labs Si5351A/B/C clock generator driver");
17239abd5f05SSebastian Hesselbarth MODULE_LICENSE("GPL");
1724