11
11
#include <linux/gcd.h>
12
12
#include <linux/rational.h>
13
13
#include <linux/debugfs.h>
14
+ #include <linux/units.h>
14
15
15
16
#include <linux/clk.h>
16
17
#include <linux/clk-provider.h>
@@ -328,11 +329,11 @@ struct hmc7044 {
328
329
struct clk_onecell_data clk_data ;
329
330
struct clk * clk_input [4 ];
330
331
struct mutex lock ;
331
- struct jesd204_dev * jdev ;
332
- u32 jdev_lmfc_lemc_rate ;
333
- u32 jdev_lmfc_lemc_gcd ;
334
- u32 jdev_max_sysref_freq ;
335
- u32 jdev_desired_sysref_freq ;
332
+ struct jesd204_dev * jdev ;
333
+ u64 jdev_lmfc_lemc_rate ;
334
+ u64 jdev_lmfc_lemc_gcd ;
335
+ u64 jdev_max_sysref_freq ;
336
+ u64 jdev_desired_sysref_freq ;
336
337
bool jdev_skip_sysref_freq_calc ;
337
338
bool is_sysref_provider ;
338
339
bool hmc_two_level_tree_sync_en ;
@@ -1600,6 +1601,7 @@ static int hmc7044_parse_dt(struct device *dev,
1600
1601
struct device_node * np = dev -> of_node , * chan_np ;
1601
1602
unsigned int cnt = 0 ;
1602
1603
int ret ;
1604
+ u32 tmp ;
1603
1605
1604
1606
if (hmc -> device_id == HMC7044 ) {
1605
1607
ret = of_property_read_u32_array (np ,
@@ -1691,12 +1693,17 @@ static int hmc7044_parse_dt(struct device *dev,
1691
1693
1692
1694
hmc -> hmc_two_level_tree_sync_en = of_property_read_bool (np , "adi,hmc-two-level-tree-sync-en" );
1693
1695
1694
- hmc -> jdev_max_sysref_freq = INT_MAX ;
1695
- of_property_read_u32 (np , "adi,jesd204-max-sysref-frequency-hz" ,
1696
- & hmc -> jdev_max_sysref_freq );
1696
+ tmp = INT_MAX ;
1697
+ of_property_read_u32 (np , "adi,jesd204-max-sysref-frequency-hz" , & tmp );
1698
+ hmc -> jdev_max_sysref_freq = (u64 )tmp * MICROHZ_PER_HZ ;
1699
+
1700
+ ret = of_property_read_u32 (np , "adi,jesd204-desired-sysref-frequency-hz" , & tmp );
1701
+ if (!ret ) {
1702
+ hmc -> jdev_desired_sysref_freq = (u64 )tmp * MICROHZ_PER_HZ ;
1703
+ }
1704
+
1705
+ of_property_read_u64 (np , "adi,jesd204-desired-sysref-frequency-uhz" , & hmc -> jdev_desired_sysref_freq );
1697
1706
1698
- of_property_read_u32 (np , "adi,jesd204-desired-sysref-frequency-hz" ,
1699
- & hmc -> jdev_desired_sysref_freq );
1700
1707
1701
1708
hmc -> jdev_skip_sysref_freq_calc =
1702
1709
of_property_read_bool (np , "adi,jesd204-skip-sysref-frequency-calc" );
@@ -1950,31 +1957,56 @@ static int hmc7044_continuous_chan_sync_enable(struct iio_dev *indio_dev, bool e
1950
1957
return 0 ;
1951
1958
}
1952
1959
1953
- static int hmc7044_lmfc_lemc_validate (struct hmc7044 * hmc , u64 dividend , u32 divisor )
1960
+ static u64 hmc7044_gcd_64 (u64 u , u64 v )
1961
+ {
1962
+ u64 t ;
1963
+
1964
+ while (v != 0 ) {
1965
+ t = u ;
1966
+ u = v ;
1967
+ div64_u64_rem (t , v , & v );
1968
+ }
1969
+
1970
+ return u ;
1971
+ }
1972
+
1973
+ static u64 hmc7044_get_rem (u64 dividend , u64 divisor )
1954
1974
{
1955
- u32 rem , rem_l , rem_u , gcd_val , min ;
1975
+ u64 rem ;
1956
1976
1957
- gcd_val = gcd (dividend , divisor );
1977
+ if (divisor == 0 )
1978
+ return 0 ;
1979
+
1980
+ div64_u64_rem (dividend , divisor , & rem );
1981
+ return rem ;
1982
+ }
1983
+
1984
+ static int hmc7044_lmfc_lemc_validate (struct hmc7044 * hmc , u64 dividend , u64 divisor )
1985
+ {
1986
+ u64 rem , rem_l , rem_u , gcd_val , min ;
1987
+
1988
+ gcd_val = hmc7044_gcd_64 (dividend , divisor );
1958
1989
min = DIV_ROUND_CLOSEST (hmc -> pll2_freq , HMC7044_OUT_DIV_MAX );
1959
1990
1960
1991
if (gcd_val >= min ) {
1961
1992
dev_dbg (& hmc -> spi -> dev ,
1962
- "%s: dividend=%llu divisor=%u GCD=%u (hmc->pll2_freq=%u, min=%u )" ,
1993
+ "%s: dividend=%llu divisor=%llu GCD=%llu (hmc->pll2_freq=%u, min=%llu )" ,
1963
1994
__func__ , dividend , divisor , gcd_val , hmc -> pll2_freq , min );
1964
1995
1965
1996
hmc -> jdev_lmfc_lemc_gcd = gcd_val ;
1966
1997
return 0 ;
1967
1998
}
1968
1999
1969
- div_u64_rem (hmc -> pll2_freq , divisor , & rem );
2000
+ rem = hmc7044_get_rem (hmc -> pll2_freq , divisor );
1970
2001
1971
2002
dev_dbg (& hmc -> spi -> dev ,
1972
- "%s: dividend=%llu divisor=%u GCD=%u rem=%u (hmc->pll2_freq=%u)" ,
2003
+ "%s: dividend=%llu divisor=%llu GCD=%llu rem=%llu (hmc->pll2_freq=%u)" ,
1973
2004
__func__ , dividend , divisor , gcd_val , rem , hmc -> pll2_freq );
1974
2005
1975
- div_u64_rem (dividend , divisor , & rem );
1976
- div_u64_rem (dividend , divisor - 1 , & rem_l );
1977
- div_u64_rem (dividend , divisor + 1 , & rem_u );
2006
+ rem = hmc7044_get_rem (dividend , divisor );
2007
+ rem_l = hmc7044_get_rem (dividend , divisor - 1 );
2008
+ rem_u = hmc7044_get_rem (dividend , divisor + 1 );
2009
+
1978
2010
1979
2011
if ((rem_l > rem ) && (rem_u > rem )) {
1980
2012
if (hmc -> jdev_lmfc_lemc_gcd )
@@ -1996,6 +2028,7 @@ static int hmc7044_jesd204_link_supported(struct jesd204_dev *jdev,
1996
2028
struct hmc7044 * hmc = iio_priv (indio_dev );
1997
2029
int ret ;
1998
2030
unsigned long rate ;
2031
+ u64 rate_uHz ;
1999
2032
2000
2033
if (reason != JESD204_STATE_OP_REASON_INIT ) {
2001
2034
hmc -> jdev_lmfc_lemc_rate = 0 ;
@@ -2014,24 +2047,27 @@ static int hmc7044_jesd204_link_supported(struct jesd204_dev *jdev,
2014
2047
return - EINVAL ;
2015
2048
}
2016
2049
2017
- rate = hmc -> jdev_desired_sysref_freq ;
2050
+ rate_uHz = hmc -> jdev_desired_sysref_freq ;
2018
2051
} else {
2019
2052
ret = jesd204_link_get_lmfc_lemc_rate (lnk , & rate );
2020
2053
if (ret < 0 )
2021
2054
return ret ;
2055
+
2056
+ rate_uHz = (u64 )rate * MICROHZ_PER_HZ + ret ;
2022
2057
}
2023
2058
2024
2059
if (hmc -> jdev_lmfc_lemc_rate ) {
2025
- hmc -> jdev_lmfc_lemc_rate = min (hmc -> jdev_lmfc_lemc_rate , ( u32 ) rate );
2026
- ret = hmc7044_lmfc_lemc_validate (hmc , hmc -> jdev_lmfc_lemc_gcd , ( u32 ) rate );
2060
+ hmc -> jdev_lmfc_lemc_rate = min (hmc -> jdev_lmfc_lemc_rate , rate_uHz );
2061
+ ret = hmc7044_lmfc_lemc_validate (hmc , hmc -> jdev_lmfc_lemc_gcd , rate_uHz );
2027
2062
} else {
2028
- hmc -> jdev_lmfc_lemc_rate = rate ;
2029
- ret = hmc7044_lmfc_lemc_validate (hmc , hmc -> pll2_freq , (u32 )rate );
2063
+ hmc -> jdev_lmfc_lemc_rate = rate_uHz ;
2064
+ ret = hmc7044_lmfc_lemc_validate (hmc , (u64 )hmc -> pll2_freq * MICROHZ_PER_HZ ,
2065
+ rate_uHz );
2030
2066
}
2031
2067
2032
- dev_dbg (dev , "%s:%d link_num %u LMFC/LEMC %u/%lu gcd %u \n" ,
2068
+ dev_dbg (dev , "%s:%d link_num %u LMFC/LEMC %llu/%llu gcd %llu \n" ,
2033
2069
__func__ , __LINE__ , lnk -> link_id , hmc -> jdev_lmfc_lemc_rate ,
2034
- rate , hmc -> jdev_lmfc_lemc_gcd );
2070
+ rate_uHz , hmc -> jdev_lmfc_lemc_gcd );
2035
2071
if (ret )
2036
2072
return ret ;
2037
2073
@@ -2199,39 +2235,41 @@ static int hmc7044_jesd204_link_pre_setup(struct jesd204_dev *jdev,
2199
2235
struct hmc7044 * hmc = iio_priv (indio_dev );
2200
2236
int i , ret ;
2201
2237
u32 sysref_timer ;
2238
+ u64 rem ;
2202
2239
2203
2240
if (reason != JESD204_STATE_OP_REASON_INIT )
2204
2241
return JESD204_STATE_CHANGE_DONE ;
2205
2242
2206
2243
dev_dbg (dev , "%s:%d link_num %u\n" , __func__ , __LINE__ , lnk -> link_id );
2207
2244
2208
- if (hmc -> jdev_desired_sysref_freq && (hmc -> jdev_lmfc_lemc_gcd %
2209
- hmc -> jdev_desired_sysref_freq == 0 )) {
2245
+ rem = hmc7044_get_rem (hmc -> jdev_lmfc_lemc_gcd , hmc -> jdev_desired_sysref_freq );
2246
+
2247
+ if (hmc -> jdev_desired_sysref_freq && rem == 0 ) {
2210
2248
hmc -> jdev_lmfc_lemc_gcd = hmc -> jdev_desired_sysref_freq ;
2211
2249
} else {
2212
2250
while ((hmc -> jdev_lmfc_lemc_gcd > hmc -> jdev_max_sysref_freq ) &&
2213
- (hmc -> jdev_lmfc_lemc_gcd %
2214
- (hmc -> jdev_lmfc_lemc_gcd >> 1 ) == 0 ))
2251
+ hmc7044_get_rem (hmc -> jdev_lmfc_lemc_gcd , hmc -> jdev_lmfc_lemc_gcd >> 1 ) == 0 )
2215
2252
hmc -> jdev_lmfc_lemc_gcd >>= 1 ;
2216
2253
}
2217
2254
/* Program the output channels */
2218
2255
for (i = 0 ; i < hmc -> num_channels ; i ++ ) {
2219
2256
if (hmc -> channels [i ].start_up_mode_dynamic_enable || hmc -> channels [i ].is_sysref ) {
2220
2257
long rate ;
2258
+ unsigned long ccf_rate = DIV_ROUND_CLOSEST_ULL (hmc -> jdev_lmfc_lemc_gcd , MICROHZ_PER_HZ );
2221
2259
2222
- dev_dbg (dev , "%s:%d Found SYSREF channel%u setting f=%u Hz\n" ,
2223
- __func__ , __LINE__ , hmc -> channels [i ].num , hmc -> jdev_lmfc_lemc_gcd );
2260
+ dev_dbg (dev , "%s:%d Found SYSREF channel%u setting f=%lu Hz\n" ,
2261
+ __func__ , __LINE__ , hmc -> channels [i ].num , ccf_rate );
2224
2262
2225
- rate = clk_round_rate (hmc -> clks [hmc -> channels [i ].num ], hmc -> jdev_lmfc_lemc_gcd );
2263
+ rate = clk_round_rate (hmc -> clks [hmc -> channels [i ].num ], ccf_rate );
2226
2264
2227
- if (rate == (long )hmc -> jdev_lmfc_lemc_gcd )
2228
- ret = clk_set_rate (hmc -> clks [hmc -> channels [i ].num ], hmc -> jdev_lmfc_lemc_gcd );
2265
+ if (rate == (long ) ccf_rate )
2266
+ ret = clk_set_rate (hmc -> clks [hmc -> channels [i ].num ], ccf_rate );
2229
2267
else
2230
2268
ret = - EINVAL ;
2231
2269
2232
2270
if (ret < 0 )
2233
- dev_err (dev , "%s: Link%u setting SYSREF rate %u failed (%d)\n" ,
2234
- __func__ , lnk -> link_id , hmc -> jdev_lmfc_lemc_gcd , ret );
2271
+ dev_err (dev , "%s: Link%u setting SYSREF rate %lu failed (%d)\n" ,
2272
+ __func__ , lnk -> link_id , ccf_rate , ret );
2235
2273
2236
2274
}
2237
2275
}
@@ -2241,7 +2279,7 @@ static int hmc7044_jesd204_link_pre_setup(struct jesd204_dev *jdev,
2241
2279
* output SYSREF frequency, and program it to be no faster than 4 MHz.
2242
2280
*/
2243
2281
2244
- sysref_timer = hmc -> jdev_lmfc_lemc_gcd / 2 ;
2282
+ sysref_timer = DIV_ROUND_CLOSEST_ULL ( hmc -> jdev_lmfc_lemc_gcd , MICROHZ_PER_HZ ) / 2 ;
2245
2283
2246
2284
while (sysref_timer >= 4000000U )
2247
2285
sysref_timer >>= 1 ;
0 commit comments