source: rtems/c/src/lib/libbsp/arm/altera-cyclone-v/rtc/rtc.c @ a1d6f7a

4.11
Last change on this file since a1d6f7a was a1d6f7a, checked in by Thomas Volgmann <Thomas.Volgmann@…>, on Apr 10, 2015 at 6:23:00 AM

bsp/altera-cyclone-v: Add RTC driver

  • Property mode set to 100644
File size: 18.8 KB
Line 
1/*
2 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <info@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15/*
16 * Driver for the DS1339 RTC (Maxim Semiconductors) -> RTC1
17 *        and the M41ST87 RTC (ST Microelectronics) -> RTC2
18 *
19 * Please note the following points:
20 * - The day of week is ignored.
21 * - The century bit is interpreted the following way:
22 *   - century not set: TOD_BASE_YEAR .. 1999
23 *   - century set: 2000 .. 2099
24 *   - century not set: 2100 .. (TOD_BASE_YEAR + 200)
25 */
26
27#include <libchip/rtc.h>
28#include <assert.h>
29#include <rtems/score/todimpl.h>
30#include <sys/filio.h>
31#include <fcntl.h>
32#include <unistd.h>
33#include <bsp/i2cdrv.h>
34
35#define ALTERA_CYCLONE_V_RTC_NUMBER  2
36
37
38/* ******************************* DS1339 ********************************** */
39
40
41#define DS1339_I2C_ADDRESS     (0xD0 >> 1)  /* 7-bit addressing! */
42#define DS1339_I2C_BUS_DEVICE  "/dev/i2c0"
43
44#define DS1339_ADDR_TIME    0x00
45
46#define DS1339_ADDR_CTRL   0x0E
47#define   DS1339_CTRL_EOSC   0x80
48#define   DS1339_CTRL_BBSQI  0x20
49#define   DS1339_CTRL_RS2    0x10
50#define   DS1339_CTRL_RS1    0x08
51#define   DS1339_CTRL_INTCN  0x04
52#define   DS1339_CTRL_A2IE   0x02
53#define   DS1339_CTRL_A1IE   0x01
54
55#define DS1339_CTRL_DEFAULT  (0x00)
56
57#define DS1339_ADDR_STATUS  0x0F
58#define   DS1339_STATUS_OSF   0x80
59#define   DS1339_STATUS_A2F   0x02
60#define   DS1339_STATUS_A1F   0x01
61
62#define DS1339_STATUS_CLEAR  (0x00)
63
64#define DS1339_ADDR_TRICKLE_CHARGE  0x10
65
66
67typedef struct
68{
69  uint8_t  seconds;
70  uint8_t  minutes;
71  uint8_t  hours;
72#define DS1339_HOURS_12_24_FLAG 0x40
73#define DS1339_HOURS_AM_PM_FLAG_OR_20_HOURS 0x20
74#define DS1339_HOURS_10_HOURS 0x10
75  uint8_t  weekday;
76  uint8_t  date;
77  uint8_t  month;
78#define DS1339_MONTH_CENTURY 0x80
79  uint8_t  year;
80}
81ds1339_time_t;
82
83
84/* The longest write transmission is writing the time + one address bit */
85#define DS1339_MAX_WRITE_SIZE  (sizeof(ds1339_time_t) + 1)
86
87
88/* Functions for converting the fields */
89static unsigned int  ds1339_get_seconds(ds1339_time_t* time)
90{
91  uint8_t  tens = time->seconds >> 4;
92  uint8_t  ones = time->seconds & 0x0F;
93
94  return tens * 10 + ones;
95}
96
97
98static unsigned int  ds1339_get_minutes(ds1339_time_t* time)
99{
100  uint8_t  tens = time->minutes >> 4;
101  uint8_t  ones = time->minutes & 0x0F;
102
103  return tens * 10 + ones;
104}
105
106
107static unsigned int  ds1339_get_hours(ds1339_time_t* time)
108{
109
110  uint8_t  value = time->hours & 0x0F;
111
112  if (time->hours & DS1339_HOURS_10_HOURS)
113  {
114    value += 10;
115  }
116  if (time->hours & DS1339_HOURS_AM_PM_FLAG_OR_20_HOURS)
117  {
118    if (time->hours & DS1339_HOURS_12_24_FLAG)
119      value += 12;
120    else
121      value += 20;
122  }
123
124  return value;
125}
126
127
128static unsigned int  ds1339_get_day_of_month(ds1339_time_t* time)
129{
130
131  uint8_t  tens = time->date >> 4;
132  uint8_t  ones = time->date & 0x0F;
133
134  return tens * 10 + ones;
135}
136
137
138static unsigned int  ds1339_get_month(ds1339_time_t* time)
139{
140
141  uint8_t  tens = (time->month >> 4) & 0x07;
142  uint8_t  ones = time->month & 0x0F;
143
144  return tens * 10 + ones;
145}
146
147
148static unsigned int  ds1339_get_year(ds1339_time_t* time)
149{
150
151  unsigned int  year = 1900;
152
153  year += (time->year >> 4) * 10;
154  year += time->year & 0x0F;
155  if (time->month & DS1339_MONTH_CENTURY)
156    year += 100;
157  if (year < TOD_BASE_YEAR)
158    year += 200;
159
160  return year;
161}
162
163
164static void  ds1339_set_time(ds1339_time_t* time,
165                             unsigned int second,
166                             unsigned int minute,
167                             unsigned int hour,
168                             unsigned int day,
169                             unsigned int month,
170                             unsigned int year)
171{
172
173  unsigned int  tens;
174  unsigned int  ones;
175  uint8_t       century = 0;
176
177  tens = second / 10;
178  ones = second % 10;
179  time->seconds = tens << 4 | ones;
180
181  tens = minute / 10;
182  ones = minute % 10;
183  time->minutes = tens << 4 | ones;
184
185  tens = hour / 10;
186  ones = hour % 10;
187  time->hours = tens << 4 | ones;
188
189  /* Weekday is not used. Therefore it can be set to an arbitrary valid value */
190  time->weekday = 1;
191
192  tens = day / 10;
193  ones = day % 10;
194  time->date = tens << 4 | ones;
195
196  tens = month / 10;
197  ones = month % 10;
198  if ((year >= 2000) && (year < 2100))
199    century = DS1339_MONTH_CENTURY;
200  time->month = century | tens << 4 | ones;
201
202  tens = (year % 100) / 10;
203  ones = year % 10;
204  time->year = tens << 4 | ones;
205
206}
207
208
209
210static rtems_status_code  ds1339_open_file(int* fd)
211{
212
213  int                rv = 0;
214  rtems_status_code  sc = RTEMS_SUCCESSFUL;
215
216  *fd = open(DS1339_I2C_BUS_DEVICE, O_RDWR);
217  if (*fd == -1)
218    sc = RTEMS_IO_ERROR;
219
220  if (sc == RTEMS_SUCCESSFUL)
221  {
222    rv = ioctl(*fd, I2C_IOC_SET_SLAVE_ADDRESS, DS1339_I2C_ADDRESS);
223    if (rv == -1)
224      sc = RTEMS_IO_ERROR;
225  }
226
227  return sc;
228}
229
230
231/* Read size bytes from ds1339 register address addr to buf. */
232static rtems_status_code  ds1339_read(uint8_t addr, void* buf, size_t size)
233{
234
235  int                fd = -1;
236  int                rv = 0;
237  rtems_status_code  sc = RTEMS_SUCCESSFUL;
238
239  sc = ds1339_open_file(&fd);
240
241  if (sc == RTEMS_SUCCESSFUL)
242  {
243    rv = write(fd, &addr, sizeof(addr));
244    if (rv != sizeof(addr))
245      sc = RTEMS_IO_ERROR;
246  }
247
248  if (sc == RTEMS_SUCCESSFUL)
249  {
250    rv = read(fd, buf, size);
251    if (rv != size)
252      sc = RTEMS_IO_ERROR;
253  }
254
255  rv = close(fd);
256  if (rv != 0)
257    sc = RTEMS_IO_ERROR;
258
259  return sc;
260}
261
262
263/* Write size bytes from buf to ds1339 register address addr. */
264static rtems_status_code  ds1339_write(uint8_t addr, void* buf, size_t size)
265{
266
267  int                fd = -1;
268  int                rv = 0;
269  rtems_status_code  sc = RTEMS_SUCCESSFUL;
270  /* The driver never writes many bytes. Therefore it should be less expensive
271   * to reserve the maximum number of bytes that will be written in one go than
272   * use a malloc. */
273  uint8_t            local_buf[DS1339_MAX_WRITE_SIZE];
274  int                write_size = size + 1;
275
276  assert(write_size <= DS1339_MAX_WRITE_SIZE);
277
278  local_buf[0] = addr;
279  memcpy(&local_buf[1], buf, size);
280
281  sc = ds1339_open_file(&fd);
282
283  if (sc == RTEMS_SUCCESSFUL)
284  {
285    rv = write(fd, local_buf, write_size);
286    if (rv != write_size)
287      sc = RTEMS_IO_ERROR;
288  }
289
290  rv = close(fd);
291  if (rv != 0)
292    sc = RTEMS_IO_ERROR;
293
294  return RTEMS_SUCCESSFUL;
295}
296
297
298static void altera_cyclone_v_ds1339_initialize(int minor)
299{
300
301  rtems_status_code  sc = RTEMS_SUCCESSFUL;
302  uint8_t            status = 0;
303
304  /* Check RTC valid */
305  sc = ds1339_read(DS1339_ADDR_STATUS, &status, sizeof(status));
306  assert(sc == RTEMS_SUCCESSFUL);
307
308  if (status & DS1339_STATUS_OSF)
309  {
310    /* RTC has been stopped. Initialise it. */
311    ds1339_time_t time;
312
313    uint8_t  write = DS1339_CTRL_DEFAULT;
314    sc = ds1339_write(DS1339_ADDR_CTRL, &write, sizeof(write));
315    assert(sc == RTEMS_SUCCESSFUL);
316
317    write = DS1339_STATUS_CLEAR;
318    sc = ds1339_write(DS1339_ADDR_STATUS, &write, sizeof(write));
319    assert(sc == RTEMS_SUCCESSFUL);
320
321    ds1339_set_time(&time, 0, 0, 0, 1, 1, TOD_BASE_YEAR);
322    sc = ds1339_write(DS1339_ADDR_TIME, &time, sizeof(time));
323    assert(sc == RTEMS_SUCCESSFUL);
324  }
325
326}
327
328
329static int altera_cyclone_v_ds1339_get_time(int minor, rtems_time_of_day* tod)
330{
331
332  ds1339_time_t      time;
333  rtems_status_code  sc = RTEMS_SUCCESSFUL;
334  rtems_time_of_day  temp_tod;
335
336  sc = ds1339_read(DS1339_ADDR_TIME, &time, sizeof(time));
337
338  if (sc == RTEMS_SUCCESSFUL)
339  {
340    temp_tod.ticks  = 0;
341    temp_tod.second = ds1339_get_seconds(&time);
342    temp_tod.minute = ds1339_get_minutes(&time);
343    temp_tod.hour   = ds1339_get_hours(&time);
344    temp_tod.day    = ds1339_get_day_of_month(&time);
345    temp_tod.month  = ds1339_get_month(&time);
346    temp_tod.year   = ds1339_get_year(&time);
347
348    if (_TOD_Validate(&temp_tod))
349      memcpy(tod, &temp_tod, sizeof(temp_tod));
350    else
351      sc = RTEMS_INVALID_CLOCK;
352  }
353
354  return -sc;
355}
356
357
358static int  altera_cyclone_v_ds1339_set_time(int minor, const rtems_time_of_day* tod)
359{
360
361  ds1339_time_t      time;
362  rtems_status_code  sc = RTEMS_SUCCESSFUL;
363
364  ds1339_set_time(&time,
365                  tod->second,
366                  tod->minute,
367                  tod->hour,
368                  tod->day,
369                  tod->month,
370                  tod->year
371                 );
372
373  sc = ds1339_write(DS1339_ADDR_TIME, &time, sizeof(time));
374
375  return -sc;
376}
377
378
379static bool  altera_cyclone_v_ds1339_probe(int minor)
380{
381
382  rtems_status_code  sc = RTEMS_SUCCESSFUL;
383  uint8_t            buf;
384
385  /* try to read from register address 0x00 */
386  sc = ds1339_read(0x00, &buf, 1);
387  if (sc != RTEMS_SUCCESSFUL)
388    /* no RTC implemented */
389    return false;
390  /* try to read from register address 0x20 (not implemented in DS1339) */
391  sc = ds1339_read(0x20, &buf, 1);
392  if (sc == RTEMS_SUCCESSFUL)
393    /* RTC is not DS1339 */
394    return false;
395
396  printk("RTC detected, type = DS1339\n");
397  return true;
398
399}
400
401
402/* ******************************* M41ST87 ********************************** */
403
404
405#define M41ST87_I2C_ADDRESS       (0xD0 >> 1)  /* 7-bit addressing! */
406#define M41ST87_I2C_BUS_DEVICE    "/dev/i2c0"
407
408#define M41ST87_ADDR_TIME         0x00
409
410#define M41ST87_ADDR_CTRL         0x08
411#define   M41ST87_CTRL_OUT          0x80
412#define   M41ST87_CTRL_FT           0x40
413#define   M41ST87_CTRL_S            0x20
414#define   M41ST87_CTRL_CAL          0x1F
415
416#define M41ST87_ADDR_ALARM_HOUR   0x0C
417#define   M41ST87_BIT_HT            0x40
418
419#define M41ST87_ADDR_FLAGS        0x0F
420#define   M41ST87_FLAG_WDF          0x80
421#define   M41ST87_FLAG_AF           0x40
422#define   M41ST87_FLAG_BL           0x10
423#define   M41ST87_FLAG_OF           0x04
424#define   M41ST87_FLAG_TB1          0x02
425#define   M41ST87_FLAG_TB2          0x01
426
427#define M41ST87_ADDR_USER_RAM     0x20
428
429
430typedef struct
431{
432  uint8_t  sec100;
433  uint8_t  seconds;
434#define M41ST87_BIT_ST          0x80
435  uint8_t  minutes;
436#define M41ST87_BIT_OFIE        0x80
437  uint8_t  hours;
438#define M41ST87_BIT_CB1         0x80
439#define M41ST87_BIT_CB0         0x40
440  uint8_t  weekday;
441#define M41ST87_BIT_TR          0x80
442#define M41ST87_BIT_THS         0x40
443#define M41ST87_BIT_CLRPW1      0x20
444#define M41ST87_BIT_CLRPW0      0x10
445#define M41ST87_BIT_32KE        0x08
446  uint8_t  day;
447#define M41ST87_BIT_PFOD        0x80
448  uint8_t  month;
449  uint8_t  year;
450}
451m41st87_time_t;
452
453
454/* The longest write transmission is writing the time + one address bit */
455#define M41ST87_MAX_WRITE_SIZE  (sizeof(m41st87_time_t) + 1)
456
457
458/* Functions for converting the fields */
459
460/*
461static unsigned int  m41st87_get_sec100(m41st87_time_t* time)
462{
463
464  uint8_t  tens = time->sec100 >> 4;
465  uint8_t  ones = time->sec100 & 0x0F;
466
467  return tens * 10 + ones;
468}
469*/
470
471
472static unsigned int  m41st87_get_seconds(m41st87_time_t* time)
473{
474
475  uint8_t  tens = (time->seconds >> 4) & 0x07;
476  uint8_t  ones = time->seconds & 0x0F;
477
478  return tens * 10 + ones;
479}
480
481
482static unsigned int  m41st87_get_minutes(m41st87_time_t* time)
483{
484
485  uint8_t  tens = (time->minutes >> 4) & 0x07;
486  uint8_t  ones = time->minutes & 0x0F;
487
488  return tens * 10 + ones;
489}
490
491
492static unsigned int  m41st87_get_hours(m41st87_time_t* time)
493{
494
495  uint8_t  tens = (time->hours >> 4) & 0x03;
496  uint8_t  ones = time->hours & 0x0F;
497
498  return tens * 10 + ones;
499}
500
501
502/*
503static unsigned int  m41st87_get_day_of_week(m41st87_time_t* time)
504{
505
506  return time->weekday & 0x07;
507}
508*/
509
510
511static unsigned int  m41st87_get_day_of_month(m41st87_time_t* time)
512{
513
514  uint8_t  tens = (time->day >> 4) & 0x03;
515  uint8_t  ones = time->day & 0x0F;
516
517  return tens * 10 + ones;
518}
519
520
521static unsigned int  m41st87_get_month(m41st87_time_t* time)
522{
523
524  uint8_t  tens = (time->month >> 4) & 0x01;
525  uint8_t  ones = time->month & 0x0F;
526
527  return tens * 10 + ones;
528}
529
530
531static unsigned int  m41st87_get_year(m41st87_time_t* time)
532{
533
534  uint8_t  century = time->hours >> 6;
535  uint8_t  tens    = time->year >> 4;
536  uint8_t  ones    = time->year & 0x0F;
537
538  return 1900 + century * 100 + tens * 10 + ones;
539}
540
541
542static void  m41st87_set_time(m41st87_time_t* time,
543                              unsigned int second,
544                              unsigned int minute,
545                              unsigned int hour,
546                              unsigned int day,
547                              unsigned int month,
548                              unsigned int year)
549{
550
551  unsigned int  century;
552  unsigned int  tens;
553  unsigned int  ones;
554
555  if (year < 1900)
556    year = 1900;
557  if (year > 2399)
558    year = 2399;
559  century = (year - 1900) / 100;
560
561  /* Hundreds of seconds is not used, set to 0 */
562  time->sec100 = 0;
563
564  tens = second / 10;
565  ones = second % 10;
566  time->seconds = (time->seconds & 0x80) | (tens << 4) | ones;
567
568  tens = minute / 10;
569  ones = minute % 10;
570  time->minutes = (time->minutes & 0x80) | (tens << 4) | ones;
571
572  tens = hour / 10;
573  ones = hour % 10;
574  time->hours = (century << 6) | (tens << 4) | ones;
575
576  /* Weekday is not used. Therefore it can be set to an arbitrary valid value */
577  time->weekday = (time->weekday & 0xF8) | 1;
578
579  tens = day / 10;
580  ones = day % 10;
581  time->day = (time->day & 0x80) | (tens << 4) | ones;
582
583  tens = month / 10;
584  ones = month % 10;
585  time->month = (tens << 4) | ones;
586
587  tens = (year % 100) / 10;
588  ones = year % 10;
589  time->year = (tens << 4) | ones;
590
591}
592
593
594
595static rtems_status_code  m41st87_open_file(int* fd)
596{
597
598  int                rv = 0;
599  rtems_status_code  sc = RTEMS_SUCCESSFUL;
600
601  *fd = open(M41ST87_I2C_BUS_DEVICE, O_RDWR);
602  if (*fd == -1)
603    sc = RTEMS_IO_ERROR;
604
605  if (sc == RTEMS_SUCCESSFUL)
606  {
607    rv = ioctl(*fd, I2C_IOC_SET_SLAVE_ADDRESS, M41ST87_I2C_ADDRESS);
608    if (rv == -1)
609      sc = RTEMS_IO_ERROR;
610  }
611
612  return sc;
613}
614
615
616/* Read size bytes from m41st87 register address addr to buf. */
617static rtems_status_code  m41st87_read(uint8_t addr, void* buf, size_t size)
618{
619
620  int                fd = -1;
621  int                rv = 0;
622  rtems_status_code  sc = RTEMS_SUCCESSFUL;
623
624  sc = m41st87_open_file(&fd);
625
626  if (sc == RTEMS_SUCCESSFUL)
627  {
628    rv = write(fd, &addr, sizeof(addr));
629    if (rv != sizeof(addr))
630      sc = RTEMS_IO_ERROR;
631  }
632
633  if (sc == RTEMS_SUCCESSFUL)
634  {
635    rv = read(fd, buf, size);
636    if (rv != size)
637      sc = RTEMS_IO_ERROR;
638  }
639
640  rv = close(fd);
641  if (rv != 0)
642    sc = RTEMS_IO_ERROR;
643
644  return sc;
645}
646
647
648/* Write size bytes from buf to m41st87 register address addr. */
649static rtems_status_code  m41st87_write(uint8_t addr, void* buf, size_t size)
650{
651
652  int                fd = -1;
653  int                rv = 0;
654  rtems_status_code  sc = RTEMS_SUCCESSFUL;
655  /* The driver never writes many bytes. Therefore it should be less expensive
656   * to reserve the maximum number of bytes that will be written in one go than
657   * use a malloc. */
658  uint8_t            local_buf[M41ST87_MAX_WRITE_SIZE];
659  int                write_size = size + 1;
660
661  assert(write_size <= M41ST87_MAX_WRITE_SIZE);
662
663  local_buf[0] = addr;
664  memcpy(&local_buf[1], buf, size);
665
666  sc = m41st87_open_file(&fd);
667
668  if (sc == RTEMS_SUCCESSFUL)
669  {
670    rv = write(fd, local_buf, write_size);
671    if (rv != write_size)
672      sc = RTEMS_IO_ERROR;
673  }
674
675  rv = close(fd);
676  if (rv != 0)
677    sc = RTEMS_IO_ERROR;
678
679  return RTEMS_SUCCESSFUL;
680}
681
682
683static void  altera_cyclone_v_m41st87_initialize(int minor)
684{
685
686  m41st87_time_t     time;
687  rtems_status_code  sc = RTEMS_SUCCESSFUL;
688  uint8_t            value;
689
690  /* Check RTC valid */
691  sc = m41st87_read(M41ST87_ADDR_TIME, &time, sizeof(time));
692  assert(sc == RTEMS_SUCCESSFUL);
693
694  if (time.seconds & M41ST87_BIT_ST)
695  {
696    /* RTC has been stopped. Reset stop flag. */
697    time.seconds = 0;
698    /* Initialise RTC. */
699    m41st87_set_time(&time, 0, 0, 0, 1, 1, TOD_BASE_YEAR);
700    sc = m41st87_write(M41ST87_ADDR_TIME, &time, sizeof(time));
701    assert(sc == RTEMS_SUCCESSFUL);
702  }
703
704  /* Reset HT bit */
705  sc = m41st87_read(M41ST87_ADDR_ALARM_HOUR, &value, 1);
706  assert(sc == RTEMS_SUCCESSFUL);
707  value &= ~M41ST87_BIT_HT;
708  sc = m41st87_write(M41ST87_ADDR_ALARM_HOUR, &value, 1);
709  assert(sc == RTEMS_SUCCESSFUL);
710
711}
712
713
714static int  altera_cyclone_v_m41st87_get_time(int minor, rtems_time_of_day* tod)
715{
716
717  m41st87_time_t     time;
718  rtems_status_code  sc = RTEMS_SUCCESSFUL;
719  rtems_time_of_day  temp_tod;
720
721  sc = m41st87_read(M41ST87_ADDR_TIME, &time, sizeof(time));
722  if (sc != RTEMS_SUCCESSFUL)
723    return -sc;
724
725  temp_tod.ticks  = 0;
726  temp_tod.second = m41st87_get_seconds(&time);
727  temp_tod.minute = m41st87_get_minutes(&time);
728  temp_tod.hour   = m41st87_get_hours(&time);
729  temp_tod.day    = m41st87_get_day_of_month(&time);
730  temp_tod.month  = m41st87_get_month(&time);
731  temp_tod.year   = m41st87_get_year(&time);
732
733  if (_TOD_Validate(&temp_tod))
734    memcpy(tod, &temp_tod, sizeof(temp_tod));
735  else
736    sc = RTEMS_INVALID_CLOCK;
737
738  return -sc;
739}
740
741
742static int  altera_cyclone_v_m41st87_set_time(int minor, const rtems_time_of_day* tod)
743{
744
745  m41st87_time_t     time;
746  rtems_status_code  sc = RTEMS_SUCCESSFUL;
747
748  /* first read to preserve the additional flags */
749  sc = m41st87_read(M41ST87_ADDR_TIME, &time, sizeof(time));
750  if (sc != RTEMS_SUCCESSFUL)
751    return -sc;
752
753  m41st87_set_time(&time,
754                   tod->second,
755                   tod->minute,
756                   tod->hour,
757                   tod->day,
758                   tod->month,
759                   tod->year
760                  );
761
762  sc = m41st87_write(M41ST87_ADDR_TIME, &time, sizeof(time));
763
764  return -sc;
765}
766
767
768static bool  altera_cyclone_v_m41st87_probe(int minor)
769{
770
771  rtems_status_code  sc = RTEMS_SUCCESSFUL;
772  uint8_t            buf;
773
774  /* try to read from register address 0x00 */
775  sc = m41st87_read(0x00, &buf, 1);
776  if (sc != RTEMS_SUCCESSFUL)
777    /* no RTC implemented */
778    return false;
779  /* try to read from register address 0x20 (implemented in M41ST87) */
780  sc = m41st87_read(0x20, &buf, 1);
781  if (sc != RTEMS_SUCCESSFUL)
782    /* RTC is not M41ST87 */
783    return false;
784
785  printk("RTC detected, type = M41ST87\n");
786  return true;
787
788}
789
790
791/* **************************************** General ********************************** */
792
793
794const rtc_fns  altera_cyclone_v_ds1339_ops =
795{
796  .deviceInitialize = altera_cyclone_v_ds1339_initialize,
797  .deviceGetTime = altera_cyclone_v_ds1339_get_time,
798  .deviceSetTime = altera_cyclone_v_ds1339_set_time
799};
800
801
802const rtc_fns  altera_cyclone_v_m41st87_ops =
803{
804  .deviceInitialize = altera_cyclone_v_m41st87_initialize,
805  .deviceGetTime = altera_cyclone_v_m41st87_get_time,
806  .deviceSetTime = altera_cyclone_v_m41st87_set_time
807};
808
809
810size_t  RTC_Count = ALTERA_CYCLONE_V_RTC_NUMBER;
811rtems_device_minor_number  RTC_Minor = 0;
812
813
814rtc_tbl  RTC_Table[ALTERA_CYCLONE_V_RTC_NUMBER] =
815{
816  {
817    .sDeviceName = "/dev/rtc",
818    .deviceType = RTC_CUSTOM,
819    .pDeviceFns = &altera_cyclone_v_ds1339_ops,
820    .deviceProbe = altera_cyclone_v_ds1339_probe,
821    .pDeviceParams = NULL,
822    .ulCtrlPort1 = 0,
823    .ulDataPort = 0,
824    .getRegister = NULL,
825    .setRegister = NULL
826  },
827  {
828    .sDeviceName = "/dev/rtc",
829    .deviceType = RTC_CUSTOM,
830    .pDeviceFns = &altera_cyclone_v_m41st87_ops,
831    .deviceProbe = altera_cyclone_v_m41st87_probe,
832    .pDeviceParams = NULL,
833    .ulCtrlPort1 = 0,
834    .ulDataPort = 0,
835    .getRegister = NULL,
836    .setRegister = NULL
837  }
838};
Note: See TracBrowser for help on using the repository browser.