]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/clk/st/clkgen-fsyn.c
Merge tag 'trace-v4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux...
[karo-tx-linux.git] / drivers / clk / st / clkgen-fsyn.c
index 09afeb85109c7fc41bd14661891e25488849b616..14819d919df10d8871d8d6cb24700d06bbdb1671 100644 (file)
@@ -42,79 +42,6 @@ struct stm_fs {
        unsigned long nsdiv;
 };
 
-static const struct stm_fs fs216c65_rtbl[] = {
-       { .mdiv = 0x1f, .pe = 0x0,      .sdiv = 0x7,    .nsdiv = 0 },   /* 312.5 Khz */
-       { .mdiv = 0x17, .pe = 0x25ed,   .sdiv = 0x1,    .nsdiv = 0 },   /* 27    MHz */
-       { .mdiv = 0x1a, .pe = 0x7b36,   .sdiv = 0x2,    .nsdiv = 1 },   /* 36.87 MHz */
-       { .mdiv = 0x13, .pe = 0x0,      .sdiv = 0x2,    .nsdiv = 1 },   /* 48    MHz */
-       { .mdiv = 0x11, .pe = 0x1c72,   .sdiv = 0x1,    .nsdiv = 1 },   /* 108   MHz */
-};
-
-static const struct stm_fs fs432c65_rtbl[] = {
-       { .mdiv = 0x1f, .pe = 0x0,      .sdiv = 0x7,    .nsdiv = 0 },   /* 625     Khz */
-       { .mdiv = 0x13, .pe = 0x777c,   .sdiv = 0x4,    .nsdiv = 1 },   /* 25.175  MHz */
-       { .mdiv = 0x19, .pe = 0x4d35,   .sdiv = 0x2,    .nsdiv = 0 },   /* 25.200  MHz */
-       { .mdiv = 0x11, .pe = 0x1c72,   .sdiv = 0x4,    .nsdiv = 1 },   /* 27.000  MHz */
-       { .mdiv = 0x17, .pe = 0x28f5,   .sdiv = 0x2,    .nsdiv = 0 },   /* 27.027  MHz */
-       { .mdiv = 0x16, .pe = 0x3359,   .sdiv = 0x2,    .nsdiv = 0 },   /* 28.320  MHz */
-       { .mdiv = 0x1f, .pe = 0x2083,   .sdiv = 0x3,    .nsdiv = 1 },   /* 30.240  MHz */
-       { .mdiv = 0x1e, .pe = 0x430d,   .sdiv = 0x3,    .nsdiv = 1 },   /* 31.500  MHz */
-       { .mdiv = 0x17, .pe = 0x0,      .sdiv = 0x3,    .nsdiv = 1 },   /* 40.000  MHz */
-       { .mdiv = 0x19, .pe = 0x121a,   .sdiv = 0x1,    .nsdiv = 0 },   /* 49.500  MHz */
-       { .mdiv = 0x13, .pe = 0x6667,   .sdiv = 0x3,    .nsdiv = 1 },   /* 50.000  MHz */
-       { .mdiv = 0x10, .pe = 0x1ee6,   .sdiv = 0x3,    .nsdiv = 1 },   /* 57.284  MHz */
-       { .mdiv = 0x1d, .pe = 0x3b14,   .sdiv = 0x2,    .nsdiv = 1 },   /* 65.000  MHz */
-       { .mdiv = 0x12, .pe = 0x7c65,   .sdiv = 0x1,    .nsdiv = 0 },   /* 71.000  MHz */
-       { .mdiv = 0x19, .pe = 0xecd,    .sdiv = 0x2,    .nsdiv = 1 },   /* 74.176  MHz */
-       { .mdiv = 0x19, .pe = 0x121a,   .sdiv = 0x2,    .nsdiv = 1 },   /* 74.250  MHz */
-       { .mdiv = 0x19, .pe = 0x3334,   .sdiv = 0x2,    .nsdiv = 1 },   /* 75.000  MHz */
-       { .mdiv = 0x18, .pe = 0x5138,   .sdiv = 0x2,    .nsdiv = 1 },   /* 78.800  MHz */
-       { .mdiv = 0x1d, .pe = 0x77d,    .sdiv = 0x0,    .nsdiv = 0 },   /* 85.500  MHz */
-       { .mdiv = 0x1c, .pe = 0x13d5,   .sdiv = 0x0,    .nsdiv = 0 },   /* 88.750  MHz */
-       { .mdiv = 0x11, .pe = 0x1c72,   .sdiv = 0x2,    .nsdiv = 1 },   /* 108.000 MHz */
-       { .mdiv = 0x17, .pe = 0x28f5,   .sdiv = 0x0,    .nsdiv = 0 },   /* 108.108 MHz */
-       { .mdiv = 0x10, .pe = 0x6e26,   .sdiv = 0x2,    .nsdiv = 1 },   /* 118.963 MHz */
-       { .mdiv = 0x15, .pe = 0x3e63,   .sdiv = 0x0,    .nsdiv = 0 },   /* 119.000 MHz */
-       { .mdiv = 0x1c, .pe = 0x471d,   .sdiv = 0x1,    .nsdiv = 1 },   /* 135.000 MHz */
-       { .mdiv = 0x19, .pe = 0xecd,    .sdiv = 0x1,    .nsdiv = 1 },   /* 148.352 MHz */
-       { .mdiv = 0x19, .pe = 0x121a,   .sdiv = 0x1,    .nsdiv = 1 },   /* 148.500 MHz */
-       { .mdiv = 0x19, .pe = 0x121a,   .sdiv = 0x0,    .nsdiv = 1 },   /* 297     MHz */
-};
-
-static const struct stm_fs fs660c32_rtbl[] = {
-       { .mdiv = 0x14, .pe = 0x376b,   .sdiv = 0x4,    .nsdiv = 1 },   /* 25.175  MHz */
-       { .mdiv = 0x14, .pe = 0x30c3,   .sdiv = 0x4,    .nsdiv = 1 },   /* 25.200  MHz */
-       { .mdiv = 0x10, .pe = 0x71c7,   .sdiv = 0x4,    .nsdiv = 1 },   /* 27.000  MHz */
-       { .mdiv = 0x00, .pe = 0x47af,   .sdiv = 0x3,    .nsdiv = 0 },   /* 27.027  MHz */
-       { .mdiv = 0x0e, .pe = 0x4e1a,   .sdiv = 0x4,    .nsdiv = 1 },   /* 28.320  MHz */
-       { .mdiv = 0x0b, .pe = 0x534d,   .sdiv = 0x4,    .nsdiv = 1 },   /* 30.240  MHz */
-       { .mdiv = 0x17, .pe = 0x6fbf,   .sdiv = 0x2,    .nsdiv = 0 },   /* 31.500  MHz */
-       { .mdiv = 0x01, .pe = 0x0,      .sdiv = 0x4,    .nsdiv = 1 },   /* 40.000  MHz */
-       { .mdiv = 0x15, .pe = 0x2aab,   .sdiv = 0x3,    .nsdiv = 1 },   /* 49.500  MHz */
-       { .mdiv = 0x14, .pe = 0x6666,   .sdiv = 0x3,    .nsdiv = 1 },   /* 50.000  MHz */
-       { .mdiv = 0x1d, .pe = 0x395f,   .sdiv = 0x1,    .nsdiv = 0 },   /* 57.284  MHz */
-       { .mdiv = 0x08, .pe = 0x4ec5,   .sdiv = 0x3,    .nsdiv = 1 },   /* 65.000  MHz */
-       { .mdiv = 0x05, .pe = 0x1770,   .sdiv = 0x3,    .nsdiv = 1 },   /* 71.000  MHz */
-       { .mdiv = 0x03, .pe = 0x4ba7,   .sdiv = 0x3,    .nsdiv = 1 },   /* 74.176  MHz */
-       { .mdiv = 0x0f, .pe = 0x3426,   .sdiv = 0x1,    .nsdiv = 0 },   /* 74.250  MHz */
-       { .mdiv = 0x0e, .pe = 0x7777,   .sdiv = 0x1,    .nsdiv = 0 },   /* 75.000  MHz */
-       { .mdiv = 0x01, .pe = 0x4053,   .sdiv = 0x3,    .nsdiv = 1 },   /* 78.800  MHz */
-       { .mdiv = 0x09, .pe = 0x15b5,   .sdiv = 0x1,    .nsdiv = 0 },   /* 85.500  MHz */
-       { .mdiv = 0x1b, .pe = 0x3f19,   .sdiv = 0x2,    .nsdiv = 1 },   /* 88.750  MHz */
-       { .mdiv = 0x10, .pe = 0x71c7,   .sdiv = 0x2,    .nsdiv = 1 },   /* 108.000 MHz */
-       { .mdiv = 0x00, .pe = 0x47af,   .sdiv = 0x1,    .nsdiv = 0 },   /* 108.108 MHz */
-       { .mdiv = 0x0c, .pe = 0x3118,   .sdiv = 0x2,    .nsdiv = 1 },   /* 118.963 MHz */
-       { .mdiv = 0x0c, .pe = 0x2f54,   .sdiv = 0x2,    .nsdiv = 1 },   /* 119.000 MHz */
-       { .mdiv = 0x07, .pe = 0xe39,    .sdiv = 0x2,    .nsdiv = 1 },   /* 135.000 MHz */
-       { .mdiv = 0x03, .pe = 0x4ba7,   .sdiv = 0x2,    .nsdiv = 1 },   /* 148.352 MHz */
-       { .mdiv = 0x0f, .pe = 0x3426,   .sdiv = 0x0,    .nsdiv = 0 },   /* 148.500 MHz */
-       { .mdiv = 0x03, .pe = 0x4ba7,   .sdiv = 0x1,    .nsdiv = 1 },   /* 296.704 MHz */
-       { .mdiv = 0x03, .pe = 0x471c,   .sdiv = 0x1,    .nsdiv = 1 },   /* 297.000 MHz */
-       { .mdiv = 0x00, .pe = 0x295f,   .sdiv = 0x1,    .nsdiv = 1 },   /* 326.700 MHz */
-       { .mdiv = 0x1f, .pe = 0x3633,   .sdiv = 0x0,    .nsdiv = 1 },   /* 333.000 MHz */
-       { .mdiv = 0x1c, .pe = 0x0,      .sdiv = 0x0,    .nsdiv = 1 },   /* 352.000 Mhz */
-};
-
 struct clkgen_quadfs_data {
        bool reset_present;
        bool bwfilter_present;
@@ -138,174 +65,18 @@ struct clkgen_quadfs_data {
        struct clkgen_field nsdiv[QUADFS_MAX_CHAN];
 
        const struct clk_ops *pll_ops;
-       const struct stm_fs *rtbl;
-       u8 rtbl_cnt;
+       int  (*get_params)(unsigned long, unsigned long, struct stm_fs *);
        int  (*get_rate)(unsigned long , const struct stm_fs *,
                        unsigned long *);
 };
 
-static const struct clk_ops st_quadfs_pll_c65_ops;
 static const struct clk_ops st_quadfs_pll_c32_ops;
-static const struct clk_ops st_quadfs_fs216c65_ops;
-static const struct clk_ops st_quadfs_fs432c65_ops;
 static const struct clk_ops st_quadfs_fs660c32_ops;
 
-static int clk_fs216c65_get_rate(unsigned long, const struct stm_fs *,
-               unsigned long *);
-static int clk_fs432c65_get_rate(unsigned long, const struct stm_fs *,
-               unsigned long *);
+static int clk_fs660c32_dig_get_params(unsigned long input,
+               unsigned long output, struct stm_fs *fs);
 static int clk_fs660c32_dig_get_rate(unsigned long, const struct stm_fs *,
                unsigned long *);
-/*
- * Values for all of the standalone instances of this clock
- * generator found in STiH415 and STiH416 SYSCFG register banks. Note
- * that the individual channel standby control bits (nsb) are in the
- * first register along with the PLL control bits.
- */
-static const struct clkgen_quadfs_data st_fs216c65_416 = {
-       /* 416 specific */
-       .npda   = CLKGEN_FIELD(0x0, 0x1, 14),
-       .nsb    = { CLKGEN_FIELD(0x0, 0x1, 10),
-                   CLKGEN_FIELD(0x0, 0x1, 11),
-                   CLKGEN_FIELD(0x0, 0x1, 12),
-                   CLKGEN_FIELD(0x0, 0x1, 13) },
-       .nsdiv_present = true,
-       .nsdiv  = { CLKGEN_FIELD(0x0, 0x1, 18),
-                   CLKGEN_FIELD(0x0, 0x1, 19),
-                   CLKGEN_FIELD(0x0, 0x1, 20),
-                   CLKGEN_FIELD(0x0, 0x1, 21) },
-       .mdiv   = { CLKGEN_FIELD(0x4, 0x1f, 0),
-                   CLKGEN_FIELD(0x14, 0x1f, 0),
-                   CLKGEN_FIELD(0x24, 0x1f, 0),
-                   CLKGEN_FIELD(0x34, 0x1f, 0) },
-       .en     = { CLKGEN_FIELD(0x10, 0x1, 0),
-                   CLKGEN_FIELD(0x20, 0x1, 0),
-                   CLKGEN_FIELD(0x30, 0x1, 0),
-                   CLKGEN_FIELD(0x40, 0x1, 0) },
-       .ndiv   = CLKGEN_FIELD(0x0, 0x1, 15),
-       .bwfilter_present = true,
-       .ref_bw = CLKGEN_FIELD(0x0, 0x3, 16),
-       .pe     = { CLKGEN_FIELD(0x8, 0xffff, 0),
-                   CLKGEN_FIELD(0x18, 0xffff, 0),
-                   CLKGEN_FIELD(0x28, 0xffff, 0),
-                   CLKGEN_FIELD(0x38, 0xffff, 0) },
-       .sdiv   = { CLKGEN_FIELD(0xC, 0x7, 0),
-                   CLKGEN_FIELD(0x1C, 0x7, 0),
-                   CLKGEN_FIELD(0x2C, 0x7, 0),
-                   CLKGEN_FIELD(0x3C, 0x7, 0) },
-       .pll_ops        = &st_quadfs_pll_c65_ops,
-       .rtbl           = fs216c65_rtbl,
-       .rtbl_cnt       = ARRAY_SIZE(fs216c65_rtbl),
-       .get_rate       = clk_fs216c65_get_rate,
-};
-
-static const struct clkgen_quadfs_data st_fs432c65_416 = {
-       .npda   = CLKGEN_FIELD(0x0, 0x1, 14),
-       .nsb    = { CLKGEN_FIELD(0x0, 0x1, 10),
-                   CLKGEN_FIELD(0x0, 0x1, 11),
-                   CLKGEN_FIELD(0x0, 0x1, 12),
-                   CLKGEN_FIELD(0x0, 0x1, 13) },
-       .nsdiv_present = true,
-       .nsdiv  = { CLKGEN_FIELD(0x0, 0x1, 18),
-                  CLKGEN_FIELD(0x0, 0x1, 19),
-                  CLKGEN_FIELD(0x0, 0x1, 20),
-                  CLKGEN_FIELD(0x0, 0x1, 21) },
-       .mdiv   = { CLKGEN_FIELD(0x4, 0x1f, 0),
-                   CLKGEN_FIELD(0x14, 0x1f, 0),
-                   CLKGEN_FIELD(0x24, 0x1f, 0),
-                   CLKGEN_FIELD(0x34, 0x1f, 0) },
-       .en     = { CLKGEN_FIELD(0x10, 0x1, 0),
-                   CLKGEN_FIELD(0x20, 0x1, 0),
-                   CLKGEN_FIELD(0x30, 0x1, 0),
-                   CLKGEN_FIELD(0x40, 0x1, 0) },
-       .ndiv   = CLKGEN_FIELD(0x0, 0x1, 15),
-       .bwfilter_present = true,
-       .ref_bw = CLKGEN_FIELD(0x0, 0x3, 16),
-       .pe     = { CLKGEN_FIELD(0x8, 0xffff, 0),
-                   CLKGEN_FIELD(0x18, 0xffff, 0),
-                   CLKGEN_FIELD(0x28, 0xffff, 0),
-                   CLKGEN_FIELD(0x38, 0xffff, 0) },
-       .sdiv   = { CLKGEN_FIELD(0xC, 0x7, 0),
-                   CLKGEN_FIELD(0x1C, 0x7, 0),
-                   CLKGEN_FIELD(0x2C, 0x7, 0),
-                   CLKGEN_FIELD(0x3C, 0x7, 0) },
-       .pll_ops        = &st_quadfs_pll_c65_ops,
-       .rtbl           = fs432c65_rtbl,
-       .rtbl_cnt       = ARRAY_SIZE(fs432c65_rtbl),
-       .get_rate       = clk_fs432c65_get_rate,
-};
-
-static const struct clkgen_quadfs_data st_fs660c32_E_416 = {
-       .npda   = CLKGEN_FIELD(0x0, 0x1, 14),
-       .nsb    = { CLKGEN_FIELD(0x0, 0x1, 10),
-                   CLKGEN_FIELD(0x0, 0x1, 11),
-                   CLKGEN_FIELD(0x0, 0x1, 12),
-                   CLKGEN_FIELD(0x0, 0x1, 13) },
-       .nsdiv_present = true,
-       .nsdiv  = { CLKGEN_FIELD(0x0, 0x1, 18),
-                   CLKGEN_FIELD(0x0, 0x1, 19),
-                   CLKGEN_FIELD(0x0, 0x1, 20),
-                   CLKGEN_FIELD(0x0, 0x1, 21) },
-       .mdiv   = { CLKGEN_FIELD(0x4, 0x1f, 0),
-                   CLKGEN_FIELD(0x14, 0x1f, 0),
-                   CLKGEN_FIELD(0x24, 0x1f, 0),
-                   CLKGEN_FIELD(0x34, 0x1f, 0) },
-       .en     = { CLKGEN_FIELD(0x10, 0x1, 0),
-                   CLKGEN_FIELD(0x20, 0x1, 0),
-                   CLKGEN_FIELD(0x30, 0x1, 0),
-                   CLKGEN_FIELD(0x40, 0x1, 0) },
-       .ndiv   = CLKGEN_FIELD(0x0, 0x7, 15),
-       .pe     = { CLKGEN_FIELD(0x8, 0x7fff, 0),
-                   CLKGEN_FIELD(0x18, 0x7fff, 0),
-                   CLKGEN_FIELD(0x28, 0x7fff, 0),
-                   CLKGEN_FIELD(0x38, 0x7fff, 0) },
-       .sdiv   = { CLKGEN_FIELD(0xC, 0xf, 0),
-                   CLKGEN_FIELD(0x1C, 0xf, 0),
-                   CLKGEN_FIELD(0x2C, 0xf, 0),
-                   CLKGEN_FIELD(0x3C, 0xf, 0) },
-       .lockstatus_present = true,
-       .lock_status = CLKGEN_FIELD(0xAC, 0x1, 0),
-       .pll_ops        = &st_quadfs_pll_c32_ops,
-       .rtbl           = fs660c32_rtbl,
-       .rtbl_cnt       = ARRAY_SIZE(fs660c32_rtbl),
-       .get_rate       = clk_fs660c32_dig_get_rate,
-};
-
-static const struct clkgen_quadfs_data st_fs660c32_F_416 = {
-       .npda   = CLKGEN_FIELD(0x0, 0x1, 14),
-       .nsb    = { CLKGEN_FIELD(0x0, 0x1, 10),
-                   CLKGEN_FIELD(0x0, 0x1, 11),
-                   CLKGEN_FIELD(0x0, 0x1, 12),
-                   CLKGEN_FIELD(0x0, 0x1, 13) },
-       .nsdiv_present = true,
-       .nsdiv  = { CLKGEN_FIELD(0x0, 0x1, 18),
-                   CLKGEN_FIELD(0x0, 0x1, 19),
-                   CLKGEN_FIELD(0x0, 0x1, 20),
-                   CLKGEN_FIELD(0x0, 0x1, 21) },
-       .mdiv   = { CLKGEN_FIELD(0x4, 0x1f, 0),
-                   CLKGEN_FIELD(0x14, 0x1f, 0),
-                   CLKGEN_FIELD(0x24, 0x1f, 0),
-                   CLKGEN_FIELD(0x34, 0x1f, 0) },
-       .en     = { CLKGEN_FIELD(0x10, 0x1, 0),
-                   CLKGEN_FIELD(0x20, 0x1, 0),
-                   CLKGEN_FIELD(0x30, 0x1, 0),
-                   CLKGEN_FIELD(0x40, 0x1, 0) },
-       .ndiv   = CLKGEN_FIELD(0x0, 0x7, 15),
-       .pe     = { CLKGEN_FIELD(0x8, 0x7fff, 0),
-                   CLKGEN_FIELD(0x18, 0x7fff, 0),
-                   CLKGEN_FIELD(0x28, 0x7fff, 0),
-                   CLKGEN_FIELD(0x38, 0x7fff, 0) },
-       .sdiv   = { CLKGEN_FIELD(0xC, 0xf, 0),
-                   CLKGEN_FIELD(0x1C, 0xf, 0),
-                   CLKGEN_FIELD(0x2C, 0xf, 0),
-                   CLKGEN_FIELD(0x3C, 0xf, 0) },
-       .lockstatus_present = true,
-       .lock_status = CLKGEN_FIELD(0xEC, 0x1, 0),
-       .pll_ops        = &st_quadfs_pll_c32_ops,
-       .rtbl           = fs660c32_rtbl,
-       .rtbl_cnt       = ARRAY_SIZE(fs660c32_rtbl),
-       .get_rate       = clk_fs660c32_dig_get_rate,
-};
 
 static const struct clkgen_quadfs_data st_fs660c32_C = {
        .nrst_present = true,
@@ -345,8 +116,7 @@ static const struct clkgen_quadfs_data st_fs660c32_C = {
        .powerup_polarity = 1,
        .standby_polarity = 1,
        .pll_ops        = &st_quadfs_pll_c32_ops,
-       .rtbl           = fs660c32_rtbl,
-       .rtbl_cnt       = ARRAY_SIZE(fs660c32_rtbl),
+       .get_params     = clk_fs660c32_dig_get_params,
        .get_rate       = clk_fs660c32_dig_get_rate,
 };
 
@@ -388,8 +158,7 @@ static const struct clkgen_quadfs_data st_fs660c32_D = {
        .powerup_polarity = 1,
        .standby_polarity = 1,
        .pll_ops        = &st_quadfs_pll_c32_ops,
-       .rtbl           = fs660c32_rtbl,
-       .rtbl_cnt       = ARRAY_SIZE(fs660c32_rtbl),
+       .get_params     = clk_fs660c32_dig_get_params,
        .get_rate       = clk_fs660c32_dig_get_rate,};
 
 /**
@@ -605,12 +374,6 @@ static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate,
        return 0;
 }
 
-static const struct clk_ops st_quadfs_pll_c65_ops = {
-       .enable         = quadfs_pll_enable,
-       .disable        = quadfs_pll_disable,
-       .is_enabled     = quadfs_pll_is_enabled,
-};
-
 static const struct clk_ops st_quadfs_pll_c32_ops = {
        .enable         = quadfs_pll_enable,
        .disable        = quadfs_pll_disable,
@@ -797,48 +560,6 @@ static int quadfs_fsynth_is_enabled(struct clk_hw *hw)
        return fs->data->standby_polarity ? !nsb : !!nsb;
 }
 
-#define P15                    (uint64_t)(1 << 15)
-
-static int clk_fs216c65_get_rate(unsigned long input, const struct stm_fs *fs,
-               unsigned long *rate)
-{
-       uint64_t res;
-       unsigned long ns;
-       unsigned long nd = 8; /* ndiv stuck at 0 => val = 8 */
-       unsigned long s;
-       long m;
-
-       m = fs->mdiv - 32;
-       s = 1 << (fs->sdiv + 1);
-       ns = (fs->nsdiv ? 1 : 3);
-
-       res = (uint64_t)(s * ns * P15 * (uint64_t)(m + 33));
-       res = res - (s * ns * fs->pe);
-       *rate = div64_u64(P15 * nd * input * 32, res);
-
-       return 0;
-}
-
-static int clk_fs432c65_get_rate(unsigned long input, const struct stm_fs *fs,
-               unsigned long *rate)
-{
-       uint64_t res;
-       unsigned long nd = 16; /* ndiv value; stuck at 0 (30Mhz input) */
-       long m;
-       unsigned long sd;
-       unsigned long ns;
-
-       m = fs->mdiv - 32;
-       sd = 1 << (fs->sdiv + 1);
-       ns = (fs->nsdiv ? 1 : 3);
-
-       res = (uint64_t)(sd * ns * P15 * (uint64_t)(m + 33));
-       res = res - (sd * ns * fs->pe);
-       *rate = div64_u64(P15 * nd * input * 32, res);
-
-       return 0;
-}
-
 #define P20            (uint64_t)(1 << 20)
 
 static int clk_fs660c32_dig_get_rate(unsigned long input,
@@ -864,6 +585,107 @@ static int clk_fs660c32_dig_get_rate(unsigned long input,
        return 0;
 }
 
+
+static int clk_fs660c32_get_pe(int m, int si, unsigned long *deviation,
+               signed long input, unsigned long output, uint64_t *p,
+               struct stm_fs *fs)
+{
+       unsigned long new_freq, new_deviation;
+       struct stm_fs fs_tmp;
+       uint64_t val;
+
+       val = (uint64_t)output << si;
+
+       *p = (uint64_t)input * P20 - (32LL  + (uint64_t)m) * val * (P20 / 32LL);
+
+       *p = div64_u64(*p, val);
+
+       if (*p > 32767LL)
+               return 1;
+
+       fs_tmp.mdiv = (unsigned long) m;
+       fs_tmp.pe = (unsigned long)*p;
+       fs_tmp.sdiv = si;
+       fs_tmp.nsdiv = 1;
+
+       clk_fs660c32_dig_get_rate(input, &fs_tmp, &new_freq);
+
+       new_deviation = abs(output - new_freq);
+
+       if (new_deviation < *deviation) {
+               fs->mdiv = m;
+               fs->pe = (unsigned long)*p;
+               fs->sdiv = si;
+               fs->nsdiv = 1;
+               *deviation = new_deviation;
+       }
+       return 0;
+}
+
+static int clk_fs660c32_dig_get_params(unsigned long input,
+               unsigned long output, struct stm_fs *fs)
+{
+       int si; /* sdiv_reg (8 downto 0) */
+       int m; /* md value */
+       unsigned long new_freq, new_deviation;
+       /* initial condition to say: "infinite deviation" */
+       unsigned long deviation = ~0;
+       uint64_t p, p1, p2;     /* pe value */
+       int r1, r2;
+
+       struct stm_fs fs_tmp;
+
+       for (si = 0; (si <= 8) && deviation; si++) {
+
+               /* Boundary test to avoid useless iteration */
+               r1 = clk_fs660c32_get_pe(0, si, &deviation,
+                               input, output, &p1, fs);
+               r2 = clk_fs660c32_get_pe(31, si, &deviation,
+                               input, output, &p2, fs);
+
+               /* No solution */
+               if (r1 && r2 && (p1 > p2))
+                       continue;
+
+               /* Try to find best deviation */
+               for (m = 1; (m < 31) && deviation; m++)
+                       clk_fs660c32_get_pe(m, si, &deviation,
+                                       input, output, &p, fs);
+
+       }
+
+       if (deviation == ~0) /* No solution found */
+               return -1;
+
+       /* pe fine tuning if deviation not 0: +/- 2 around computed pe value */
+       if (deviation) {
+               fs_tmp.mdiv = fs->mdiv;
+               fs_tmp.sdiv = fs->sdiv;
+               fs_tmp.nsdiv = fs->nsdiv;
+
+               if (fs->pe > 2)
+                       p2 = fs->pe - 2;
+               else
+                       p2 = 0;
+
+               for (; p2 < 32768ll && (p2 <= (fs->pe + 2)); p2++) {
+                       fs_tmp.pe = (unsigned long)p2;
+
+                       clk_fs660c32_dig_get_rate(input, &fs_tmp, &new_freq);
+
+                       new_deviation = abs(output - new_freq);
+
+                       /* Check if this is a better solution */
+                       if (new_deviation < deviation) {
+                               fs->pe = (unsigned long)p2;
+                               deviation = new_deviation;
+
+                       }
+               }
+       }
+       return 0;
+}
+
 static int quadfs_fsynt_get_hw_value_for_recalc(struct st_clk_quadfs_fsynth *fs,
                struct stm_fs *params)
 {
@@ -899,38 +721,14 @@ static long quadfs_find_best_rate(struct clk_hw *hw, unsigned long drate,
        struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
        int (*clk_fs_get_rate)(unsigned long ,
                                const struct stm_fs *, unsigned long *);
-       struct stm_fs prev_params;
-       unsigned long prev_rate, rate = 0;
-       unsigned long diff_rate, prev_diff_rate = ~0;
-       int index;
+       int (*clk_fs_get_params)(unsigned long, unsigned long, struct stm_fs *);
+       unsigned long rate = 0;
 
        clk_fs_get_rate = fs->data->get_rate;
+       clk_fs_get_params = fs->data->get_params;
 
-       for (index = 0; index < fs->data->rtbl_cnt; index++) {
-               prev_rate = rate;
-
-               *params = fs->data->rtbl[index];
-               prev_params = *params;
-
-               clk_fs_get_rate(prate, &fs->data->rtbl[index], &rate);
-
-               diff_rate = abs(drate - rate);
-
-               if (diff_rate > prev_diff_rate) {
-                       rate = prev_rate;
-                       *params = prev_params;
-                       break;
-               }
-
-               prev_diff_rate = diff_rate;
-
-               if (drate == rate)
-                       return rate;
-       }
-
-
-       if (index == fs->data->rtbl_cnt)
-               *params = prev_params;
+       if (!clk_fs_get_params(prate, drate, params))
+               clk_fs_get_rate(prate, params, &rate);
 
        return rate;
 }
@@ -1063,34 +861,6 @@ static struct clk * __init st_clk_register_quadfs_fsynth(
        return clk;
 }
 
-static const struct of_device_id quadfs_of_match[] = {
-       {
-               .compatible = "st,stih416-quadfs216",
-               .data = &st_fs216c65_416
-       },
-       {
-               .compatible = "st,stih416-quadfs432",
-               .data = &st_fs432c65_416
-       },
-       {
-               .compatible = "st,stih416-quadfs660-E",
-               .data = &st_fs660c32_E_416
-       },
-       {
-               .compatible = "st,stih416-quadfs660-F",
-               .data = &st_fs660c32_F_416
-       },
-       {
-               .compatible = "st,stih407-quadfs660-C",
-               .data = &st_fs660c32_C
-       },
-       {
-               .compatible = "st,stih407-quadfs660-D",
-               .data = &st_fs660c32_D
-       },
-       {}
-};
-
 static void __init st_of_create_quadfs_fsynths(
                struct device_node *np, const char *pll_name,
                struct clkgen_quadfs_data *quadfs, void __iomem *reg,
@@ -1150,18 +920,14 @@ static void __init st_of_create_quadfs_fsynths(
        of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
 }
 
-static void __init st_of_quadfs_setup(struct device_node *np)
+static void __init st_of_quadfs_setup(struct device_node *np,
+               struct clkgen_quadfs_data *data)
 {
-       const struct of_device_id *match;
        struct clk *clk;
        const char *pll_name, *clk_parent_name;
        void __iomem *reg;
        spinlock_t *lock;
 
-       match = of_match_node(quadfs_of_match, np);
-       if (WARN_ON(!match))
-               return;
-
        reg = of_iomap(np, 0);
        if (!reg)
                return;
@@ -1180,8 +946,8 @@ static void __init st_of_quadfs_setup(struct device_node *np)
 
        spin_lock_init(lock);
 
-       clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name,
-                       (struct clkgen_quadfs_data *) match->data, reg, lock);
+       clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, data,
+                       reg, lock);
        if (IS_ERR(clk))
                goto err_exit;
        else
@@ -1190,11 +956,20 @@ static void __init st_of_quadfs_setup(struct device_node *np)
                        __clk_get_name(clk_get_parent(clk)),
                        (unsigned int)clk_get_rate(clk));
 
-       st_of_create_quadfs_fsynths(np, pll_name,
-                                   (struct clkgen_quadfs_data *)match->data,
-                                   reg, lock);
+       st_of_create_quadfs_fsynths(np, pll_name, data, reg, lock);
 
 err_exit:
        kfree(pll_name); /* No longer need local copy of the PLL name */
 }
-CLK_OF_DECLARE(quadfs, "st,quadfs", st_of_quadfs_setup);
+
+static void __init st_of_quadfs660C_setup(struct device_node *np)
+{
+       st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_C);
+}
+CLK_OF_DECLARE(quadfs660C, "st,quadfs-pll", st_of_quadfs660C_setup);
+
+static void __init st_of_quadfs660D_setup(struct device_node *np)
+{
+       st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_D);
+}
+CLK_OF_DECLARE(quadfs660D, "st,quadfs", st_of_quadfs660D_setup);