Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
meta-elphel393
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
meta-elphel393
Commits
bfaf4ab6
Commit
bfaf4ab6
authored
Dec 03, 2013
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
si5338: added frequency calculation
parent
69cf7478
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
663 additions
and
36 deletions
+663
-36
elphel393.dts
conf/machine/boards/elphel393/elphel393.dts
+1
-0
vsc3304.patch
recipes-kernel/linux/linux-xlnx/vsc3304.patch
+662
-36
No files found.
conf/machine/boards/elphel393/elphel393.dts
View file @
bfaf4ab6
...
@@ -188,6 +188,7 @@
...
@@ -188,6 +188,7 @@
si5338
,
in_p1_div
=
<
0
>;
/*
unused
*/
si5338
,
in_p1_div
=
<
0
>;
/*
unused
*/
si5338
,
in_p2_div
=
<
0
>;
/*
unused
*/
si5338
,
in_p2_div
=
<
0
>;
/*
unused
*/
si5338
,
in_mux
=
<
1
>;
/*
in
-
3
*/
si5338
,
in_mux
=
<
1
>;
/*
in
-
3
*/
si5338
,
fb_mux
=
<
2
>;
/*
no
clock
*/
si5338
,
in_frequency
=
<
25000000
>;
/*
25
MHz
*/
si5338
,
in_frequency
=
<
25000000
>;
/*
25
MHz
*/
};
};
gpio
@
20
{
gpio
@
20
{
...
...
recipes-kernel/linux/linux-xlnx/vsc3304.patch
View file @
bfaf4ab6
Index: git/drivers/misc/Kconfig
Index: git/drivers/misc/Kconfig
===================================================================
===================================================================
--- git.orig/drivers/misc/Kconfig 2013-12-0
1 13:21:03.113068339
-0700
--- git.orig/drivers/misc/Kconfig 2013-12-0
2 23:08:01.002329798
-0700
+++ git/drivers/misc/Kconfig 2013-12-0
1 13:21:06.549068375
-0700
+++ git/drivers/misc/Kconfig 2013-12-0
2 23:08:03.994329829
-0700
@@ -549,6 +549,19 @@
@@ -549,6 +549,19 @@
their requirements.
their requirements.
...
@@ -24,8 +24,8 @@ Index: git/drivers/misc/Kconfig
...
@@ -24,8 +24,8 @@ Index: git/drivers/misc/Kconfig
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/eeprom/Kconfig"
Index: git/drivers/misc/Makefile
Index: git/drivers/misc/Makefile
===================================================================
===================================================================
--- git.orig/drivers/misc/Makefile 2013-12-0
1 13:21:03.113068339
-0700
--- git.orig/drivers/misc/Makefile 2013-12-0
2 23:08:01.002329798
-0700
+++ git/drivers/misc/Makefile 2013-12-0
1 13:21:06.549068375
-0700
+++ git/drivers/misc/Makefile 2013-12-0
2 23:08:03.994329829
-0700
@@ -55,3 +55,5 @@
@@ -55,3 +55,5 @@
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
obj-$(CONFIG_SRAM) += sram.o
...
@@ -35,7 +35,7 @@ Index: git/drivers/misc/Makefile
...
@@ -35,7 +35,7 @@ Index: git/drivers/misc/Makefile
Index: git/drivers/misc/vsc330x.c
Index: git/drivers/misc/vsc330x.c
===================================================================
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ git/drivers/misc/vsc330x.c 2013-12-0
1 13:21:06.549068375
-0700
+++ git/drivers/misc/vsc330x.c 2013-12-0
2 23:08:03.998329829
-0700
@@ -0,0 +1,872 @@
@@ -0,0 +1,872 @@
+/*!***************************************************************************
+/*!***************************************************************************
+ *! FILE NAME : vsc330x.c
+ *! FILE NAME : vsc330x.c
...
@@ -912,8 +912,8 @@ Index: git/drivers/misc/vsc330x.c
...
@@ -912,8 +912,8 @@ Index: git/drivers/misc/vsc330x.c
Index: git/drivers/misc/si5338.c
Index: git/drivers/misc/si5338.c
===================================================================
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ git/drivers/misc/si5338.c 2013-12-0
1 17:28:06.337222090
-0700
+++ git/drivers/misc/si5338.c 2013-12-0
2 23:17:35.422335756
-0700
@@ -0,0 +1,
867
@@
@@ -0,0 +1,
1493
@@
+/*!***************************************************************************
+/*!***************************************************************************
+ *! FILE NAME : si5338.c
+ *! FILE NAME : si5338.c
+ *! DESCRIPTION: control of the Silicon Laboratories SI5338 clock generator
+ *! DESCRIPTION: control of the Silicon Laboratories SI5338 clock generator
...
@@ -959,14 +959,17 @@ Index: git/drivers/misc/si5338.c
...
@@ -959,14 +959,17 @@ Index: git/drivers/misc/si5338.c
+#define REG5338_DEV_CONFIG2_VAL 38 /* last 2 digits of part number */
+#define REG5338_DEV_CONFIG2_VAL 38 /* last 2 digits of part number */
+
+
+
+
+#define FVCOMIN 2200000000L
+#define FVCOMIN 2200000000L
L
+#define FVCOMAX 2840000000L
+#define FVCOMAX 2840000000L
L
+#define INFREQMIN 5000000LL
+#define INFREQMIN 5000000LL
+#define INFREQMAX 710000000LL
+#define INFREQMAX 710000000LL
+
+#define MSINT_MIN 8 /* not considering 4,6 */
+#define MSINT_MAX 567
+
+
+#define AWE_IN_MUX 0x1d18
+#define AWE_IN_MUX 0x1d18
+#define AWE_IN_MUX1 0x1c1c
+#define AWE_IN_MUX1 0x1c1c
+#define AWE_FB_MUX 0x1e18
+#define AWE_FB_MUX1 0x1c20
+
+
+#define AWE_XTAL_FREQ 0x1c03
+#define AWE_XTAL_FREQ 0x1c03
+#define AWE_PFD_REF 0x1de0
+#define AWE_PFD_REF 0x1de0
...
@@ -974,6 +977,100 @@ Index: git/drivers/misc/si5338.c
...
@@ -974,6 +977,100 @@ Index: git/drivers/misc/si5338.c
+#define AWE_P1DIV 0x1d07
+#define AWE_P1DIV 0x1d07
+#define AWE_P2DIV 0x1e07
+#define AWE_P2DIV 0x1e07
+
+
+#define AWE_FCAL_OVRD_07_00 0x2dff
+#define AWE_FCAL_OVRD_15_08 0x2eff
+#define AWE_FCAL_OVRD_17_15 0x2f03
+#define AWE_PFD_EXTFB 0x3080
+#define AWE_PLL_KPHI 0x307f
+#define AWE_FCAL_OVRD_EN 0x3180
+#define AWE_VCO_GAIN 0x3170
+#define AWE_RSEL 0x310c
+#define AWE_BWSEL 0x3103
+#define AWE_PLL_EN 0x32c0
+#define AWE_MSCAL 0x323f
+#define AWE_MS3_HS 0x3380
+#define AWE_MS2_HS 0x3340
+#define AWE_MS1_HS 0x3320
+#define AWE_MS0_HS 0x3310
+#define AWE_MS_PEC 0x3307
+
+#define AWE_MS0_FIDCT 0x3460
+#define AWE_MS0_FIDDIS 0x3410
+#define AWE_MS0_SSMODE 0x340C
+#define AWE_MS0_PHIDCT 0x3403
+#define AWE_MS0_P1_07_00 0x35ff
+#define AWE_MS0_P1_15_08 0x36ff
+#define AWE_MS0_P1_17_16 0x3703
+#define AWE_MS0_P2_05_00 0x37fc
+#define AWE_MS0_P2_13_06 0x38ff
+#define AWE_MS0_P2_21_14 0x39ff
+#define AWE_MS0_P2_29_22 0x3aff
+#define AWE_MS0_P3_07_00 0x3bff
+#define AWE_MS0_P3_15_08 0x3cff
+#define AWE_MS0_P3_23_16 0x3dff
+#define AWE_MS0_P3_29_24 0x3e3f
+
+
+#define AWE_MS1_FIDCT 0x3f60
+#define AWE_MS1_FIDDIS 0x3f10
+#define AWE_MS1_SSMODE 0x3f0C
+#define AWE_MS1_PHIDCT 0x3f03
+#define AWE_MS1_P1_07_00 0x40ff
+#define AWE_MS1_P1_15_08 0x41ff
+#define AWE_MS1_P1_17_16 0x4203
+#define AWE_MS1_P2_05_00 0x42fc
+#define AWE_MS1_P2_13_06 0x43ff
+#define AWE_MS1_P2_21_14 0x44ff
+#define AWE_MS1_P2_29_22 0x45ff
+#define AWE_MS1_P3_07_00 0x46ff
+#define AWE_MS1_P3_15_08 0x47ff
+#define AWE_MS1_P3_23_16 0x48ff
+#define AWE_MS1_P3_29_24 0x493f
+
+#define AWE_MS2_FRCTL 0x4a60 /* different name? */
+#define AWE_MS2_FIDDIS 0x4a10
+#define AWE_MS2_SSMODE 0x4a0C
+#define AWE_MS2_PHIDCT 0x4a03
+#define AWE_MS2_P1_07_00 0x4bff
+#define AWE_MS2_P1_15_08 0x4cff
+#define AWE_MS2_P1_17_16 0x4d03
+#define AWE_MS2_P2_05_00 0x4dfc
+#define AWE_MS2_P2_13_06 0x4eff
+#define AWE_MS2_P2_21_14 0x4fff
+#define AWE_MS2_P2_29_22 0x50ff
+#define AWE_MS2_P3_07_00 0x51ff
+#define AWE_MS2_P3_15_08 0x52ff
+#define AWE_MS2_P3_23_16 0x53ff
+#define AWE_MS2_P3_29_24 0x543f
+
+#define AWE_MS3_FIDCT 0x5560
+#define AWE_MS3_FIDDIS 0x5510
+#define AWE_MS3_SSMODE 0x550C
+#define AWE_MS3_PHIDCT 0x5503
+#define AWE_MS3_P1_07_00 0x56ff
+#define AWE_MS3_P1_15_08 0x57ff
+#define AWE_MS3_P1_17_16 0x5803
+#define AWE_MS3_P2_05_00 0x58fc
+#define AWE_MS3_P2_13_06 0x59ff
+#define AWE_MS3_P2_21_14 0x5aff
+#define AWE_MS3_P2_29_22 0x5bff
+#define AWE_MS3_P3_07_00 0x5cff
+#define AWE_MS3_P3_15_08 0x5dff
+#define AWE_MS3_P3_23_16 0x5eff
+#define AWE_MS3_P3_29_24 0x5f3f
+
+#define AWE_MSN_P1_07_00 0x61ff
+#define AWE_MSN_P1_15_08 0x62ff
+#define AWE_MSN_P1_17_16 0x6303
+#define AWE_MSN_P2_05_00 0x63fc
+#define AWE_MSN_P2_13_06 0x64ff
+#define AWE_MSN_P2_21_14 0x65ff
+#define AWE_MSN_P2_29_22 0x66ff
+#define AWE_MSN_P3_07_00 0x67ff
+#define AWE_MSN_P3_15_08 0x68ff
+#define AWE_MSN_P3_23_16 0x69ff
+#define AWE_MSN_P3_29_24 0x6a3f
+
+
+
+static void si5338_init_of(struct i2c_client *client);
+static void si5338_init_of(struct i2c_client *client);
+
+
...
@@ -1004,6 +1101,9 @@ Index: git/drivers/misc/si5338.c
...
@@ -1004,6 +1101,9 @@ Index: git/drivers/misc/si5338.c
+static ssize_t in_mux_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t in_mux_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t in_mux_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t in_mux_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t in_mux_txt_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t in_mux_txt_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t fb_mux_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t fb_mux_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t fb_mux_txt_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t in_pfd_ref_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t in_pfd_ref_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t in_pfd_ref_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t in_pfd_ref_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t in_pfd_ref_txt_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t in_pfd_ref_txt_show (struct device *dev, struct device_attribute *attr, char *buf);
...
@@ -1012,13 +1112,53 @@ Index: git/drivers/misc/si5338.c
...
@@ -1012,13 +1112,53 @@ Index: git/drivers/misc/si5338.c
+static ssize_t in_pfd_fb_txt_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t in_pfd_fb_txt_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t pll_ref_frequency_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t pll_ref_frequency_show (struct device *dev, struct device_attribute *attr, char *buf);
+
+
+static ssize_t _msx_p123_show(struct device *dev, struct device_attribute *attr, char *buf, int chn);
+static ssize_t _msx_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, int chn);
+static ssize_t _msx_abc_show(struct device *dev, struct device_attribute *attr, char *buf, int chn);
+static ssize_t _msx_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, int chn);
+static ssize_t ms0_p123_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms0_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t ms0_abc_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms0_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t ms1_p123_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms1_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t ms1_abc_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms1_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t ms2_p123_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms2_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t ms2_abc_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms2_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t ms3_p123_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms3_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t ms3_abc_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms3_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t msn_p123_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t msn_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t msn_abc_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t msn_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t pll_freq_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t _pll_freq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count,int int_div, int by_out);
+static ssize_t pll_freq_fract_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t pll_freq_int_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t pll_by_out_fract_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t pll_by_out_int_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+
+
+
+
+/* -------------------------------------- */
+/* -------------------------------------- */
+static int ms_to_p123(u64* ms,u32 * p123);
+static int p123_to_ms(u64* ms,u32 * p123);
+static int get_ms_p123(struct i2c_client *client,u32 * p123, int chn); /* chn 0,1,2,3,4 (4 - msn) */
+static int set_ms_p123(struct i2c_client *client,u32 * p123, int chn); /* chn 0,1,2,3,4 (4 - msn) */
+static int set_pll_freq(struct i2c_client *client, u64 *vco_freq, int int_div);
+static int get_pll_freq(struct i2c_client *client,u64 * pll_freq);
+static int set_pll_freq_by_out(struct i2c_client *client, u64 *out_freq, int int_msn_div);
+
+
+
+static s64 get_pll_in_frequency(struct i2c_client *client);
+static s64 get_pll_in_frequency(struct i2c_client *client);
+static int set_in_mux(struct i2c_client *client, int data);
+static int set_in_mux(struct i2c_client *client, int data);
+static int get_in_mux(struct i2c_client *client);
+static int get_in_mux(struct i2c_client *client);
+static int set_fb_mux(struct i2c_client *client, int data);
+static int get_fb_mux(struct i2c_client *client);
+static int set_in_pdiv(struct i2c_client *client, int div, int chn); /*chn =0,1 */
+static int set_in_pdiv(struct i2c_client *client, int div, int chn); /*chn =0,1 */
+static int get_in_pdiv(struct i2c_client *client, int chn); /*chn =0,1 */
+static int get_in_pdiv(struct i2c_client *client, int chn); /*chn =0,1 */
+static int set_in_pfd_ref_fb(struct i2c_client *client, u8 val, int chn); /*chn =0 - ref, 1 - fb*/
+static int set_in_pfd_ref_fb(struct i2c_client *client, u8 val, int chn); /*chn =0 - ref, 1 - fb*/
...
@@ -1027,8 +1167,8 @@ Index: git/drivers/misc/si5338.c
...
@@ -1027,8 +1167,8 @@ Index: git/drivers/misc/si5338.c
+static u64 get_in_frequency(struct i2c_client *client);
+static u64 get_in_frequency(struct i2c_client *client);
+
+
+
+
+static s64 read_multireg64 (struct i2c_client *client,
int awel,
u32 * awe);
+static s64 read_multireg64 (struct i2c_client *client, u32 * awe);
+static int write_multireg64 (struct i2c_client *client, u64 data,
int awel,
u32 * awe);
+static int write_multireg64 (struct i2c_client *client, u64 data, u32 * awe);
+static int read_field (struct i2c_client *client, u32 awe);
+static int read_field (struct i2c_client *client, u32 awe);
+static int write_field (struct i2c_client *client, u8 data, u32 awe);
+static int write_field (struct i2c_client *client, u8 data, u32 awe);
+static int write_adwe(struct i2c_client *client, u32 adwe);
+static int write_adwe(struct i2c_client *client, u32 adwe);
...
@@ -1062,12 +1202,13 @@ Index: git/drivers/misc/si5338.c
...
@@ -1062,12 +1202,13 @@ Index: git/drivers/misc/si5338.c
+
+
+//static DEVICE_ATTR(xtal_freq, SYSFS_PERMISSIONS, input_xtal_freq_show, input_xtal_freq_store);
+//static DEVICE_ATTR(xtal_freq, SYSFS_PERMISSIONS, input_xtal_freq_show, input_xtal_freq_store);
+static DEVICE_ATTR(xtal_freq_txt, SYSFS_PERMISSIONS & SYSFS_READONLY, input_xtal_freq_txt_show, NULL);
+static DEVICE_ATTR(xtal_freq_txt, SYSFS_PERMISSIONS & SYSFS_READONLY, input_xtal_freq_txt_show, NULL);
+
+static DEVICE_ATTR(in_frequency, SYSFS_PERMISSIONS, in_frequency_show, in_frequency_store);
+static DEVICE_ATTR(in_frequency, SYSFS_PERMISSIONS, in_frequency_show, in_frequency_store);
+static DEVICE_ATTR(in_p1_div, SYSFS_PERMISSIONS, in_p1_div_show, in_p1_div_store);
+static DEVICE_ATTR(in_p1_div, SYSFS_PERMISSIONS, in_p1_div_show, in_p1_div_store);
+static DEVICE_ATTR(in_p2_div, SYSFS_PERMISSIONS, in_p2_div_show, in_p2_div_store);
+static DEVICE_ATTR(in_p2_div, SYSFS_PERMISSIONS, in_p2_div_show, in_p2_div_store);
+static DEVICE_ATTR(in_mux, SYSFS_PERMISSIONS, in_mux_show, in_mux_store);
+static DEVICE_ATTR(in_mux, SYSFS_PERMISSIONS, in_mux_show, in_mux_store);
+static DEVICE_ATTR(in_mux_txt, SYSFS_PERMISSIONS & SYSFS_READONLY, in_mux_txt_show, NULL);
+static DEVICE_ATTR(in_mux_txt, SYSFS_PERMISSIONS & SYSFS_READONLY, in_mux_txt_show, NULL);
+static DEVICE_ATTR(fb_mux, SYSFS_PERMISSIONS, fb_mux_show, fb_mux_store);
+static DEVICE_ATTR(fb_mux_txt, SYSFS_PERMISSIONS & SYSFS_READONLY, fb_mux_txt_show, NULL);
+static DEVICE_ATTR(in_pfd_ref, SYSFS_PERMISSIONS, in_pfd_ref_show, in_pfd_ref_store);
+static DEVICE_ATTR(in_pfd_ref, SYSFS_PERMISSIONS, in_pfd_ref_show, in_pfd_ref_store);
+static DEVICE_ATTR(in_pfd_ref_txt, SYSFS_PERMISSIONS & SYSFS_READONLY, in_pfd_ref_txt_show, NULL);
+static DEVICE_ATTR(in_pfd_ref_txt, SYSFS_PERMISSIONS & SYSFS_READONLY, in_pfd_ref_txt_show, NULL);
+static DEVICE_ATTR(in_pfd_fb, SYSFS_PERMISSIONS, in_pfd_fb_show, in_pfd_fb_store);
+static DEVICE_ATTR(in_pfd_fb, SYSFS_PERMISSIONS, in_pfd_fb_show, in_pfd_fb_store);
...
@@ -1083,6 +1224,8 @@ Index: git/drivers/misc/si5338.c
...
@@ -1083,6 +1224,8 @@ Index: git/drivers/misc/si5338.c
+ &dev_attr_in_p2_div.attr,
+ &dev_attr_in_p2_div.attr,
+ &dev_attr_in_mux.attr,
+ &dev_attr_in_mux.attr,
+ &dev_attr_in_mux_txt.attr,
+ &dev_attr_in_mux_txt.attr,
+ &dev_attr_fb_mux.attr,
+ &dev_attr_fb_mux_txt.attr,
+ &dev_attr_in_pfd_ref.attr,
+ &dev_attr_in_pfd_ref.attr,
+ &dev_attr_in_pfd_ref_txt.attr,
+ &dev_attr_in_pfd_ref_txt.attr,
+ &dev_attr_in_pfd_fb.attr,
+ &dev_attr_in_pfd_fb.attr,
...
@@ -1096,14 +1239,60 @@ Index: git/drivers/misc/si5338.c
...
@@ -1096,14 +1239,60 @@ Index: git/drivers/misc/si5338.c
+ .name = "input",
+ .name = "input",
+};
+};
+
+
+static DEVICE_ATTR(ms0_p123, SYSFS_PERMISSIONS, ms0_p123_show, ms0_p123_store);
+static DEVICE_ATTR(ms0_abc, SYSFS_PERMISSIONS, ms0_abc_show, ms0_abc_store);
+static DEVICE_ATTR(ms1_p123, SYSFS_PERMISSIONS, ms1_p123_show, ms1_p123_store);
+static DEVICE_ATTR(ms1_abc, SYSFS_PERMISSIONS, ms1_abc_show, ms1_abc_store);
+static DEVICE_ATTR(ms2_p123, SYSFS_PERMISSIONS, ms2_p123_show, ms2_p123_store);
+static DEVICE_ATTR(ms2_abc, SYSFS_PERMISSIONS, ms2_abc_show, ms2_abc_store);
+static DEVICE_ATTR(ms3_p123, SYSFS_PERMISSIONS, ms3_p123_show, ms3_p123_store);
+static DEVICE_ATTR(ms3_abc, SYSFS_PERMISSIONS, ms3_abc_show, ms3_abc_store);
+static DEVICE_ATTR(msn_p123, SYSFS_PERMISSIONS, msn_p123_show, msn_p123_store);
+static DEVICE_ATTR(msn_abc, SYSFS_PERMISSIONS, msn_abc_show, msn_abc_store);
+
+static struct attribute *multisynth_attrs[] = {
+ &dev_attr_ms0_p123.attr,
+ &dev_attr_ms0_abc.attr,
+ &dev_attr_ms1_p123.attr,
+ &dev_attr_ms1_abc.attr,
+ &dev_attr_ms2_p123.attr,
+ &dev_attr_ms2_abc.attr,
+ &dev_attr_ms3_p123.attr,
+ &dev_attr_ms3_abc.attr,
+ &dev_attr_msn_p123.attr,
+ &dev_attr_msn_abc.attr,
+ NULL
+};
+static const struct attribute_group dev_attr_multisynth_group = {
+ .attrs = multisynth_attrs,
+ .name = "multiSynth",
+};
+static DEVICE_ATTR(pll_freq_fract, SYSFS_PERMISSIONS, pll_freq_show, pll_freq_fract_store);
+static DEVICE_ATTR(pll_freq_int, SYSFS_PERMISSIONS, pll_freq_show, pll_freq_int_store);
+static DEVICE_ATTR(pll_by_out_fract,SYSFS_PERMISSIONS, pll_freq_show, pll_by_out_fract_store);
+static DEVICE_ATTR(pll_by_out_int, SYSFS_PERMISSIONS, pll_freq_show, pll_by_out_int_store);
+
+
+
+static struct attribute *pll_dev_attrs[] = {
+ &dev_attr_pll_ref_frequency.attr,
+ &dev_attr_pll_freq_fract.attr,
+ &dev_attr_pll_freq_int.attr,
+ &dev_attr_pll_by_out_fract.attr,
+ &dev_attr_pll_by_out_int.attr,
+ NULL
+};
+
+
+static const struct attribute_group dev_attr_pll_group = {
+ .attrs = pll_dev_attrs,
+ .name = "pll",
+};
+
+
+static const struct i2c_device_id si5338_id[] = {
+static const struct i2c_device_id si5338_id[] = {
+ { "si5338", 0 },
+ { "si5338", 0 },
+ { }
+ { }
+};
+};
+
+
+
+struct si5338_data_t {
+struct si5338_data_t {
+ u64 input_frequency;
+ u64 input_frequency;
+ u64 pll_frequency;
+ u64 pll_frequency;
...
@@ -1121,6 +1310,8 @@ Index: git/drivers/misc/si5338.c
...
@@ -1121,6 +1310,8 @@ Index: git/drivers/misc/si5338.c
+ if (&dev->kobj) {
+ if (&dev->kobj) {
+ if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_raw_group)))<0) return retval;
+ if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_raw_group)))<0) return retval;
+ if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_input_group)))<0) return retval;
+ if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_input_group)))<0) return retval;
+ if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_multisynth_group)))<0) return retval;
+ if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_pll_group)))<0) return retval;
+ }
+ }
+ return retval;
+ return retval;
+}
+}
...
@@ -1347,6 +1538,30 @@ Index: git/drivers/misc/si5338.c
...
@@ -1347,6 +1538,30 @@ Index: git/drivers/misc/si5338.c
+ if (((data=get_in_mux(client)))<0) return data;
+ if (((data=get_in_mux(client)))<0) return data;
+ return sprintf(buf, "%s\n",mux_txt[data]);
+ return sprintf(buf, "%s\n",mux_txt[data]);
+}
+}
+static ssize_t fb_mux_show (struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int data;
+ struct i2c_client *client = to_i2c_client(dev);
+ if (((data=get_fb_mux(client)))<0) return data;
+ return sprintf(buf, "%d\n",data);
+}
+static ssize_t fb_mux_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int data,rc;
+ sscanf(buf, "%d", &data);
+ if (((rc=set_fb_mux(client, data)))<0) return rc;
+ return count;
+}
+static ssize_t fb_mux_txt_show (struct device *dev, struct device_attribute *attr, char *buf)
+{
+ const char *mux_fb_txt[]={"IN5/IN6(diff)","IN4(single ended)","No clock"};
+ int data;
+ struct i2c_client *client = to_i2c_client(dev);
+ if (((data=get_fb_mux(client)))<0) return data;
+ return sprintf(buf, "%s\n",mux_fb_txt[data]);
+}
+
+static ssize_t in_pfd_ref_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t in_pfd_ref_show (struct device *dev, struct device_attribute *attr, char *buf)
+{
+{
+ int data;
+ int data;
...
@@ -1402,10 +1617,407 @@ Index: git/drivers/misc/si5338.c
...
@@ -1402,10 +1617,407 @@ Index: git/drivers/misc/si5338.c
+ if (pll_in_freq<0) return (int) pll_in_freq;
+ if (pll_in_freq<0) return (int) pll_in_freq;
+ return sprintf(buf, "%lld\n",pll_in_freq);
+ return sprintf(buf, "%lld\n",pll_in_freq);
+}
+}
+static ssize_t _msx_p123_show(struct device *dev, struct device_attribute *attr, char *buf, int chn)
+{
+ int rc;
+ u32 p123[3];
+ struct i2c_client *client = to_i2c_client(dev);
+ if (((rc=get_ms_p123(client,p123, chn)))<0) return rc;
+// return sprintf(buf, "%ld %ld %ld\n",p123[0],p123[1],p123[2]);
+ return sprintf(buf, "%u %u %u\n",p123[0],p123[1],p123[2]);
+}
+static ssize_t _msx_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count,int chn)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int rc;
+ u32 p123[3];
+ int num_items;
+// num_items=sscanf(buf, "%ld %ld %ld", &p123[0], &p123[1], &p123[2]);
+ num_items=sscanf(buf, "%u %u %u", &p123[0], &p123[1], &p123[2]);
+ if (num_items<3){
+ p123[1]=0;
+ p123[2]=1;
+ }
+ if (((rc=set_ms_p123(client,p123, chn)))<0) return rc;
+ return count;
+}
+static ssize_t _msx_abc_show(struct device *dev, struct device_attribute *attr, char *buf, int chn)
+{
+ int rc;
+ u32 p123[3];
+ u64 ms[3];
+ struct i2c_client *client = to_i2c_client(dev);
+ if (((rc=get_ms_p123(client,p123, chn)))<0) return rc;
+ p123_to_ms(ms,p123);
+ return sprintf(buf, "%lld %lld %lld\n",ms[0],ms[1],ms[2]);
+}
+static ssize_t _msx_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count,int chn)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int rc;
+ u32 p123[3];
+ u64 ms[3];
+ int num_items;
+ num_items=sscanf(buf, "%lld %lld %lld", &ms[0], &ms[1], &ms[2]);
+ if (num_items<3){
+ ms[1]=0;
+ ms[2]=1;
+ }
+ ms_to_p123(ms,p123);
+ if (((rc=set_ms_p123(client,p123, chn)))<0) return rc;
+ return count;
+}
+static ssize_t ms0_p123_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_p123_show(dev, attr, buf, 0);}
+static ssize_t ms0_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_p123_store(dev, attr, buf, count,0);}
+static ssize_t ms0_abc_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_abc_show(dev, attr, buf, 0);}
+static ssize_t ms0_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_abc_store(dev, attr, buf, count,0);}
+
+static ssize_t ms1_p123_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_p123_show(dev, attr, buf, 1);}
+static ssize_t ms1_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_p123_store(dev, attr, buf, count,1);}
+static ssize_t ms1_abc_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_abc_show(dev, attr, buf, 1);}
+static ssize_t ms1_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_abc_store(dev, attr, buf, count,1);}
+
+static ssize_t ms2_p123_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_p123_show(dev, attr, buf, 2);}
+static ssize_t ms2_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_p123_store(dev, attr, buf, count,2);}
+static ssize_t ms2_abc_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_abc_show(dev, attr, buf, 2);}
+static ssize_t ms2_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_abc_store(dev, attr, buf, count,2);}
+
+static ssize_t ms3_p123_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_p123_show(dev, attr, buf, 3);}
+static ssize_t ms3_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_p123_store(dev, attr, buf, count,3);}
+static ssize_t ms3_abc_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_abc_show(dev, attr, buf, 3);}
+static ssize_t ms3_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_abc_store(dev, attr, buf, count,3);}
+
+static ssize_t msn_p123_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_p123_show(dev, attr, buf, 4);}
+static ssize_t msn_p123_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_p123_store(dev, attr, buf, count,4);}
+static ssize_t msn_abc_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {return _msx_abc_show(dev, attr, buf, 4);}
+static ssize_t msn_abc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _msx_abc_store(dev, attr, buf, count,4);}
+static ssize_t pll_freq_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u64 pll_freq[3];
+ struct i2c_client *client = to_i2c_client(dev);
+
+
+ if (((rc=get_pll_freq(client,pll_freq)))<0) return rc;
+ return sprintf(buf, "%lld %lld %lld\n",pll_freq[0],pll_freq[1],pll_freq[2]);
+}
+
+
+static ssize_t _pll_freq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count,int int_div, int by_out)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int rc;
+ u64 freq[3];
+ int num_items;
+ num_items=sscanf(buf, "%lld %lld %lld", &freq[0], &freq[1], &freq[2]);
+ if (num_items<3){
+ freq[1]=0;
+ freq[2]=1;
+ }
+ if (by_out) {
+ if (((rc=set_pll_freq_by_out(client, freq, int_div)))<0) return rc;
+ } else {
+ if (((rc=set_pll_freq (client, freq, int_div)))<0) return rc;
+ }
+ return count;
+}
+static ssize_t pll_freq_fract_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _pll_freq_store(dev, attr, buf, count, 0, 0);}
+static ssize_t pll_freq_int_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _pll_freq_store(dev, attr, buf, count, 1, 0);}
+static ssize_t pll_by_out_fract_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _pll_freq_store(dev, attr, buf, count, 0, 1);}
+static ssize_t pll_by_out_int_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {return _pll_freq_store(dev, attr, buf, count, 1, 1);}
+
+
+/* -------------------------------------- */
+
+
+/* -----------PLL section--------------------------- */
+/* Setting PLL frequency in 3 ways:
+ * 1 - specified directly, allow fractional MSN
+ * 2 - specified directly, integer MSN
+ * 3 - specified by output frequency, integer MSN
+ */
+static u32 awe_msx[5][3][5]=
+ {{{AWE_MS0_P1_07_00, AWE_MS0_P1_15_08, AWE_MS0_P1_17_16, 0, 0},
+ {AWE_MS0_P2_05_00, AWE_MS0_P2_13_06, AWE_MS0_P2_21_14, AWE_MS0_P2_29_22, 0},
+ {AWE_MS0_P3_07_00, AWE_MS0_P3_15_08, AWE_MS0_P3_23_16, AWE_MS0_P3_29_24, 0}},
+ {{AWE_MS1_P1_07_00, AWE_MS1_P1_15_08, AWE_MS1_P1_17_16, 0, 0},
+ {AWE_MS1_P2_05_00, AWE_MS1_P2_13_06, AWE_MS1_P2_21_14, AWE_MS1_P2_29_22, 0},
+ {AWE_MS1_P3_07_00, AWE_MS1_P3_15_08, AWE_MS1_P3_23_16, AWE_MS1_P3_29_24, 0}},
+ {{AWE_MS2_P1_07_00, AWE_MS2_P1_15_08, AWE_MS2_P1_17_16, 0, 0},
+ {AWE_MS2_P2_05_00, AWE_MS2_P2_13_06, AWE_MS2_P2_21_14, AWE_MS2_P2_29_22, 0},
+ {AWE_MS2_P3_07_00, AWE_MS2_P3_15_08, AWE_MS2_P3_23_16, AWE_MS2_P3_29_24, 0}},
+ {{AWE_MS3_P1_07_00, AWE_MS3_P1_15_08, AWE_MS3_P1_17_16, 0, 0},
+ {AWE_MS3_P2_05_00, AWE_MS3_P2_13_06, AWE_MS3_P2_21_14, AWE_MS3_P2_29_22, 0},
+ {AWE_MS3_P3_07_00, AWE_MS3_P3_15_08, AWE_MS3_P3_23_16, AWE_MS3_P3_29_24, 0}},
+ {{AWE_MSN_P1_07_00, AWE_MSN_P1_15_08, AWE_MSN_P1_17_16, 0, 0},
+ {AWE_MSN_P2_05_00, AWE_MSN_P2_13_06, AWE_MSN_P2_21_14, AWE_MSN_P2_29_22, 0},
+ {AWE_MSN_P3_07_00, AWE_MSN_P3_15_08, AWE_MSN_P3_23_16, AWE_MSN_P3_29_24, 0}}};
+
+static int ms_to_p123(u64* ms,u32 * p123)
+{
+ /*
+ * a=ms[0],b=ms[1],c=ms[2] ms~=a+b/c
+ * p1=floor(((a*c+b)*128)/c -512)
+ * p2=mod((b*128),c)
+ * p3=c
+ */
+ u64 d;
+ u64 ms_denom=ms[2], ms_nom=ms[1], ms_int=ms[0];
+ while (ms_denom >= (1<<30)) { /* will not happen with current frequency values specified in integer Hz */
+ ms_denom >>= 1;
+ ms_nom >>= 1;
+ }
+ if ((ms_nom==0) || (ms_denom==0)){
+ ms_denom = 1;
+ ms_nom = 0;
+ }
+ d= (ms_int * ms_denom + ms_nom)<<7;
+ p123[0]= (u32) (div64_u64(d,ms_denom) -512);
+ d=div64_u64((ms_nom<<7),ms_denom);
+ p123[1]= (u32) ((ms_nom<<7)-d*ms_denom);
+ p123[2]=ms_denom;
+ return 0;
+}
+static int p123_to_ms(u64* ms,u32 * p123)
+{
+ /* a=ms[0],b=ms[1],c=ms[2] ms~=a+b/c
+ * p1=floor(((a*c+b)*128)/c -512)
+ * p2=mod((b*128),c)
+ * p3=c
+ * ---
+ * b*128=k*c +p2; k<128, p2<c
+ * p1=floor(((a*c+b)*128)/c -512)=a*128 + floor((b*128)/c) -512 = a*128+ k -512
+ * k=mod (p1,128) =p1 & 0x7f
+ * c= p3
+ * b= (k*c + p2)/128= ((p1 & 0x7f)*p3 + p2) >>7
+ * a= (p1+512)>>7=(p1>>7)+4
+ *
+ */
+ ms[2]=p123[2]; /* c= p3 */
+ ms[1]=(ms[2]*(p123[0] & 0x7f) + p123[1]) >>7; /* b= (c*(p1 & 0x7f) + p2) >>7 */
+ ms[0]=(p123[0]>>7)+4; /* a= (p1>>7)+4 */
+ return 0;
+}
+
+
+static int get_ms_p123(struct i2c_client *client,u32 * p123, int chn) /* chn 0,1,2,3,4 (4 - msn) */
+{
+ int i;
+ s64 rc;
+ for (i=0;i<3;i++){
+ if (((rc=read_multireg64 (client, awe_msx[chn][i])))<0) return (int) rc;
+ p123[i]= (u32) rc;
+ }
+ return 0;
+}
+static int set_ms_p123(struct i2c_client *client,u32 * p123, int chn) /* chn 0,1,2,3,4 (4 - msn) */
+{
+ int i,rc;
+ for (i=0;i<3;i++){
+ if (((rc=write_multireg64(client, (u64) p123[i], awe_msx[chn][i])))<0) return rc;
+ }
+ return 0;
+}
+
+static int set_pll_freq(struct i2c_client *client, u64 *vco_freq, int int_div)
+{
+ s64 pll_in_freq, pll_in_freq_scaled,pll_out_freq_scaled,d;
+ u32 msn_p123[3];
+ u64 msn[]={0,0,1};
+ s64 vco_int=vco_freq[0],vco_nom=vco_freq[1],vco_denom=vco_freq[2];
+ if ((vco_nom==0) || (vco_denom==0)){
+ vco_nom=0;
+ vco_denom=1;
+ }
+ if (vco_nom>=vco_denom){ /* normalize */
+ d=div64_u64(vco_nom,vco_denom);
+ vco_int+=d;
+ vco_nom-=d*vco_denom;
+ }
+ if (vco_int < FVCOMIN){
+ dev_err(&client->dev, "Specified PLL frequency is too low: %llu < %llu\n",vco_int, FVCOMIN);
+ return - EINVAL;
+ }
+ if (vco_int > FVCOMAX){
+ dev_err(&client->dev, "Specified PLL frequency is too high: %llu > %llu\n",vco_int, FVCOMAX);
+ return - EINVAL;
+ }
+
+ pll_in_freq=get_pll_in_frequency(client);
+ if (pll_in_freq<0) return (int) pll_in_freq;
+ pll_in_freq_scaled=pll_in_freq*vco_denom;
+// pll_out_freq_scaled=pll_out_freq*vco_denom;
+ pll_out_freq_scaled=vco_int*vco_denom+vco_nom;
+ msn[0]=div64_u64(pll_out_freq_scaled,pll_in_freq_scaled);
+ msn[1]=pll_out_freq_scaled-pll_in_freq_scaled*msn[0];
+ msn[2]=pll_in_freq_scaled;
+ while (msn[2] >= (1<<30)) { /* trim */
+ msn[2] >>= 1;
+ msn[1] >>= 1;
+ }
+
+ if (msn[0] < MSINT_MIN){
+ dev_err(&client->dev, "Calculated MSN ratio is too low: %llu < %u\n",msn[0], MSINT_MIN);
+ return - EINVAL;
+ }
+ if (msn[0] > MSINT_MAX){
+ dev_err(&client->dev, "Calculated MSN ratio is too high: %llu > %u\n",msn[0], MSINT_MAX);
+ return - EINVAL;
+ }
+ if (int_div){
+ if (msn[1]>=(msn[2]>>1)) msn[0]++; // round
+ msn[1] = 0;
+ msn[2] = 1;
+ }
+ ms_to_p123(msn, msn_p123);
+ return set_ms_p123(client,msn_p123, 4); // MSN
+}
+
+static int get_pll_freq(struct i2c_client *client,u64 * pll_freq)
+{
+ int rc;
+ s64 pll_in_freq;
+ u32 p123[3];
+ s64 d;
+ pll_in_freq=get_pll_in_frequency(client);
+ if (pll_in_freq<=0) return (int) pll_in_freq;
+ if (((rc=get_ms_p123(client,p123,4)))<0) return rc; /* channel4 - MSN */
+ p123_to_ms(pll_freq,p123);
+ if (pll_freq[2]<=0) return -EINVAL; /* 0 denominator */
+ pll_freq[0]*=pll_in_freq;
+ pll_freq[1]*=pll_in_freq;
+ if (pll_freq[1]>=pll_freq[0]){ /* normalize */
+ d=div64_u64(pll_freq[1],pll_freq[2]);
+ pll_freq[0]+=d;
+ pll_freq[1]-=d*pll_freq[2];
+ }
+ return 0;
+}
+
+
+
+/*
+ * Calculate pll output frequency to match specified output frequency
+ * out_freq as int,nom,denom
+ */
+static int set_pll_freq_by_out(struct i2c_client *client, u64 *out_freq, int int_msn_div)
+{
+ /* use r-divider if the output frequency is too low (less than 5 MHz) */
+ u64 out_int=out_freq[0],out_nom=out_freq[1],out_denom=out_freq[2],
+ pll_out_freq[3], scaled_max,scaled_min;
+ s64 pll_freq_scaled, out_freq_scaled,err,best_err=-1,out_div,pll_in_freq,in_div,best_in_div,
+ pll_in_freq_scaled,synth_out_scaled;
+ int r_div=1;
+ if (out_denom<out_nom){
+ dev_err(&client->dev, "Nominator (%lld) should be less than denominator (%lld)\n",
+ out_nom,out_denom);
+ return -EINVAL;
+ }
+ if (out_int<(FVCOMAX/MSINT_MAX)){
+ while ((r_div < 32) && (out_int<(FVCOMAX/MSINT_MAX))){
+ out_int<<=1;
+ out_nom<<=1;
+ r_div<<=1;
+ if (out_nom>out_denom) {
+ out_int++;
+ out_nom-=out_denom;
+ }
+
+ }
+ if (out_int<(FVCOMAX/MSINT_MAX)){
+ dev_err(&client->dev, "Specified output frequency is too low: %lld < %lld\n",
+ out_freq[0], FVCOMAX/MSINT_MAX/32);
+ return -EINVAL;
+ }
+ }
+ dev_dbg(&client->dev, "Output divider by %u, Output frequency before divider: %llu+%llu/%llu Hz\n",
+ r_div,out_int, out_nom,out_denom);
+
+ out_freq_scaled=out_int*out_denom+out_nom;
+ scaled_max=FVCOMAX*out_denom;
+ scaled_min=FVCOMIN*out_denom;
+ if (int_msn_div==0){
+ out_div=div64_u64( (FVCOMAX+FVCOMIN/2)*out_denom+(out_freq_scaled>>1),out_freq_scaled);
+ if ((out_div==7) || (out_div==5) || (out_div==3)){
+ if (out_freq_scaled*(out_div+1)<scaled_max){
+ out_div++;
+ } else if ((out_div>4) && (out_freq_scaled*(out_div-1)>scaled_min)){
+ out_div--;
+ } else {
+ out_div=0;
+ }
+ }
+ if ((out_div<4) || (out_div > MSINT_MAX) ||
+ (out_freq_scaled*out_div < scaled_min) ||
+ (out_freq_scaled*out_div > scaled_max)){
+ dev_err(&client->dev, "Can not find suitable divisor for output frequency %lld+%lld/%lld Hz\n",
+ out_int, out_nom,out_denom);
+ return -EINVAL;
+ }
+// pll_out_freq=div64_u64(out_freq_scaled*out_div+(out_denom>>1),out_denom);
+ pll_out_freq[0]=div64_u64(out_freq_scaled*out_div,out_denom);
+ pll_out_freq[1]=(out_freq_scaled*out_div)-pll_out_freq[0]*out_denom;
+ pll_out_freq[2]=out_denom;
+
+ dev_dbg(&client->dev, "PLL output divider by %llu, pll frequency: %llu+%llu/%llu Hz\n",
+ out_div,pll_out_freq[0],pll_out_freq[1],pll_out_freq[2]);
+ return set_pll_freq(client, pll_out_freq, 0);
+ } else { /* if (int_msn_div==0), find the best pair of integer coefficients */
+ pll_in_freq=get_pll_in_frequency(client);
+ pll_in_freq_scaled=pll_in_freq*out_denom;
+ if (pll_in_freq<0) return (int) pll_in_freq;
+ best_in_div=0;
+ for (out_div=4;out_div<=MSINT_MAX;out_div++) if ((out_div!=5) && (out_div!=7)){
+ pll_freq_scaled=out_freq_scaled*out_div; /* here scaled by denominator */
+ if ((pll_freq_scaled>=scaled_min) && (pll_freq_scaled<=scaled_max)) {
+ in_div=div64_u64(pll_freq_scaled+(pll_in_freq_scaled>>1),pll_in_freq_scaled); // round
+ synth_out_scaled=div64_u64(pll_in_freq_scaled*in_div+ (out_div>>1),out_div);
+ err=synth_out_scaled-out_freq_scaled;
+ if (err<0) err=-err;
+ if ((best_in_div==0) || (err < best_err)){
+ best_err=err;
+ best_in_div=in_div;
+ }
+ }
+ }
+ if (best_in_div==0){
+ dev_err(&client->dev, "Failed to find suitable integer coefficients for pll input %lld Hz\n",
+ pll_in_freq);
+
+ }
+// pll_out_freq=div64_u64(pll_in_freq_scaled*best_in_div+(out_denom>>1),out_denom);
+ pll_out_freq[0]=div64_u64(pll_in_freq_scaled*best_in_div,out_denom);
+ pll_out_freq[1]=(pll_in_freq_scaled*best_in_div)-pll_out_freq[0]*out_denom;
+ pll_out_freq[2]=out_denom;
+ dev_dbg(&client->dev, "PLL output frequency: %llu+%llu/%llu Hz, MS input divider: %lld, MS output divider: %lld\n",
+ pll_out_freq[0],pll_out_freq[1],pll_out_freq[2], best_in_div, out_div);
+ return set_pll_freq(client, pll_out_freq, 0); /* integer result */
+ }
+}
+
+
+
+/* ----------- Input section ----------------- */
+
+
+static s64 get_pll_in_frequency(struct i2c_client *client)
+static s64 get_pll_in_frequency(struct i2c_client *client)
+{
+{
...
@@ -1440,6 +2052,30 @@ Index: git/drivers/misc/si5338.c
...
@@ -1440,6 +2052,30 @@ Index: git/drivers/misc/si5338.c
+{
+{
+ return read_field(client,AWE_IN_MUX );
+ return read_field(client,AWE_IN_MUX );
+}
+}
+
+static int set_fb_mux(struct i2c_client *client, int data)
+{
+ int data1,rc;
+ switch (data) {
+ case 0: data1=0; break;
+ case 1: data1=1; break;
+ case 2: data1=0; break;
+ default:
+ dev_err(&client->dev, "Invalid value for feedback multiplexer %d\n",data);
+ return - EINVAL;
+ }
+ if (((rc=write_field (client, data, AWE_FB_MUX )))<0) return rc;
+ if (((rc=write_field (client, data1, AWE_FB_MUX1)))<0) return rc;
+ return 0;
+}
+
+static int get_fb_mux(struct i2c_client *client)
+{
+ return read_field(client,AWE_IN_MUX );
+}
+
+
+
+static const u8 in_div_values[]={1,2,4,8,16,32};
+static const u8 in_div_values[]={1,2,4,8,16,32};
+static int set_in_pdiv(struct i2c_client *client, int div, int chn) /*chn =0,1 */
+static int set_in_pdiv(struct i2c_client *client, int div, int chn) /*chn =0,1 */
+{
+{
...
@@ -1506,15 +2142,15 @@ Index: git/drivers/misc/si5338.c
...
@@ -1506,15 +2142,15 @@ Index: git/drivers/misc/si5338.c
+ return clientdata->input_frequency;
+ return clientdata->input_frequency;
+}
+}
+
+
+/* -----------
----------
----------------- */
+/* -----------
General
----------------- */
+
+
+static s64 read_multireg64 (struct i2c_client *client,
int awel,
u32 * awe)
+static s64 read_multireg64 (struct i2c_client *client, u32 * awe)
+{
+{
+ int i,nshift,nbits, full_shift=0;
+ int i,nshift,nbits, full_shift=0;
+ u8 mask;
+ u8 mask;
+ u16 reg;
+ u16 reg;
+ s64 data=0, rc;
+ s64 data=0, rc;
+ for (i=0;
i<awel
;i++){
+ for (i=0;
awe[i]!=0
;i++){
+ reg=awe[i]>>8;
+ reg=awe[i]>>8;
+ mask=awe[i]&0xff;
+ mask=awe[i]&0xff;
+ if (mask!=0){
+ if (mask!=0){
...
@@ -1534,12 +2170,12 @@ Index: git/drivers/misc/si5338.c
...
@@ -1534,12 +2170,12 @@ Index: git/drivers/misc/si5338.c
+}
+}
+
+
+
+
+static int write_multireg64 (struct i2c_client *client, u64 data,
int awel,
u32 * awe)
+static int write_multireg64 (struct i2c_client *client, u64 data, u32 * awe)
+{
+{
+ int i,rc,nshift,nbits;
+ int i,rc,nshift,nbits;
+ u8 mask,reg_data;
+ u8 mask,reg_data;
+ u16 reg;
+ u16 reg;
+ for (i=0;
i<awel
;i++){
+ for (i=0;
awe[i]!=0
;i++){
+ reg=awe[i]>>8;
+ reg=awe[i]>>8;
+ mask=awe[i]&0xff;
+ mask=awe[i]&0xff;
+ if (mask!=0){
+ if (mask!=0){
...
@@ -1585,6 +2221,7 @@ Index: git/drivers/misc/si5338.c
...
@@ -1585,6 +2221,7 @@ Index: git/drivers/misc/si5338.c
+ reg_data=(data & 0xff) << nshift;
+ reg_data=(data & 0xff) << nshift;
+ if (((rc=write_reg(client, reg, reg_data, mask)))<0) return rc;
+ if (((rc=write_reg(client, reg, reg_data, mask)))<0) return rc;
+ }
+ }
+ return 0;
+}
+}
+
+
+
+
...
@@ -1630,7 +2267,7 @@ Index: git/drivers/misc/si5338.c
...
@@ -1630,7 +2267,7 @@ Index: git/drivers/misc/si5338.c
+ int rc,page;
+ int rc,page;
+ struct si5338_data_t *clientdata = i2c_get_clientdata(client);
+ struct si5338_data_t *clientdata = i2c_get_clientdata(client);
+ page=(reg >> 8) & REG5338_PAGE_MASK;
+ page=(reg >> 8) & REG5338_PAGE_MASK;
+ dev_dbg(&client->dev,"reading i2c device : slave=0x%x, reg=0x%x page=0x%x, last_page=0x%x\n",(int) (client->addr),reg,page,clientdata->last_page);
+
//
dev_dbg(&client->dev,"reading i2c device : slave=0x%x, reg=0x%x page=0x%x, last_page=0x%x\n",(int) (client->addr),reg,page,clientdata->last_page);
+ if (clientdata && (reg!=REG5338_PAGE) && (page != clientdata->last_page)) { /* set page if needed */
+ if (clientdata && (reg!=REG5338_PAGE) && (page != clientdata->last_page)) { /* set page if needed */
+ if (((rc=_write_single_reg(client, REG5338_PAGE, page)))<0) return rc;
+ if (((rc=_write_single_reg(client, REG5338_PAGE, page)))<0) return rc;
+ }
+ }
...
@@ -1700,31 +2337,20 @@ Index: git/drivers/misc/si5338.c
...
@@ -1700,31 +2337,20 @@ Index: git/drivers/misc/si5338.c
+ dev_info(&client->dev,"Found '%s', value = %d (0x%x)\n","si5338,in_mux",(int)(be32_to_cpup(config_data)),(int)(be32_to_cpup(config_data)));
+ dev_info(&client->dev,"Found '%s', value = %d (0x%x)\n","si5338,in_mux",(int)(be32_to_cpup(config_data)),(int)(be32_to_cpup(config_data)));
+ set_in_mux(client, be32_to_cpup(config_data));
+ set_in_mux(client, be32_to_cpup(config_data));
+ }
+ }
+ config_data = of_get_property(client->dev.of_node, "si5338,fb_mux", &len);
+ if (config_data && (len>0)) {
+ dev_info(&client->dev,"Found '%s', value = %d (0x%x)\n","si5338,fb_mux",(int)(be32_to_cpup(config_data)),(int)(be32_to_cpup(config_data)));
+ set_fb_mux(client, be32_to_cpup(config_data));
+ }
+ config_data = of_get_property(client->dev.of_node, "si5338,in_frequency", &len);
+ config_data = of_get_property(client->dev.of_node, "si5338,in_frequency", &len);
+ if (config_data && (len>0)) {
+ if (config_data && (len>0)) {
+ dev_info(&client->dev,"Found '%s', value = %d (0x%x)\n","si5338,in_frequency",(int)(be32_to_cpup(config_data)),(int)(be32_to_cpup(config_data)));
+ dev_info(&client->dev,"Found '%s', value = %d (0x%x)\n","si5338,in_frequency",(int)(be32_to_cpup(config_data)),(int)(be32_to_cpup(config_data)));
+ set_in_frequency(client, be32_to_cpup(config_data)); /* 32 bits are sufficient here */
+ set_in_frequency(client, be32_to_cpup(config_data)); /* 32 bits are sufficient here */
+ }
+ }
+/*
+si5338 0-0070: Chip si5338 is found, driver version 1.0
+si5338 0-0070: Found 2 items in 'si5338,configuration_data' in the Device Tree
+si5338 0-0070: Invalid value for input multiplexer 16777216
+si5338 0-0070: Input frequency too high: 1081638145 > 710000000
+ */
+ } else {
+ } else {
+ dev_info(&client->dev,"Device tree data not found for %s\n",client->name);
+ dev_info(&client->dev,"Device tree data not found for %s\n",client->name);
+ }
+ }
+}
+}
+#if 0
+si5338,in_pfd_ref=<0>; /* p1div_in (input divisors not used) */
+si5338,in_pfd_fb= <0>; /* unused */
+si5338,in_p1_div= <0>; /* unused */
+si5338,in_p2_div= <0>; /* unused */
+si5338,in_mux= <1>; /* in-3 */
+si5338,in_frequency= <25000000>; /* 25MHz */
+
+#endif
+
+
+
+static int si5338_i2c_probe(struct i2c_client *client,
+static int si5338_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment