2 * Driver for Silicon Labs Si570/Si571 Programmable XO/VCXO
4 * Copyright (C) 2010, 2011 Ericsson AB.
5 * Copyright (C) 2011 Guenter Roeck.
7 * Author: Guenter Roeck <guenter.roeck@ericsson.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
20 #include <linux/module.h>
21 #include <linux/jiffies.h>
22 #include <linux/i2c.h>
23 #include <linux/err.h>
24 #include <linux/mutex.h>
25 #include <linux/delay.h>
26 #include <linux/log2.h>
27 #include <linux/slab.h>
28 #include <linux/of_i2c.h>
29 #include <linux/i2c/si570.h>
32 #define SI570_REG_HS_N1 7
33 #define SI570_REG_N1_RFREQ0 8
34 #define SI570_REG_RFREQ1 9
35 #define SI570_REG_RFREQ2 10
36 #define SI570_REG_RFREQ3 11
37 #define SI570_REG_RFREQ4 12
38 #define SI570_REG_CONTROL 135
39 #define SI570_REG_FREEZE_DCO 137
41 #define HS_DIV_SHIFT 5
42 #define HS_DIV_MASK 0xe0
43 #define HS_DIV_OFFSET 4
44 #define N1_6_2_MASK 0x1f
45 #define N1_1_0_MASK 0xc0
46 #define RFREQ_37_32_MASK 0x3f
48 #define SI570_FOUT_FACTORY_DFLT 156250000LL
49 #define SI598_FOUT_FACTORY_DFLT 10000000LL
51 #define SI570_MIN_FREQ 10000000L
52 #define SI570_MAX_FREQ 1417500000L
53 #define SI598_MAX_FREQ 525000000L
55 #define FDCO_MIN 4850000000LL
56 #define FDCO_MAX 5670000000LL
57 #define FDCO_CENTER ((FDCO_MIN + FDCO_MAX) / 2)
59 #define SI570_CNTRL_RECALL (1 << 0)
60 #define SI570_CNTRL_FREEZE_ADC (1 << 4)
61 #define SI570_CNTRL_FREEZE_M (1 << 5)
62 #define SI570_CNTRL_NEWFREQ (1 << 6)
63 #define SI570_CNTRL_RESET (1 << 7)
65 #define SI570_FREEZE_DCO (1 << 4)
66 #define SI570_UNFREEZE_DCO 0xEF
69 struct attribute_group attrs
;
72 u64 fout
; /* Factory default frequency */
73 u64 fxtal
; /* Factory xtal frequency */
81 static struct i2c_client
*si570_client
;
84 static int si570_get_defaults(struct i2c_client
*client
)
86 struct si570_data
*data
= i2c_get_clientdata(client
);
87 int reg1
, reg2
, reg3
, reg4
, reg5
, reg6
;
90 i2c_smbus_write_byte_data(client
, SI570_REG_CONTROL
,
93 reg1
= i2c_smbus_read_byte_data(client
, SI570_REG_HS_N1
);
96 reg2
= i2c_smbus_read_byte_data(client
, SI570_REG_N1_RFREQ0
);
99 reg3
= i2c_smbus_read_byte_data(client
, SI570_REG_RFREQ1
);
102 reg4
= i2c_smbus_read_byte_data(client
, SI570_REG_RFREQ2
);
105 reg5
= i2c_smbus_read_byte_data(client
, SI570_REG_RFREQ3
);
108 reg6
= i2c_smbus_read_byte_data(client
, SI570_REG_RFREQ4
);
112 data
->hs_div
= ((reg1
& HS_DIV_MASK
) >> HS_DIV_SHIFT
) + HS_DIV_OFFSET
;
113 data
->n1
= ((reg1
& N1_6_2_MASK
) << 2) + ((reg2
& N1_1_0_MASK
) >> 6)
115 /* Handle invalid cases */
119 data
->rfreq
= reg2
& RFREQ_37_32_MASK
;
120 data
->rfreq
= (data
->rfreq
<< 8) + reg3
;
121 data
->rfreq
= (data
->rfreq
<< 8) + reg4
;
122 data
->rfreq
= (data
->rfreq
<< 8) + reg5
;
123 data
->rfreq
= (data
->rfreq
<< 8) + reg6
;
126 * Accept optional precision loss to avoid arithmetic overflows.
127 * Acceptable per Silicon Labs Application Note AN334.
129 fdco
= data
->fout
* data
->n1
* data
->hs_div
;
130 if (fdco
>= (1LL << 36))
131 data
->fxtal
= div64_u64((fdco
<< 24), (data
->rfreq
>> 4));
133 data
->fxtal
= div64_u64((fdco
<< 28), data
->rfreq
);
135 data
->frequency
= data
->fout
;
141 * Update rfreq registers
142 * This function must be called with update mutex lock held.
144 static void si570_update_rfreq(struct i2c_client
*client
,
145 struct si570_data
*data
)
148 status
= i2c_smbus_write_byte_data(client
, SI570_REG_N1_RFREQ0
,
149 ((data
->n1
- 1) << 6)
150 | ((data
->rfreq
>> 32) & RFREQ_37_32_MASK
));
152 dev_err(&client
->dev
,
153 "unable to write 0x%llX to REG_N1_RFREQ0: %d\n",
154 (((data
->n1
- 1) << 6) | ((data
->rfreq
>> 32) &
155 RFREQ_37_32_MASK
)) & 0xff, status
);
156 status
= i2c_smbus_write_byte_data(client
, SI570_REG_RFREQ1
,
157 (data
->rfreq
>> 24) & 0xff);
159 dev_err(&client
->dev
,
160 "unable to write 0x%llX to REG_RFREQ1: %d\n",
161 (data
->rfreq
>> 24) & 0xff, status
);
162 status
= i2c_smbus_write_byte_data(client
, SI570_REG_RFREQ2
,
163 (data
->rfreq
>> 16) & 0xff);
165 dev_err(&client
->dev
,
166 "unable to write 0x%llX to REG_RFREQ2: %d\n",
167 (data
->rfreq
>> 16) & 0xff, status
);
168 status
= i2c_smbus_write_byte_data(client
, SI570_REG_RFREQ3
,
169 (data
->rfreq
>> 8) & 0xff);
171 dev_err(&client
->dev
,
172 "unable to write 0x%llX to REG_RFREQ3: %d\n",
173 (data
->rfreq
>> 8) & 0xff, status
);
174 status
= i2c_smbus_write_byte_data(client
, SI570_REG_RFREQ4
,
177 dev_err(&client
->dev
,
178 "unable to write 0x%llX to REG_RFREQ4: %d\n",
179 data
->rfreq
& 0xff, status
);
183 * Update si570 frequency for small frequency changes (< 3,500 ppm)
184 * This function must be called with update mutex lock held.
186 static int si570_set_frequency_small(struct i2c_client
*client
,
187 struct si570_data
*data
,
188 unsigned long frequency
)
190 data
->frequency
= frequency
;
191 /* This is a re-implementation of DIV_ROUND_CLOSEST
192 * using the div64_u64 function lieu of letting the compiler
195 data
->rfreq
= div64_u64((data
->rfreq
* frequency
) +
196 div64_u64(data
->frequency
, 2), data
->frequency
);
197 i2c_smbus_write_byte_data(client
, SI570_REG_CONTROL
,
198 SI570_CNTRL_FREEZE_M
);
199 si570_update_rfreq(client
, data
);
200 i2c_smbus_write_byte_data(client
, SI570_REG_CONTROL
, 0);
205 const uint8_t si570_hs_div_values
[] = { 11, 9, 7, 6, 5, 4 };
208 * Set si570 frequency.
209 * This function must be called with update mutex lock held.
211 static int si570_set_frequency(struct i2c_client
*client
,
212 struct si570_data
*data
,
213 unsigned long frequency
)
216 u64 fdco
, best_fdco
= ULLONG_MAX
;
218 for (i
= 0; i
< ARRAY_SIZE(si570_hs_div_values
); i
++) {
219 hs_div
= si570_hs_div_values
[i
];
220 /* Calculate lowest possible value for n1 */
221 n1
= div64_u64(div64_u64(FDCO_MIN
, (u64
)hs_div
),
226 fdco
= (u64
)frequency
* (u64
)hs_div
* (u64
)n1
;
229 if (fdco
>= FDCO_MIN
&& fdco
< best_fdco
) {
231 data
->hs_div
= hs_div
;
232 data
->frequency
= frequency
;
233 data
->rfreq
= div64_u64((fdco
<< 28),
237 n1
+= (n1
== 1 ? 1 : 2);
240 if (best_fdco
== ULLONG_MAX
) {
241 dev_err(&client
->dev
, "error - best FDCO is out of range\n");
245 /* The DCO reg should be accessed with a read-modify-write operation
248 i2c_smbus_write_byte_data(client
, SI570_REG_FREEZE_DCO
,
250 i2c_smbus_write_byte_data(client
, SI570_REG_HS_N1
,
251 ((data
->hs_div
- HS_DIV_OFFSET
) <<
253 | (((data
->n1
- 1) >> 2) & N1_6_2_MASK
));
254 si570_update_rfreq(client
, data
);
255 i2c_smbus_write_byte_data(client
, SI570_REG_FREEZE_DCO
,
257 i2c_smbus_write_byte_data(client
, SI570_REG_CONTROL
,
258 SI570_CNTRL_NEWFREQ
);
264 * This function must be called with update mutex lock held.
266 static int si570_reset(struct i2c_client
*client
, struct si570_data
*data
)
268 i2c_smbus_write_byte_data(client
, SI570_REG_CONTROL
,
270 usleep_range(1000, 5000);
271 return si570_set_frequency(client
, data
, data
->frequency
);
274 static ssize_t
show_frequency_attr(struct device
*dev
,
275 struct device_attribute
*devattr
,
278 struct i2c_client
*client
= to_i2c_client(dev
);
279 struct si570_data
*data
= i2c_get_clientdata(client
);
281 return sprintf(buf
, "%llu\n", data
->frequency
);
284 int get_frequency_si570(struct device
*dev
, unsigned long *freq
)
289 if ((!dev
) || (to_i2c_client(dev
) != si570_client
))
292 show_frequency_attr(dev
, NULL
, buf
);
294 err
= strict_strtoul(buf
, 10, freq
);
300 EXPORT_SYMBOL(get_frequency_si570
);
302 static ssize_t
set_frequency_attr(struct device
*dev
,
303 struct device_attribute
*attr
,
304 const char *buf
, size_t count
)
306 struct i2c_client
*client
= to_i2c_client(dev
);
307 struct si570_data
*data
= i2c_get_clientdata(client
);
311 err
= strict_strtoul(buf
, 10, &val
);
315 if (val
< SI570_MIN_FREQ
|| val
> data
->max_freq
) {
316 dev_err(&client
->dev
,
317 "requested frequency %lu Hz is out of range\n", val
);
321 mutex_lock(&data
->lock
);
323 if (div64_u64(abs(val
- data
->frequency
) * 10000LL,
324 data
->frequency
) < 35)
325 err
= si570_set_frequency_small(client
, data
, val
);
327 err
= si570_set_frequency(client
, data
, val
);
328 mutex_unlock(&data
->lock
);
330 dev_warn(&client
->dev
,
331 "unable to set output frequency %lu Hz: %d\n",
336 dev_info(&client
->dev
,
337 "set new output frequency %lu Hz\n", val
);
342 int set_frequency_si570(struct device
*dev
, unsigned long freq
)
346 if ((!dev
) || (to_i2c_client(dev
) != si570_client
))
349 sprintf(buf
, "%lu", freq
);
351 return set_frequency_attr(dev
, NULL
, buf
, 0);
353 EXPORT_SYMBOL(set_frequency_si570
);
355 static ssize_t
show_reset_attr(struct device
*dev
,
356 struct device_attribute
*devattr
,
359 return sprintf(buf
, "%d\n", 0);
362 static ssize_t
set_reset_attr(struct device
*dev
,
363 struct device_attribute
*attr
,
364 const char *buf
, size_t count
)
366 struct i2c_client
*client
= to_i2c_client(dev
);
367 struct si570_data
*data
= i2c_get_clientdata(client
);
371 err
= strict_strtoul(buf
, 10, &val
);
377 mutex_lock(&data
->lock
);
378 err
= si570_reset(client
, data
);
379 mutex_unlock(&data
->lock
);
386 int reset_si570(struct device
*dev
, int id
)
390 if ((!dev
) || (to_i2c_client(dev
) != si570_client
))
393 sprintf(buf
, "%lu", (unsigned long)id
);
394 return set_reset_attr(dev
, NULL
, buf
, 0);
396 EXPORT_SYMBOL(reset_si570
);
398 struct i2c_client
*get_i2c_client_si570(void)
402 EXPORT_SYMBOL(get_i2c_client_si570
);
404 static DEVICE_ATTR(frequency
, S_IWUSR
| S_IRUGO
, show_frequency_attr
, set_frequency_attr
);
405 static DEVICE_ATTR(reset
, S_IWUSR
| S_IRUGO
, show_reset_attr
, set_reset_attr
);
407 static struct attribute
*si570_attr
[] = {
408 &dev_attr_frequency
.attr
,
409 &dev_attr_reset
.attr
,
413 static const struct i2c_device_id si570_id
[] = {
420 MODULE_DEVICE_TABLE(i2c
, si570_id
);
422 static int si570_probe(struct i2c_client
*client
,
423 const struct i2c_device_id
*id
)
425 struct si570_platform_data
*pdata
= client
->dev
.platform_data
;
426 struct si570_data
*data
;
428 unsigned long initial_fout
;
430 data
= kzalloc(sizeof(struct si570_data
), GFP_KERNEL
);
436 if (id
->driver_data
) {
437 data
->fout
= SI598_FOUT_FACTORY_DFLT
;
438 data
->max_freq
= SI598_MAX_FREQ
;
440 data
->fout
= SI570_FOUT_FACTORY_DFLT
;
441 data
->max_freq
= SI570_MAX_FREQ
;
444 if (pdata
&& pdata
->factory_fout
)
445 data
->fout
= pdata
->factory_fout
;
447 if (client
->dev
.of_node
&&
448 (of_property_read_u64(client
->dev
.of_node
, "factory-fout",
450 dev_warn(&client
->dev
,
451 "DTS does not contain factory-fout, using default\n");
454 i2c_set_clientdata(client
, data
);
455 err
= si570_get_defaults(client
);
459 mutex_init(&data
->lock
);
461 /* Register sysfs hooks */
462 data
->attrs
.attrs
= si570_attr
;
463 err
= sysfs_create_group(&client
->dev
.kobj
, &data
->attrs
);
467 /* Display a message indicating that we've successfully registered */
468 dev_info(&client
->dev
,
469 "registered %s with default frequency %llu Hz\n",
470 id
->name
, data
->fout
);
472 /* Read the requested initial fout from either platform data or the
476 if (pdata
&& pdata
->initial_fout
) {
477 initial_fout
= pdata
->initial_fout
;
479 if (client
->dev
.of_node
) {
480 of_property_read_u32(client
->dev
.of_node
, "initial-fout",
481 (u32
*)&initial_fout
);
482 if (pdata
&& pdata
->initial_fout
&&
483 (pdata
->initial_fout
!= initial_fout
)) {
484 dev_warn(&client
->dev
,
485 "OF initial fout %lu overrides platform data fout %lu\n",
487 pdata
->initial_fout
);
491 if (initial_fout
!= 0) {
492 if (initial_fout
< SI570_MIN_FREQ
||
493 initial_fout
> data
->max_freq
) {
494 dev_err(&client
->dev
,
495 "requested initial frequency %lu is out of range, using default\n",
500 mutex_lock(&data
->lock
);
502 if (div64_u64(abs(initial_fout
- data
->frequency
) *
503 10000LL, data
->frequency
) < 35)
504 err
= si570_set_frequency_small(client
, data
,
507 err
= si570_set_frequency(client
, data
,
509 mutex_unlock(&data
->lock
);
511 dev_warn(&client
->dev
,
512 "unable to set initial output frequency %lu: %d\n",
517 dev_info(&client
->dev
,
518 "set initial output frequency %lu Hz\n",
522 si570_client
= client
;
532 static int si570_remove(struct i2c_client
*client
)
534 struct si570_data
*data
= i2c_get_clientdata(client
);
536 sysfs_remove_group(&client
->dev
.kobj
, &data
->attrs
);
542 static const struct of_device_id i2c_si570_of_match
[] = {
543 { .compatible
= "si570" },
546 MODULE_DEVICE_TABLE(of
, i2c_si570_of_match
);
549 static struct i2c_driver si570_driver
= {
552 .of_match_table
= of_match_ptr(i2c_si570_of_match
),
554 .probe
= si570_probe
,
555 .remove
= si570_remove
,
556 .id_table
= si570_id
,
559 static int __init
si570_init(void)
561 return i2c_add_driver(&si570_driver
);
564 static void __exit
si570_exit(void)
566 i2c_del_driver(&si570_driver
);
569 MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
570 MODULE_DESCRIPTION("Si570 driver");
571 MODULE_LICENSE("GPL");
573 module_init(si570_init
);
574 module_exit(si570_exit
);