diff options
Diffstat (limited to 'drivers/clk/st/clkgen-fsyn.c')
-rw-r--r-- | drivers/clk/st/clkgen-fsyn.c | 481 |
1 files changed, 128 insertions, 353 deletions
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index 09afeb85109c..14819d919df1 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -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); |