aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorMylène Josserand <mylene.josserand@free-electrons.com>2016-03-21 13:06:09 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-03-24 21:41:13 -0400
commit59a8383adb75459c9d6766656bccc05950b783ea (patch)
tree1e05f7f7883155af28e9bc43b76cefcd0f8a083a /drivers/rtc
parent85062c9b990b1dc8bbb8971ee7d3044a999cf25f (diff)
rtc: abx80x: handle autocalibration
The autocalibration is separated in two bits to set in Oscillator Control register (0x1c) : - OSEL bit to select the oscillator type (XT or RC). - ACAL bit to select the autocalibration type. These functionnalities are exported in sysfs entries : "oscillator" and "autocalibration". Respectively, the values are "xtal" for XT oscillator and "rc" for RC oscillator and 0 to disable the autocalibration cycle, 512 for a 512 seconds autocalibration cycle and 1024 for a cycle of 1024 seconds. Examples : Set to XT Oscillator echo xtal > /sys/class/rtc/rtc0/device/oscillator Activate an autocalibration every 512 seconds echo 512 > /sys/class/rtc/rtc0/device/autocalibration Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-abx80x.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index d41bbcd653f6..0e4c9a0989d1 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -49,7 +49,19 @@
49 49
50#define ABX8XX_REG_CD_TIMER_CTL 0x18 50#define ABX8XX_REG_CD_TIMER_CTL 0x18
51 51
52#define ABX8XX_REG_OSC 0x1c
53#define ABX8XX_OSC_FOS BIT(3)
54#define ABX8XX_OSC_BOS BIT(4)
55#define ABX8XX_OSC_ACAL_512 BIT(5)
56#define ABX8XX_OSC_ACAL_1024 BIT(6)
57
58#define ABX8XX_OSC_OSEL BIT(7)
59
60#define ABX8XX_REG_OSS 0x1d
61#define ABX8XX_OSS_OMODE BIT(4)
62
52#define ABX8XX_REG_CFG_KEY 0x1f 63#define ABX8XX_REG_CFG_KEY 0x1f
64#define ABX8XX_CFG_KEY_OSC 0xa1
53#define ABX8XX_CFG_KEY_MISC 0x9d 65#define ABX8XX_CFG_KEY_MISC 0x9d
54 66
55#define ABX8XX_REG_ID0 0x28 67#define ABX8XX_REG_ID0 0x28
@@ -81,6 +93,20 @@ static struct abx80x_cap abx80x_caps[] = {
81 [ABX80X] = {.pn = 0} 93 [ABX80X] = {.pn = 0}
82}; 94};
83 95
96static int abx80x_is_rc_mode(struct i2c_client *client)
97{
98 int flags = 0;
99
100 flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSS);
101 if (flags < 0) {
102 dev_err(&client->dev,
103 "Failed to read autocalibration attribute\n");
104 return flags;
105 }
106
107 return (flags & ABX8XX_OSS_OMODE) ? 1 : 0;
108}
109
84static int abx80x_enable_trickle_charger(struct i2c_client *client, 110static int abx80x_enable_trickle_charger(struct i2c_client *client,
85 u8 trickle_cfg) 111 u8 trickle_cfg)
86{ 112{
@@ -248,6 +274,174 @@ static int abx80x_set_alarm(struct device *dev, struct rtc_wkalrm *t)
248 return 0; 274 return 0;
249} 275}
250 276
277static int abx80x_rtc_set_autocalibration(struct device *dev,
278 int autocalibration)
279{
280 struct i2c_client *client = to_i2c_client(dev);
281 int retval, flags = 0;
282
283 if ((autocalibration != 0) && (autocalibration != 1024) &&
284 (autocalibration != 512)) {
285 dev_err(dev, "autocalibration value outside permitted range\n");
286 return -EINVAL;
287 }
288
289 flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC);
290 if (flags < 0)
291 return flags;
292
293 if (autocalibration == 0) {
294 flags &= ~(ABX8XX_OSC_ACAL_512 | ABX8XX_OSC_ACAL_1024);
295 } else if (autocalibration == 1024) {
296 /* 1024 autocalibration is 0x10 */
297 flags |= ABX8XX_OSC_ACAL_1024;
298 flags &= ~(ABX8XX_OSC_ACAL_512);
299 } else {
300 /* 512 autocalibration is 0x11 */
301 flags |= (ABX8XX_OSC_ACAL_1024 | ABX8XX_OSC_ACAL_512);
302 }
303
304 /* Unlock write access to Oscillator Control Register */
305 retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
306 ABX8XX_CFG_KEY_OSC);
307 if (retval < 0) {
308 dev_err(dev, "Failed to write CONFIG_KEY register\n");
309 return retval;
310 }
311
312 retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSC, flags);
313
314 return retval;
315}
316
317static int abx80x_rtc_get_autocalibration(struct device *dev)
318{
319 struct i2c_client *client = to_i2c_client(dev);
320 int flags = 0, autocalibration;
321
322 flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC);
323 if (flags < 0)
324 return flags;
325
326 if (flags & ABX8XX_OSC_ACAL_512)
327 autocalibration = 512;
328 else if (flags & ABX8XX_OSC_ACAL_1024)
329 autocalibration = 1024;
330 else
331 autocalibration = 0;
332
333 return autocalibration;
334}
335
336static ssize_t autocalibration_store(struct device *dev,
337 struct device_attribute *attr,
338 const char *buf, size_t count)
339{
340 int retval;
341 unsigned long autocalibration = 0;
342
343 retval = kstrtoul(buf, 10, &autocalibration);
344 if (retval < 0) {
345 dev_err(dev, "Failed to store RTC autocalibration attribute\n");
346 return -EINVAL;
347 }
348
349 retval = abx80x_rtc_set_autocalibration(dev, autocalibration);
350
351 return retval ? retval : count;
352}
353
354static ssize_t autocalibration_show(struct device *dev,
355 struct device_attribute *attr, char *buf)
356{
357 int autocalibration = 0;
358
359 autocalibration = abx80x_rtc_get_autocalibration(dev);
360 if (autocalibration < 0) {
361 dev_err(dev, "Failed to read RTC autocalibration\n");
362 sprintf(buf, "0\n");
363 return autocalibration;
364 }
365
366 return sprintf(buf, "%d\n", autocalibration);
367}
368
369static DEVICE_ATTR_RW(autocalibration);
370
371static ssize_t oscillator_store(struct device *dev,
372 struct device_attribute *attr,
373 const char *buf, size_t count)
374{
375 struct i2c_client *client = to_i2c_client(dev);
376 int retval, flags, rc_mode = 0;
377
378 if (strncmp(buf, "rc", 2) == 0) {
379 rc_mode = 1;
380 } else if (strncmp(buf, "xtal", 4) == 0) {
381 rc_mode = 0;
382 } else {
383 dev_err(dev, "Oscillator selection value outside permitted ones\n");
384 return -EINVAL;
385 }
386
387 flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC);
388 if (flags < 0)
389 return flags;
390
391 if (rc_mode == 0)
392 flags &= ~(ABX8XX_OSC_OSEL);
393 else
394 flags |= (ABX8XX_OSC_OSEL);
395
396 /* Unlock write access on Oscillator Control register */
397 retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
398 ABX8XX_CFG_KEY_OSC);
399 if (retval < 0) {
400 dev_err(dev, "Failed to write CONFIG_KEY register\n");
401 return retval;
402 }
403
404 retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSC, flags);
405 if (retval < 0) {
406 dev_err(dev, "Failed to write Oscillator Control register\n");
407 return retval;
408 }
409
410 return retval ? retval : count;
411}
412
413static ssize_t oscillator_show(struct device *dev,
414 struct device_attribute *attr, char *buf)
415{
416 int rc_mode = 0;
417 struct i2c_client *client = to_i2c_client(dev);
418
419 rc_mode = abx80x_is_rc_mode(client);
420
421 if (rc_mode < 0) {
422 dev_err(dev, "Failed to read RTC oscillator selection\n");
423 sprintf(buf, "\n");
424 return rc_mode;
425 }
426
427 if (rc_mode)
428 return sprintf(buf, "rc\n");
429 else
430 return sprintf(buf, "xtal\n");
431}
432
433static DEVICE_ATTR_RW(oscillator);
434
435static struct attribute *rtc_calib_attrs[] = {
436 &dev_attr_autocalibration.attr,
437 &dev_attr_oscillator.attr,
438 NULL,
439};
440
441static const struct attribute_group rtc_calib_attr_group = {
442 .attrs = rtc_calib_attrs,
443};
444
251static int abx80x_alarm_irq_enable(struct device *dev, unsigned int enabled) 445static int abx80x_alarm_irq_enable(struct device *dev, unsigned int enabled)
252{ 446{
253 struct i2c_client *client = to_i2c_client(dev); 447 struct i2c_client *client = to_i2c_client(dev);
@@ -303,6 +497,13 @@ static int abx80x_dt_trickle_cfg(struct device_node *np)
303 return (trickle_cfg | i); 497 return (trickle_cfg | i);
304} 498}
305 499
500static void rtc_calib_remove_sysfs_group(void *_dev)
501{
502 struct device *dev = _dev;
503
504 sysfs_remove_group(&dev->kobj, &rtc_calib_attr_group);
505}
506
306static int abx80x_probe(struct i2c_client *client, 507static int abx80x_probe(struct i2c_client *client,
307 const struct i2c_device_id *id) 508 const struct i2c_device_id *id)
308{ 509{
@@ -405,6 +606,24 @@ static int abx80x_probe(struct i2c_client *client,
405 } 606 }
406 } 607 }
407 608
609 /* Export sysfs entries */
610 err = sysfs_create_group(&(&client->dev)->kobj, &rtc_calib_attr_group);
611 if (err) {
612 dev_err(&client->dev, "Failed to create sysfs group: %d\n",
613 err);
614 return err;
615 }
616
617 err = devm_add_action(&client->dev, rtc_calib_remove_sysfs_group,
618 &client->dev);
619 if (err) {
620 rtc_calib_remove_sysfs_group(&client->dev);
621 dev_err(&client->dev,
622 "Failed to add sysfs cleanup action: %d\n",
623 err);
624 return err;
625 }
626
408 return 0; 627 return 0;
409} 628}
410 629