source: rtems/bsps/arm/altera-cyclone-v/rtc/rtc.c @ 523867d

Last change on this file since 523867d was 523867d, checked in by Sebastian Huber <sebastian.huber@…>, on 05/11/21 at 15:27:20

rtems: Constify rtems_task_wake_when()

Add a parameter to _TOD_Validate() to disable the validation of the
ticks member.

There are two reasons for this change. Firstly, in
rtems_task_wake_when() was a double check for time_buffer == NULL (one
in rtems_task_wake_when() and one in _TOD_Validate()). Secondly, the
ticks member is ignored by rtems_task_wake_when(). This was done with a
write of zero to the ticks member and thus a modification of the
user-provided structure. Now the structure is no longer modified.
Using a mask parameter is quite efficient. You just have to load an
immediate value and there are no additional branches in _TOD_Validate().

Close #4406.

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