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
===================================================================
--- git.orig/drivers/misc/Kconfig 2013-12-07 11:59:45.450394753 -0700
+++ git/drivers/misc/Kconfig 2013-12-07 11:59:48.558394785 -0700
--- git.orig/drivers/misc/Kconfig 2013-12-08 13:24:02.319343372 -0700
+++ git/drivers/misc/Kconfig 2013-12-08 13:24:46.000000000 -0700
@@ -549,6 +549,19 @@
their requirements.
......@@ -24,8 +24,8 @@ Index: git/drivers/misc/Kconfig
source "drivers/misc/eeprom/Kconfig"
Index: git/drivers/misc/Makefile
===================================================================
--- git.orig/drivers/misc/Makefile 2013-12-07 11:59:45.450394753 -0700
+++ git/drivers/misc/Makefile 2013-12-07 11:59:48.558394785 -0700
--- git.orig/drivers/misc/Makefile 2013-12-08 13:24:02.319343372 -0700
+++ git/drivers/misc/Makefile 2013-12-08 13:24:46.000000000 -0700
@@ -55,3 +55,5 @@
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
......@@ -35,7 +35,7 @@ Index: git/drivers/misc/Makefile
Index: git/drivers/misc/vsc330x.c
===================================================================
--- /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 @@
+/*!***************************************************************************
+ *! FILE NAME : vsc330x.c
......@@ -912,8 +912,8 @@ Index: git/drivers/misc/vsc330x.c
Index: git/drivers/misc/si5338.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ git/drivers/misc/si5338.c 2013-12-08 01:27:57.338897726 -0700
@@ -0,0 +1,3542 @@
+++ git/drivers/misc/si5338.c 2013-12-09 00:58:03.587775288 -0700
@@ -0,0 +1,3764 @@
+/*!***************************************************************************
+ *! FILE NAME : si5338.c
+ *! DESCRIPTION: control of the Silicon Laboratories SI5338 clock generator
......@@ -968,6 +968,8 @@ Index: git/drivers/misc/si5338.c
+#define MSINT_MIN 8 /* not considering 4,6 */
+#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_MUX1 0x1c1c
+#define AWE_FB_MUX 0x1e18
......@@ -1014,13 +1016,10 @@ Index: git/drivers/misc/si5338.c
+#define AWE_DRV2_TRIM 0x297c
+#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_15_08 0x2eff
+#define AWE_FCAL_OVRD_17_15 0x2f03
+#define AWE_REG47_72 0x2ffc
+#define AWE_PFD_EXTFB 0x3080
+#define AWE_PLL_KPHI 0x307f
+#define AWE_FCAL_OVRD_EN 0x3180
......@@ -1119,6 +1118,13 @@ Index: git/drivers/misc/si5338.c
+#define AWE_OUT2_DIS_STATE 0x76c0
+#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_OUT1_DIS 0xe602
......@@ -1126,6 +1132,26 @@ Index: git/drivers/misc/si5338.c
+#define AWE_OUT3_DIS 0xe608
+#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 */
......@@ -1240,18 +1266,24 @@ Index: git/drivers/misc/si5338.c
+
+ {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 *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 *out_freq_setup_names[]={
+ "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};
+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 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_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);
......@@ -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_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_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);
......@@ -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 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_misc_registers(struct i2c_client *client);
+static int get_ms_powerdown(struct i2c_client *client, int chn);
......@@ -1425,24 +1461,28 @@ Index: git/drivers/misc/si5338.c
+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 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 */
+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(hex_address, SYSFS_PERMISSIONS, raw_hex_address_show, raw_hex_address_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 DEVICE_ATTR(invalidate_cache, SYSFS_PERMISSIONS & SYSFS_WRITEONLY, NULL, invalidate_cache_store);
+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(hex_address, SYSFS_PERMISSIONS, raw_hex_address_show,raw_hex_address_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[] = {
+ &dev_attr_address.attr,
+ &dev_attr_data.attr,
+ &dev_attr_hex_address.attr,
+ &dev_attr_hex_data.attr,
+ &dev_attr_hex_all.attr,
+ &dev_attr_hex_adwe.attr,
+ NULL
+ &dev_attr_invalidate_cache.attr,
+ &dev_attr_address.attr,
+ &dev_attr_data.attr,
+ &dev_attr_hex_address.attr,
+ &dev_attr_hex_data.attr,
+ &dev_attr_hex_all.attr,
+ &dev_attr_hex_adwe.attr,
+ NULL
+};
+
+static const struct attribute_group dev_attr_raw_group = {
......@@ -1534,10 +1574,15 @@ Index: git/drivers/misc/si5338.c
+ .attrs = multisynth_attrs,
+ .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 */
+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
+
+
+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_freq_fract.attr,
+ &dev_attr_pll_freq_int.attr,
......@@ -1786,6 +1833,7 @@ Index: git/drivers/misc/si5338.c
+ return (cp)?(cp[0]-'0'):-1;
+}
+
+
+static int make_config_out (struct device *dev,
+ ssize_t (*show_output)(struct device *dev, struct device_attribute *attr, char *buf),
+ ssize_t (*store_config)(struct device *dev, struct device_attribute *attr,
......@@ -1894,6 +1942,7 @@ Index: git/drivers/misc/si5338.c
+ len+=rc;
+ return len;
+}
+
+static ssize_t output_route_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int chn, rc;
......@@ -1903,6 +1952,8 @@ Index: git/drivers/misc/si5338.c
+ return count;
+}
+
+//static void invalidate_cache(struct i2c_client *client)
+
+
+static int get_output_description (struct device *dev, char * buf, int chn)
+{
......@@ -1979,7 +2030,12 @@ Index: git/drivers/misc/si5338.c
+ 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)
+{
......@@ -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)
+{
+ const char digits[]="0123456789";
+ const char hex_digits[]="0123456789abcdefABCDEF";
+ struct i2c_client *client = to_i2c_client(dev);
+ struct si5338_data_t *clientdata= i2c_get_clientdata(client);
+ int adwe,rc=0;
+ int left=count,num_bytes;
+ const char * cp;
+ 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);
+ buf = cp;
+ dev_dbg(dev,"left=%d", left);
......@@ -2348,6 +2404,10 @@ Index: git/drivers/misc/si5338.c
+ p123[2]=1;
+ }
+ 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;
+}
+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
+ }
+ ms_to_p123(ms,p123);
+ 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;
+}
+
......@@ -2401,6 +2465,24 @@ Index: git/drivers/misc/si5338.c
+ 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)
+{
+ int rc;
......@@ -3321,11 +3403,13 @@ Index: git/drivers/misc/si5338.c
+ /* setup MSn division */
+ if (((rc=set_pll_ms_by_out(client, out_freq, chn, int_div)))<0) return rc;
+ /* 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) */
+ if (((rc=set_out_source(client, chn, 6)))<0) return rc;
+ /* 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;
+ /* enable power for selected output */
+ if (((rc=set_drv_powerdown(client, 0, chn)))<0) return rc;
+ return 0; /* all done */
+}
+
......@@ -3379,6 +3463,93 @@ Index: git/drivers/misc/si5338.c
+}
+
+/* -----------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)
+{
+ int rc;
......@@ -3433,6 +3604,7 @@ Index: git/drivers/misc/si5338.c
+ 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) ms_pec, AWE_MS_PEC)))<0) return rc;
+ if (((rc=write_field(client, 3, AWE_PLL_EN)))<0) return rc; /* enable PLL */
+ return 0;
+}
+
......@@ -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_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 int get_ms_powerdown(struct i2c_client *client, int chn)
+{
......@@ -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)
+{
+ int rc;
+ s64 pll_in_freq, pll_in_freq_scaled,pll_out_freq_scaled,d;
+ u32 msn_p123[3];
+ u64 msn[]={0,0,1};
......@@ -3771,9 +3945,15 @@ Index: git/drivers/misc/si5338.c
+ ms_scaled=ms[0]*ms[2]+ms[1];
+ out_freq[1]=pll_freq_scaled*ms[2];
+ out_freq[2]=ms_scaled*pll_out_freq[2];
+ 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]);
+ if (out_freq[2]==0){
+ out_freq[0]=0;
+ 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]);
+ return 0;
+}
......@@ -3852,6 +4032,8 @@ Index: git/drivers/misc/si5338.c
+ /* set up registers */
+ ms_to_p123(ms,p123);
+ 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;
+}
+/* ----------- Input section ----------------- */
......@@ -4229,14 +4411,19 @@ Index: git/drivers/misc/si5338.c
+static int _write_single_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+ 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);
+ if (clientdata && (reg==REG5338_PAGE)) {
+// 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) ){
+ clientdata->cache[reg].data= val;
+ clientdata->cache[reg].flags |= CACHE_INIT;
+ if (clientdata) {
+ if (reg==REG5338_PAGE) {
+ // 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;
+ } else {
+ ireg |=(clientdata->last_page)<<8;
+ }
+ if (ireg<=LAST_REG){
+ clientdata->cache[ireg].data= val;
+ clientdata->cache[ireg].flags |= CACHE_INIT;
+ }
+ }
+ return i2c_smbus_write_byte_data(client, reg, val);
+}
......@@ -4257,6 +4444,7 @@ Index: git/drivers/misc/si5338.c
+ val=((val ^ rc) & mask)^ rc;
+ if ((val==rc) && !(clientdata->cache[reg].flags & CACHE_VOLAT)) {
+ dev_dbg(&client->dev,"No change and not volatile -> no write\n");
+ return 0;
+ }
+ }
+ return _write_single_reg(client, reg & 0xff, val);
......@@ -4294,6 +4482,8 @@ Index: git/drivers/misc/si5338.c
+{
+ // struct device *dev=&client->dev;
+ 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;
+ int len,i,n;
+ u16 page_reg;
......@@ -4308,6 +4498,24 @@ Index: git/drivers/misc/si5338.c
+ struct si5338_setup_data setup_data;
+ __be32 * setup_data_be32= (__be32 *) &setup_data;
+ 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);
+ if (config_data){
+ len /= sizeof(*config_data);
......@@ -4387,11 +4595,25 @@ Index: git/drivers/misc/si5338.c
+ }
+ }
+
+
+ } else {
+ 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,
......@@ -4420,7 +4642,7 @@ Index: git/drivers/misc/si5338.c
+ clientdata->cache[i].data=0;
+ }
+ 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[]
+ 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