Commit e8f2c31a authored by Andrey Filippov's avatar Andrey Filippov

si5338.c - debugging, comparing to the map by the manufacturers software

parent 530f9049
Index: git/drivers/misc/Kconfig Index: git/drivers/misc/Kconfig
=================================================================== ===================================================================
--- git.orig/drivers/misc/Kconfig 2013-12-07 11:59:45.450394753 -0700 --- git.orig/drivers/misc/Kconfig 2013-12-08 13:24:02.319343372 -0700
+++ git/drivers/misc/Kconfig 2013-12-07 11:59:48.558394785 -0700 +++ git/drivers/misc/Kconfig 2013-12-08 13:24:46.000000000 -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-07 11:59:45.450394753 -0700 --- git.orig/drivers/misc/Makefile 2013-12-08 13:24:02.319343372 -0700
+++ git/drivers/misc/Makefile 2013-12-07 11:59:48.558394785 -0700 +++ git/drivers/misc/Makefile 2013-12-08 13:24:46.000000000 -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-07 11:59:48.558394785 -0700 +++ git/drivers/misc/vsc330x.c 2013-12-08 13:24:46.000000000 -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-08 01:27:57.338897726 -0700 +++ git/drivers/misc/si5338.c 2013-12-09 00:58:03.587775288 -0700
@@ -0,0 +1,3542 @@ @@ -0,0 +1,3764 @@
+/*!*************************************************************************** +/*!***************************************************************************
+ *! 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
...@@ -968,6 +968,8 @@ Index: git/drivers/misc/si5338.c ...@@ -968,6 +968,8 @@ Index: git/drivers/misc/si5338.c
+#define MSINT_MIN 8 /* not considering 4,6 */ +#define MSINT_MIN 8 /* not considering 4,6 */
+#define MSINT_MAX 567 +#define MSINT_MAX 567
+ +
+#define INIT_TIMEOUT 1000 /* reads of the I2C status register (1 cycle ~ 0.1 ms) */
+
+#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_MUX 0x1e18
...@@ -1014,13 +1016,10 @@ Index: git/drivers/misc/si5338.c ...@@ -1014,13 +1016,10 @@ Index: git/drivers/misc/si5338.c
+#define AWE_DRV2_TRIM 0x297c +#define AWE_DRV2_TRIM 0x297c
+#define AWE_DRV3_TRIM 0x2a1f +#define AWE_DRV3_TRIM 0x2a1f
+ +
+#define AWE_FCAL_OVRD_A 0x2bff
+#define AWE_FCAL_OVRD_B 0x2cff
+#define AWE_FCAL_OVRD_C 0x2d03
+
+#define AWE_FCAL_OVRD_07_00 0x2dff +#define AWE_FCAL_OVRD_07_00 0x2dff
+#define AWE_FCAL_OVRD_15_08 0x2eff +#define AWE_FCAL_OVRD_15_08 0x2eff
+#define AWE_FCAL_OVRD_17_15 0x2f03 +#define AWE_FCAL_OVRD_17_15 0x2f03
+#define AWE_REG47_72 0x2ffc
+#define AWE_PFD_EXTFB 0x3080 +#define AWE_PFD_EXTFB 0x3080
+#define AWE_PLL_KPHI 0x307f +#define AWE_PLL_KPHI 0x307f
+#define AWE_FCAL_OVRD_EN 0x3180 +#define AWE_FCAL_OVRD_EN 0x3180
...@@ -1119,6 +1118,13 @@ Index: git/drivers/misc/si5338.c ...@@ -1119,6 +1118,13 @@ Index: git/drivers/misc/si5338.c
+#define AWE_OUT2_DIS_STATE 0x76c0 +#define AWE_OUT2_DIS_STATE 0x76c0
+#define AWE_OUT3_DIS_STATE 0x7ac0 +#define AWE_OUT3_DIS_STATE 0x7ac0
+ +
+#define AWE_STATUS 0xdaff
+#define AWE_STATUS_PLL_LOL 0xda10
+#define AWE_STATUS_PLL_LOS_FDBK 0xda08
+#define AWE_STATUS_PLL_LOS_CLKIN 0xda04
+#define AWE_STATUS_PLL_SYS_CAL 0xda01
+
+#define AWE_MS_RESET 0xe204
+ +
+#define AWE_OUT0_DIS 0xe601 +#define AWE_OUT0_DIS 0xe601
+#define AWE_OUT1_DIS 0xe602 +#define AWE_OUT1_DIS 0xe602
...@@ -1126,6 +1132,26 @@ Index: git/drivers/misc/si5338.c ...@@ -1126,6 +1132,26 @@ Index: git/drivers/misc/si5338.c
+#define AWE_OUT3_DIS 0xe608 +#define AWE_OUT3_DIS 0xe608
+#define AWE_OUT_ALL_DIS 0xe610 +#define AWE_OUT_ALL_DIS 0xe610
+ +
+#define AWE_FCAL_07_00 0xebff
+#define AWE_FCAL_15_08 0xecff
+#define AWE_FCAL_17_16 0xed03
+
+
+#define AWE_DIS_LOS 0xf180
+#define AWE_REG241 0xf1ff
+
+#define AWE_SOFT_RESET 0xf602
+
+
+#define AWE_MS0_SSUPP3_07_00 0x121ff /* set them to 0 - default==1 */
+#define AWE_MS0_SSUPP3_14_08 0x1227f
+#define AWE_MS1_SSUPP3_07_00 0x131ff
+#define AWE_MS1_SSUPP3_14_08 0x1327f
+#define AWE_MS2_SSUPP3_07_00 0x141ff
+#define AWE_MS2_SSUPP3_14_08 0x1427f
+#define AWE_MS3_SSUPP3_07_00 0x151ff
+#define AWE_MS3_SSUPP3_14_08 0x1527f
+
+ +
+ +
+#define AWE_MISC_47 0x2ffc /* write 0x5 */ +#define AWE_MISC_47 0x2ffc /* write 0x5 */
...@@ -1240,18 +1266,24 @@ Index: git/drivers/misc/si5338.c ...@@ -1240,18 +1266,24 @@ Index: git/drivers/misc/si5338.c
+ +
+ {NULL, 0x0,0x0,0x0,0x0}, + {NULL, 0x0,0x0,0x0,0x0},
+}; +};
+static const int volatile_registers[]={218,-1}; +static const int volatile_registers[]={AWE_STATUS, AWE_SOFT_RESET, AWE_FCAL_07_00, AWE_FCAL_15_08, AWE_FCAL_17_16, -1};
+static const char *out_names[]={"output0","output1","output2","output3","outputs", NULL}; +static const char *out_names[]={"output0","output1","output2","output3","outputs", NULL};
+static const char *in_freq_names[]={"in_frequency12", "in_frequency3", "in_frequency4", "in_frequency56", "in_frequency12xo", NULL}; +static const char *in_freq_names[]={"in_frequency12", "in_frequency3", "in_frequency4", "in_frequency56", "in_frequency12xo", NULL};
+static const char *pll_setup_names[]={"pll_freq_fract", "pll_freq_int", "pll_by_out_fract", "pll_by_out_int", NULL}; +static const char *pll_setup_names[]={"pll_freq_fract", "pll_freq_int", "pll_by_out_fract", "pll_by_out_int", NULL};
+static const char *out_freq_setup_names[]={ +static const char *out_freq_setup_names[]={
+ "out0_freq_fract", "out1_freq_fract", "out2_freq_fract", "out3_freq_fract", + "out0_freq_fract", "out1_freq_fract", "out2_freq_fract", "out3_freq_fract",
+ "out0_freq_int", "out1_freq_int", "out2_freq_int", "out3_freq_int", NULL}; + "out0_freq_int", "out1_freq_int", "out2_freq_int", "out3_freq_int", NULL};
+static u32 awe_msx_ssup3[4][3]=
+ {{AWE_MS0_SSUPP3_07_00,AWE_MS0_SSUPP3_14_08,0},
+ {AWE_MS1_SSUPP3_07_00,AWE_MS1_SSUPP3_14_08,0},
+ {AWE_MS2_SSUPP3_07_00,AWE_MS2_SSUPP3_14_08,0},
+ {AWE_MS3_SSUPP3_07_00,AWE_MS3_SSUPP3_14_08,0}};
+ +
+static void si5338_init_of(struct i2c_client *client); +static void si5338_init_of(struct i2c_client *client);
+ +
+static int get_chn_from_name(const char * name); +static int get_chn_from_name(const char * name);
+ +
+static ssize_t invalidate_cache_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t raw_address_show (struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t raw_address_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t raw_address_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t raw_address_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t raw_data_show (struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t raw_data_show (struct device *dev, struct device_attribute *attr, char *buf);
...@@ -1302,6 +1334,8 @@ Index: git/drivers/misc/si5338.c ...@@ -1302,6 +1334,8 @@ Index: git/drivers/misc/si5338.c
+static ssize_t ms_powerdown_show (struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t ms_powerdown_show (struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ms_powerdown_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t ms_powerdown_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ +
+static ssize_t pre_init_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t post_init_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_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); +static ssize_t pll_freq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t pll_ms_freq_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t pll_ms_freq_show(struct device *dev, struct device_attribute *attr, char *buf);
...@@ -1383,7 +1417,9 @@ Index: git/drivers/misc/si5338.c ...@@ -1383,7 +1417,9 @@ Index: git/drivers/misc/si5338.c
+static int set_out_frequency_and_route (struct i2c_client *client, u64 *out_freq, int chn, int int_div); +static int set_out_frequency_and_route (struct i2c_client *client, u64 *out_freq, int chn, int int_div);
+static s64 get_output_src_frequency(struct i2c_client *client, u64 *out_freq, int chn); +static s64 get_output_src_frequency(struct i2c_client *client, u64 *out_freq, int chn);
+ +
+ +static int pre_init(struct i2c_client *client);
+static int post_init(struct i2c_client *client, int timeout); /*1 in timeout ~ 0.1ms - i2c read register */
+static int get_status(struct i2c_client *client);
+static int set_pll_paremeters(struct i2c_client *client); +static int set_pll_paremeters(struct i2c_client *client);
+static int set_misc_registers(struct i2c_client *client); +static int set_misc_registers(struct i2c_client *client);
+static int get_ms_powerdown(struct i2c_client *client, int chn); +static int get_ms_powerdown(struct i2c_client *client, int chn);
...@@ -1425,24 +1461,28 @@ Index: git/drivers/misc/si5338.c ...@@ -1425,24 +1461,28 @@ Index: git/drivers/misc/si5338.c
+static int write_adwe(struct i2c_client *client, u32 adwe); +static int write_adwe(struct i2c_client *client, u32 adwe);
+static int write_reg(struct i2c_client *client, u16 reg, u8 val, u8 mask); +static int write_reg(struct i2c_client *client, u16 reg, u8 val, u8 mask);
+static int read_reg(struct i2c_client *client, u16 reg); +static int read_reg(struct i2c_client *client, u16 reg);
+static void invalidate_cache(struct i2c_client *client);
+ +
+ +
+/* raw access to i2c registers, need to set address (9 bits) first, then r/w data */ +/* raw access to i2c registers, need to set address (9 bits) first, then r/w data */
+static DEVICE_ATTR(address, SYSFS_PERMISSIONS, raw_address_show, raw_address_store); +
+static DEVICE_ATTR(data, SYSFS_PERMISSIONS, raw_data_show, raw_data_store); +static DEVICE_ATTR(invalidate_cache, SYSFS_PERMISSIONS & SYSFS_WRITEONLY, NULL, invalidate_cache_store);
+static DEVICE_ATTR(hex_address, SYSFS_PERMISSIONS, raw_hex_address_show, raw_hex_address_store); +static DEVICE_ATTR(address, SYSFS_PERMISSIONS, raw_address_show, raw_address_store);
+static DEVICE_ATTR(hex_data, SYSFS_PERMISSIONS, raw_hex_data_show, raw_hex_data_store); +static DEVICE_ATTR(data, SYSFS_PERMISSIONS, raw_data_show, raw_data_store);
+static DEVICE_ATTR(hex_all, SYSFS_PERMISSIONS & SYSFS_READONLY, raw_hex_all_show, NULL); +static DEVICE_ATTR(hex_address, SYSFS_PERMISSIONS, raw_hex_address_show,raw_hex_address_store);
+static DEVICE_ATTR(hex_adwe, SYSFS_PERMISSIONS, raw_hex_adwe_show, raw_hex_adwe_store); +static DEVICE_ATTR(hex_data, SYSFS_PERMISSIONS, raw_hex_data_show, raw_hex_data_store);
+static DEVICE_ATTR(hex_all, SYSFS_PERMISSIONS & SYSFS_READONLY, raw_hex_all_show, NULL);
+static DEVICE_ATTR(hex_adwe, SYSFS_PERMISSIONS, raw_hex_adwe_show, raw_hex_adwe_store);
+ +
+static struct attribute *raw_dev_attrs[] = { +static struct attribute *raw_dev_attrs[] = {
+ &dev_attr_address.attr, + &dev_attr_invalidate_cache.attr,
+ &dev_attr_data.attr, + &dev_attr_address.attr,
+ &dev_attr_hex_address.attr, + &dev_attr_data.attr,
+ &dev_attr_hex_data.attr, + &dev_attr_hex_address.attr,
+ &dev_attr_hex_all.attr, + &dev_attr_hex_data.attr,
+ &dev_attr_hex_adwe.attr, + &dev_attr_hex_all.attr,
+ NULL + &dev_attr_hex_adwe.attr,
+ NULL
+}; +};
+ +
+static const struct attribute_group dev_attr_raw_group = { +static const struct attribute_group dev_attr_raw_group = {
...@@ -1534,10 +1574,15 @@ Index: git/drivers/misc/si5338.c ...@@ -1534,10 +1574,15 @@ Index: git/drivers/misc/si5338.c
+ .attrs = multisynth_attrs, + .attrs = multisynth_attrs,
+ .name = "multiSynth", + .name = "multiSynth",
+}; +};
+static DEVICE_ATTR(pll_freq_fract, SYSFS_PERMISSIONS, pll_freq_show, pll_freq_store); +
+static DEVICE_ATTR(pll_freq_int, SYSFS_PERMISSIONS, pll_freq_show, pll_freq_store); +
+static DEVICE_ATTR(pll_by_out_fract,SYSFS_PERMISSIONS, pll_freq_show, pll_freq_store); +
+static DEVICE_ATTR(pll_by_out_int, SYSFS_PERMISSIONS, pll_freq_show, pll_freq_store); +static DEVICE_ATTR(pre_init, SYSFS_PERMISSIONS & SYSFS_WRITEONLY, NULL, pre_init_store);
+static DEVICE_ATTR(post_init, SYSFS_PERMISSIONS & SYSFS_WRITEONLY, NULL, post_init_store);
+static DEVICE_ATTR(pll_freq_fract, SYSFS_PERMISSIONS, pll_freq_show, pll_freq_store);
+static DEVICE_ATTR(pll_freq_int, SYSFS_PERMISSIONS, pll_freq_show, pll_freq_store);
+static DEVICE_ATTR(pll_by_out_fract,SYSFS_PERMISSIONS, pll_freq_show, pll_freq_store);
+static DEVICE_ATTR(pll_by_out_int, SYSFS_PERMISSIONS, pll_freq_show, pll_freq_store);
+ +
+/* has to have/not have '_fract' in the name */ +/* has to have/not have '_fract' in the name */
+static DEVICE_ATTR(pll_ms0_freq_fract,SYSFS_PERMISSIONS, pll_ms_freq_show, pll_ms_freq_store); +static DEVICE_ATTR(pll_ms0_freq_fract,SYSFS_PERMISSIONS, pll_ms_freq_show, pll_ms_freq_store);
...@@ -1551,6 +1596,8 @@ Index: git/drivers/misc/si5338.c ...@@ -1551,6 +1596,8 @@ Index: git/drivers/misc/si5338.c
+ +
+ +
+static struct attribute *pll_dev_attrs[] = { +static struct attribute *pll_dev_attrs[] = {
+ &dev_attr_pre_init.attr,
+ &dev_attr_post_init.attr,
+ &dev_attr_pll_ref_frequency.attr, + &dev_attr_pll_ref_frequency.attr,
+ &dev_attr_pll_freq_fract.attr, + &dev_attr_pll_freq_fract.attr,
+ &dev_attr_pll_freq_int.attr, + &dev_attr_pll_freq_int.attr,
...@@ -1786,6 +1833,7 @@ Index: git/drivers/misc/si5338.c ...@@ -1786,6 +1833,7 @@ Index: git/drivers/misc/si5338.c
+ return (cp)?(cp[0]-'0'):-1; + return (cp)?(cp[0]-'0'):-1;
+} +}
+ +
+
+static int make_config_out (struct device *dev, +static int make_config_out (struct device *dev,
+ ssize_t (*show_output)(struct device *dev, struct device_attribute *attr, char *buf), + ssize_t (*show_output)(struct device *dev, struct device_attribute *attr, char *buf),
+ ssize_t (*store_config)(struct device *dev, struct device_attribute *attr, + ssize_t (*store_config)(struct device *dev, struct device_attribute *attr,
...@@ -1894,6 +1942,7 @@ Index: git/drivers/misc/si5338.c ...@@ -1894,6 +1942,7 @@ Index: git/drivers/misc/si5338.c
+ len+=rc; + len+=rc;
+ return len; + return len;
+} +}
+
+static ssize_t output_route_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t output_route_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{ +{
+ int chn, rc; + int chn, rc;
...@@ -1903,6 +1952,8 @@ Index: git/drivers/misc/si5338.c ...@@ -1903,6 +1952,8 @@ Index: git/drivers/misc/si5338.c
+ return count; + return count;
+} +}
+ +
+//static void invalidate_cache(struct i2c_client *client)
+
+ +
+static int get_output_description (struct device *dev, char * buf, int chn) +static int get_output_description (struct device *dev, char * buf, int chn)
+{ +{
...@@ -1979,7 +2030,12 @@ Index: git/drivers/misc/si5338.c ...@@ -1979,7 +2030,12 @@ Index: git/drivers/misc/si5338.c
+ return retval; + return retval;
+} +}
+ +
+ +static ssize_t invalidate_cache_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ invalidate_cache(client);
+ return count;
+}
+ +
+static ssize_t raw_address_show (struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t raw_address_show (struct device *dev, struct device_attribute *attr, char *buf)
+{ +{
...@@ -2080,14 +2136,14 @@ Index: git/drivers/misc/si5338.c ...@@ -2080,14 +2136,14 @@ Index: git/drivers/misc/si5338.c
+ */ + */
+static ssize_t raw_hex_adwe_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t raw_hex_adwe_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{ +{
+ const char digits[]="0123456789"; + const char hex_digits[]="0123456789abcdefABCDEF";
+ struct i2c_client *client = to_i2c_client(dev); + struct i2c_client *client = to_i2c_client(dev);
+ struct si5338_data_t *clientdata= i2c_get_clientdata(client); + struct si5338_data_t *clientdata= i2c_get_clientdata(client);
+ int adwe,rc=0; + int adwe,rc=0;
+ int left=count,num_bytes; + int left=count,num_bytes;
+ const char * cp; + const char * cp;
+ mutex_lock(&clientdata->lock); + mutex_lock(&clientdata->lock);
+ while ((left>0) && ((cp=strpbrk(buf,digits))) && cp[0]){ + while ((left>0) && ((cp=strpbrk(buf,hex_digits))) && cp[0]){
+ left -= (cp-buf); + left -= (cp-buf);
+ buf = cp; + buf = cp;
+ dev_dbg(dev,"left=%d", left); + dev_dbg(dev,"left=%d", left);
...@@ -2348,6 +2404,10 @@ Index: git/drivers/misc/si5338.c ...@@ -2348,6 +2404,10 @@ Index: git/drivers/misc/si5338.c
+ p123[2]=1; + p123[2]=1;
+ } + }
+ if (((rc=set_ms_p123(client,p123, chn)))<0) return rc; + if (((rc=set_ms_p123(client,p123, chn)))<0) return rc;
+ if (chn<4){
+ /* disable spread spectrum - only this register was changed to 0 from default 1 */
+ if (((rc=write_multireg64(client, 0 , awe_msx_ssup3[chn])))<0) return rc;
+ }
+ return count; + return count;
+} +}
+static ssize_t ms_abc_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t ms_abc_show(struct device *dev, struct device_attribute *attr, char *buf)
...@@ -2380,6 +2440,10 @@ Index: git/drivers/misc/si5338.c ...@@ -2380,6 +2440,10 @@ Index: git/drivers/misc/si5338.c
+ } + }
+ ms_to_p123(ms,p123); + ms_to_p123(ms,p123);
+ if (((rc=set_ms_p123(client,p123, chn)))<0) return rc; + if (((rc=set_ms_p123(client,p123, chn)))<0) return rc;
+ if (chn<4){
+ /* disable spread spectrum - only this register was changed to 0 from default 1 */
+ if (((rc=write_multireg64(client, 0 , awe_msx_ssup3[chn])))<0) return rc;
+ }
+ return count; + return count;
+} +}
+ +
...@@ -2401,6 +2465,24 @@ Index: git/drivers/misc/si5338.c ...@@ -2401,6 +2465,24 @@ Index: git/drivers/misc/si5338.c
+ return count; + return count;
+} +}
+ +
+static ssize_t pre_init_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int rc;
+ if (((rc=pre_init(client)))<0) return rc;
+ return count;
+}
+
+static ssize_t post_init_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int rc,timeout=0;
+ sscanf(buf, "%d", &timeout);
+ if (timeout <=0) timeout=INIT_TIMEOUT;
+ if (((rc=post_init(client,timeout)))<0) return rc;
+ return count;
+}
+
+static ssize_t pll_freq_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t pll_freq_show(struct device *dev, struct device_attribute *attr, char *buf)
+{ +{
+ int rc; + int rc;
...@@ -3321,11 +3403,13 @@ Index: git/drivers/misc/si5338.c ...@@ -3321,11 +3403,13 @@ Index: git/drivers/misc/si5338.c
+ /* setup MSn division */ + /* setup MSn division */
+ if (((rc=set_pll_ms_by_out(client, out_freq, chn, int_div)))<0) return rc; + if (((rc=set_pll_ms_by_out(client, out_freq, chn, int_div)))<0) return rc;
+ /* enable power for selected MS */ + /* enable power for selected MS */
+ if (((rc=set_ms_powerdown(client, 1, chn)))<0) return rc; + if (((rc=set_ms_powerdown(client, 0, chn)))<0) return rc;
+ /* route MSn to the output (6 - use 'own' MS) */ + /* route MSn to the output (6 - use 'own' MS) */
+ if (((rc=set_out_source(client, chn, 6)))<0) return rc; + if (((rc=set_out_source(client, chn, 6)))<0) return rc;
+ /* setup output (R) division - by 1/2/4/8/16/32 */ + /* setup output (R) division - by 1/2/4/8/16/32 */
+ if (((rc=set_out_div_by_frequency(client, out_freq, chn)))<0) return rc; + if (((rc=set_out_div_by_frequency(client, out_freq, chn)))<0) return rc;
+ /* enable power for selected output */
+ if (((rc=set_drv_powerdown(client, 0, chn)))<0) return rc;
+ return 0; /* all done */ + return 0; /* all done */
+} +}
+ +
...@@ -3379,6 +3463,93 @@ Index: git/drivers/misc/si5338.c ...@@ -3379,6 +3463,93 @@ Index: git/drivers/misc/si5338.c
+} +}
+ +
+/* -----------PLL section--------------------------- */ +/* -----------PLL section--------------------------- */
+static u32 awe_fcal[]= {AWE_FCAL_07_00, AWE_FCAL_15_08, AWE_FCAL_17_16, 0};
+static u32 awe_fcal_ovrd[]={AWE_FCAL_OVRD_07_00, AWE_FCAL_OVRD_15_08, AWE_FCAL_OVRD_17_15, 0};
+static int pre_init(struct i2c_client *client)
+{
+ int rc;
+ if (((rc=write_field(client, 1, AWE_OUT_ALL_DIS )))<0) return rc; /* disable all outputs */
+ if (((rc=write_field(client, 1, AWE_DIS_LOS )))<0) return rc; /* pause LOL */
+ return 0;
+}
+static int post_init(struct i2c_client *client, int timeout) /*1 in timeout ~ 0.1ms - i2c read register */
+{
+ int rc,i,in_src, fb_src,ext_fb,check_los=0;
+ s64 fcal;
+ /* validate input clock status */
+ if (((in_src=get_in_pfd_ref_fb(client,0)))<0) return in_src;
+ switch (in_src){
+ case 0:
+ case 2:
+ case 4:
+ check_los |= AWE_STATUS_PLL_LOS_CLKIN; break;
+ case 1:
+ case 3:
+ check_los |= AWE_STATUS_PLL_LOS_FDBK; break;
+ }
+ if (((ext_fb=read_field(client,AWE_PFD_EXTFB)))<0) return ext_fb;
+ if (ext_fb){
+ if (((fb_src=get_in_pfd_ref_fb(client,1)))<0) return fb_src;
+ switch (in_src){
+ case 1:
+ case 3:
+ check_los |= AWE_STATUS_PLL_LOS_CLKIN; break;
+ case 0:
+ case 2:
+ check_los |= AWE_STATUS_PLL_LOS_FDBK; break;
+ }
+ }
+ check_los &= 0xf;
+ for (i=0;i<timeout;i++){
+ if (((rc=get_status(client)))<0) return rc;
+ if ((rc & check_los)==0) break; /* inputs OK */
+ }
+ if (i>=timeout){
+ dev_err(&client->dev, "Timeout waiting for input clocks, status=0x%x, mask=0x%x\n",rc, check_los);
+ return -EPIPE;
+ }
+ dev_dbg(&client->dev, "Validated input clocks, t=%d cycles (timeout= %d cycles), status =0x%x, mask=0x%x\n",
+ i, timeout, rc, check_los);
+
+ if (((rc=write_field(client, 0, AWE_FCAL_OVRD_EN )))<0) return rc; /* Configure PLL for locking, set FCAL_OVRD_EN=0 */
+ write_field(client, 1, AWE_SOFT_RESET ); /* Configure PLL for locking, set SOFT_RESET=1 (ignore i2c error) */
+ for (i=0;i<250;i++) get_status(client); /* wait 25 ms */
+ if (((rc=write_field(client, 0x65, AWE_REG241 )))<0) return rc; /* re-enable LOL, set reg 241=0x65 */
+
+ check_los |= AWE_STATUS_PLL_LOL | AWE_STATUS_PLL_SYS_CAL;
+ check_los &= 0xf;
+ for (i=0;i<timeout;i++){
+ if (((rc=get_status(client)))<0) return rc;
+ if ((rc & check_los)==0) break; /* alarms not set OK */
+ }
+ if (i>=timeout){
+ dev_err(&client->dev, "Timeout waiting for PLL lock, status=0x%x, mask=0x%x\n",rc, check_los);
+ return -EPIPE;
+ }
+ dev_dbg(&client->dev, "Validated PLL locked, t=%d cycles (timeout= %d cycles), status =0x%x, mask=0x%x\n",
+ i, timeout, rc, check_los);
+
+ /* copy FCAL values to active registers */
+ if (((fcal=read_multireg64 (client, awe_fcal)))<0) return (int) fcal;
+ if (((rc= write_multireg64(client, fcal, awe_fcal_ovrd)))<0) return rc;
+ dev_dbg(&client->dev, "Copied FCAL data 0x%llx\n", fcal);
+ if (((rc=write_field(client, 5, AWE_REG47_72 )))<0) return rc; /* set 47[7:2] to 000101b */
+ if (((rc=write_field(client, 1, AWE_FCAL_OVRD_EN )))<0) return rc; /* SET PLL to use FCAL values, set FCAL_OVRD_EN=1 */
+ /* only needed if using down-spread. Won't hurt to do anyway */
+ if (((rc=write_field(client, 1, AWE_MS_RESET )))<0) return rc; /* SET MS RESET=1 */
+ for (i=0;i<10;i++) get_status(client); /* wait 1 ms */
+ if (((rc=write_field(client, 0, AWE_MS_RESET )))<0) return rc; /* SET MS RESET=0 */
+ if (((rc=write_field(client, 0, AWE_OUT_ALL_DIS )))<0) return rc; /* enable all (enabled individually) outputs */
+ write_field(client, 0, AWE_SOFT_RESET ); /* Not documented - what to do with the soft reset bit - clearing */
+ return 0;
+}
+
+static int get_status(struct i2c_client *client)
+{
+ return read_field(client,AWE_STATUS);
+}
+
+
+static int set_pll_paremeters(struct i2c_client *client) +static int set_pll_paremeters(struct i2c_client *client)
+{ +{
+ int rc; + int rc;
...@@ -3433,6 +3604,7 @@ Index: git/drivers/misc/si5338.c ...@@ -3433,6 +3604,7 @@ Index: git/drivers/misc/si5338.c
+ AWE_VCO_GAIN_RSEL_BWSEL)))<0) return rc; + AWE_VCO_GAIN_RSEL_BWSEL)))<0) return rc;
+ if (((rc=write_field(client, (u8) mscal, AWE_MSCAL )))<0) return rc; + if (((rc=write_field(client, (u8) mscal, AWE_MSCAL )))<0) return rc;
+ if (((rc=write_field(client, (u8) ms_pec, AWE_MS_PEC)))<0) return rc; + if (((rc=write_field(client, (u8) ms_pec, AWE_MS_PEC)))<0) return rc;
+ if (((rc=write_field(client, 3, AWE_PLL_EN)))<0) return rc; /* enable PLL */
+ return 0; + return 0;
+} +}
+ +
...@@ -3470,6 +3642,7 @@ Index: git/drivers/misc/si5338.c ...@@ -3470,6 +3642,7 @@ Index: git/drivers/misc/si5338.c
+ {AWE_MSN_P2_05_00, AWE_MSN_P2_13_06, AWE_MSN_P2_21_14, AWE_MSN_P2_29_22, 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}}}; + {AWE_MSN_P3_07_00, AWE_MSN_P3_15_08, AWE_MSN_P3_23_16, AWE_MSN_P3_29_24, 0}}};
+ +
+
+static const u32 awe_ms_powerdown[]={AWE_MS0_PDN, AWE_MS1_PDN, AWE_MS2_PDN, AWE_MS3_PDN}; +static const u32 awe_ms_powerdown[]={AWE_MS0_PDN, AWE_MS1_PDN, AWE_MS2_PDN, AWE_MS3_PDN};
+static int get_ms_powerdown(struct i2c_client *client, int chn) +static int get_ms_powerdown(struct i2c_client *client, int chn)
+{ +{
...@@ -3572,6 +3745,7 @@ Index: git/drivers/misc/si5338.c ...@@ -3572,6 +3745,7 @@ Index: git/drivers/misc/si5338.c
+ */ + */
+static int set_pll_freq(struct i2c_client *client, u64 *vco_freq, int int_div) +static int set_pll_freq(struct i2c_client *client, u64 *vco_freq, int int_div)
+{ +{
+ int rc;
+ s64 pll_in_freq, pll_in_freq_scaled,pll_out_freq_scaled,d; + s64 pll_in_freq, pll_in_freq_scaled,pll_out_freq_scaled,d;
+ u32 msn_p123[3]; + u32 msn_p123[3];
+ u64 msn[]={0,0,1}; + u64 msn[]={0,0,1};
...@@ -3771,9 +3945,15 @@ Index: git/drivers/misc/si5338.c ...@@ -3771,9 +3945,15 @@ Index: git/drivers/misc/si5338.c
+ ms_scaled=ms[0]*ms[2]+ms[1]; + ms_scaled=ms[0]*ms[2]+ms[1];
+ out_freq[1]=pll_freq_scaled*ms[2]; + out_freq[1]=pll_freq_scaled*ms[2];
+ out_freq[2]=ms_scaled*pll_out_freq[2]; + out_freq[2]=ms_scaled*pll_out_freq[2];
+ out_freq[0]=div64_u64(out_freq[1],out_freq[2]); + if (out_freq[2]==0){
+ out_freq[1]-=out_freq[0]*out_freq[2]; + out_freq[0]=0;
+ remove_common_factor(&out_freq[1]); + out_freq[1]=0;
+ out_freq[2]=1;
+ } else {
+ out_freq[0]=div64_u64(out_freq[1],out_freq[2]);
+ out_freq[1]-=out_freq[0]*out_freq[2];
+ remove_common_factor(&out_freq[1]);
+ }
+ dev_dbg(&client->dev, "MS%d output frequency: %llu+%llu/%llu Hz\n",chn,out_freq[0],out_freq[1],out_freq[2]); + dev_dbg(&client->dev, "MS%d output frequency: %llu+%llu/%llu Hz\n",chn,out_freq[0],out_freq[1],out_freq[2]);
+ return 0; + return 0;
+} +}
...@@ -3852,6 +4032,8 @@ Index: git/drivers/misc/si5338.c ...@@ -3852,6 +4032,8 @@ Index: git/drivers/misc/si5338.c
+ /* set up registers */ + /* set up registers */
+ ms_to_p123(ms,p123); + ms_to_p123(ms,p123);
+ if (((rc=set_ms_p123(client,p123, chn)))<0) return rc; + if (((rc=set_ms_p123(client,p123, chn)))<0) return rc;
+/* disable spread spectrum - only this register was changed to 0 from default 1 */
+ if (((rc=write_multireg64(client, 0 , awe_msx_ssup3[chn])))<0) return rc;
+ return 0; + return 0;
+} +}
+/* ----------- Input section ----------------- */ +/* ----------- Input section ----------------- */
...@@ -4229,14 +4411,19 @@ Index: git/drivers/misc/si5338.c ...@@ -4229,14 +4411,19 @@ Index: git/drivers/misc/si5338.c
+static int _write_single_reg(struct i2c_client *client, u8 reg, u8 val) +static int _write_single_reg(struct i2c_client *client, u8 reg, u8 val)
+{ +{
+ struct si5338_data_t *clientdata = i2c_get_clientdata(client); + struct si5338_data_t *clientdata = i2c_get_clientdata(client);
+ int ireg=reg;
+ dev_dbg(&client->dev,"device write: slave=0x%x, reg=0x%x, val=0x%x\n", (int) (client->addr),reg,val); + dev_dbg(&client->dev,"device write: slave=0x%x, reg=0x%x, val=0x%x\n", (int) (client->addr),reg,val);
+ if (clientdata && (reg==REG5338_PAGE)) { + if (clientdata) {
+// dev_dbg(&client->dev,"changing page: new=0x%x, was=0x%x\n",val & REG5338_PAGE_MASK,clientdata->last_page); + if (reg==REG5338_PAGE) {
+ clientdata->last_page=val & REG5338_PAGE_MASK; + // dev_dbg(&client->dev,"changing page: new=0x%x, was=0x%x\n",val & REG5338_PAGE_MASK,clientdata->last_page);
+ } + clientdata->last_page=val & REG5338_PAGE_MASK;
+ if (clientdata && (reg<=LAST_REG) ){ + } else {
+ clientdata->cache[reg].data= val; + ireg |=(clientdata->last_page)<<8;
+ clientdata->cache[reg].flags |= CACHE_INIT; + }
+ if (ireg<=LAST_REG){
+ clientdata->cache[ireg].data= val;
+ clientdata->cache[ireg].flags |= CACHE_INIT;
+ }
+ } + }
+ return i2c_smbus_write_byte_data(client, reg, val); + return i2c_smbus_write_byte_data(client, reg, val);
+} +}
...@@ -4257,6 +4444,7 @@ Index: git/drivers/misc/si5338.c ...@@ -4257,6 +4444,7 @@ Index: git/drivers/misc/si5338.c
+ val=((val ^ rc) & mask)^ rc; + val=((val ^ rc) & mask)^ rc;
+ if ((val==rc) && !(clientdata->cache[reg].flags & CACHE_VOLAT)) { + if ((val==rc) && !(clientdata->cache[reg].flags & CACHE_VOLAT)) {
+ dev_dbg(&client->dev,"No change and not volatile -> no write\n"); + dev_dbg(&client->dev,"No change and not volatile -> no write\n");
+ return 0;
+ } + }
+ } + }
+ return _write_single_reg(client, reg & 0xff, val); + return _write_single_reg(client, reg & 0xff, val);
...@@ -4294,6 +4482,8 @@ Index: git/drivers/misc/si5338.c ...@@ -4294,6 +4482,8 @@ Index: git/drivers/misc/si5338.c
+{ +{
+ // struct device *dev=&client->dev; + // struct device *dev=&client->dev;
+ const __be32 * config_data; + const __be32 * config_data;
+ const char * init_type_string;
+ int init_type=0; /* 0 - none, 1 - always, 2 - if not running (TODO) */
+ struct device_node *node = client->dev.of_node; + struct device_node *node = client->dev.of_node;
+ int len,i,n; + int len,i,n;
+ u16 page_reg; + u16 page_reg;
...@@ -4308,6 +4498,24 @@ Index: git/drivers/misc/si5338.c ...@@ -4308,6 +4498,24 @@ Index: git/drivers/misc/si5338.c
+ struct si5338_setup_data setup_data; + struct si5338_setup_data setup_data;
+ __be32 * setup_data_be32= (__be32 *) &setup_data; + __be32 * setup_data_be32= (__be32 *) &setup_data;
+ if (node) { + if (node) {
+ init_type_string = of_get_property(client->dev.of_node, "si5338,init", &len);
+ if (init_type_string){
+ if (strcmp(init_type_string,"always")==0) init_type=1;
+ else if (strcmp(init_type_string,"if off")==0) init_type=2;
+ else {
+ dev_err(&client->dev,"Unrecognized si5338 initialization type '%s'. Only 'always' and 'if off' are permitted\n",init_type_string);
+ }
+ }
+ switch (init_type){
+ case 2:
+ dev_err(&client->dev,"Not yet implemented, initializing unconditionally\n");
+ init_type=1;
+ case 1:
+ pre_init(client);
+ break;
+ }
+
+
+ config_data = of_get_property(client->dev.of_node, "si5338,configuration_data", &len); + config_data = of_get_property(client->dev.of_node, "si5338,configuration_data", &len);
+ if (config_data){ + if (config_data){
+ len /= sizeof(*config_data); + len /= sizeof(*config_data);
...@@ -4387,11 +4595,25 @@ Index: git/drivers/misc/si5338.c ...@@ -4387,11 +4595,25 @@ Index: git/drivers/misc/si5338.c
+ } + }
+ } + }
+ +
+
+ } 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 (init_type){
+ if (post_init(client,INIT_TIMEOUT)<0) dev_err(&client->dev,"SI5338 initialization failed\n");
+ else dev_info(&client->dev,"SI5338 initialized\n");
+ }
+
+} +}
+ +
+static void invalidate_cache(struct i2c_client *client)
+{
+ int i;
+ struct si5338_data_t *clientdata = i2c_get_clientdata(client);
+ for (i=0;i<=LAST_REG;i++){
+ clientdata->cache[i].flags&= ~CACHE_INIT;
+ }
+}
+ +
+ +
+static int si5338_i2c_probe(struct i2c_client *client, +static int si5338_i2c_probe(struct i2c_client *client,
...@@ -4420,7 +4642,7 @@ Index: git/drivers/misc/si5338.c ...@@ -4420,7 +4642,7 @@ Index: git/drivers/misc/si5338.c
+ clientdata->cache[i].data=0; + clientdata->cache[i].data=0;
+ } + }
+ for (i=0;volatile_registers[i]>=0;i++){ + for (i=0;volatile_registers[i]>=0;i++){
+ clientdata->cache[volatile_registers[i]].flags |= CACHE_VOLAT; + clientdata->cache[volatile_registers[i]>>8].flags |= CACHE_VOLAT;
+ } + }
+ //volatile_registers[] + //volatile_registers[]
+ i2c_set_clientdata(client, clientdata); + i2c_set_clientdata(client, clientdata);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment