Changeset a1d6f7a in rtems


Ignore:
Timestamp:
Apr 10, 2015, 6:23:00 AM (5 years ago)
Author:
Thomas Volgmann <Thomas.Volgmann@…>
Branches:
4.11, master
Children:
bcf536a
Parents:
a6c5a7e0
git-author:
Thomas Volgmann <Thomas.Volgmann@…> (04/10/15 06:23:00)
git-committer:
Sebastian Huber <sebastian.huber@…> (04/10/15 06:23:00)
Message:

bsp/altera-cyclone-v: Add RTC driver

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/arm/altera-cyclone-v/rtc/rtc.c

    ra6c5a7e0 ra1d6f7a  
    1414
    1515/*
    16  * Driver for the DS1339 RTC.
     16 * Driver for the DS1339 RTC (Maxim Semiconductors) -> RTC1
     17 *        and the M41ST87 RTC (ST Microelectronics) -> RTC2
    1718 *
    1819 * Please note the following points:
     
    3233#include <bsp/i2cdrv.h>
    3334
    34 #define ALTERA_CYCLONE_V_RTC_NUMBER 1
    35 
    36 #define DS1339_I2C_ADDRESS 0x68
    37 #define DS1339_I2C_BUS_DEVICE "/dev/i2c0"
    38 
    39 #define DS1339_ADDR_CTRL 0x0E
    40 #define DS1339_CTRL_EOSC 0x80
    41 #define DS1339_CTRL_BBSQI 0x20
    42 #define DS1339_CTRL_RS2 0x10
    43 #define DS1339_CTRL_RS1 0x08
    44 #define DS1339_CTRL_INTCN 0x04
    45 #define DS1339_CTRL_A2IE 0x02
    46 #define DS1339_CTRL_A1IE 0x01
    47 
    48 #define DS1339_CTRL_DEFAULT (0x00)
    49 
    50 #define DS1339_ADDR_TIME 0x00
    51 #define DS1339_ADDR_STATUS 0x0F
    52 #define DS1339_STATUS_OSF 0x80
    53 #define DS1339_STATUS_A2F 0x02
    54 #define DS1339_STATUS_A1F 0x01
    55 
    56 #define DS1339_STATUS_CLEAR (0x00)
    57 
    58 typedef struct {
    59   uint8_t seconds;
    60   uint8_t minutes;
    61   uint8_t hours;
     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;
    6272#define DS1339_HOURS_12_24_FLAG 0x40
    6373#define DS1339_HOURS_AM_PM_FLAG_OR_20_HOURS 0x20
    6474#define DS1339_HOURS_10_HOURS 0x10
    65   uint8_t weekday;
    66   uint8_t date;
    67   uint8_t month;
     75  uint8_t  weekday;
     76  uint8_t  date;
     77  uint8_t  month;
    6878#define DS1339_MONTH_CENTURY 0x80
    69   uint8_t year;
    70 } ds1339_time_t;
     79  uint8_t  year;
     80}
     81ds1339_time_t;
     82
    7183
    7284/* The longest write transmission is writing the time + one address bit */
    73 #define DS1339_MAX_WRITE_SIZE (sizeof(ds1339_time_t) + 1)
     85#define DS1339_MAX_WRITE_SIZE  (sizeof(ds1339_time_t) + 1)
     86
    7487
    7588/* Functions for converting the fields */
    76 static unsigned int get_seconds (ds1339_time_t *time) {
    77   uint8_t tens = time->seconds >> 4;
    78   uint8_t ones = time->seconds & 0x0F;
    79   return tens * 10 + ones;
    80 }
    81 
    82 static unsigned int get_minutes (ds1339_time_t *time) {
    83   uint8_t tens = time->minutes >> 4;
    84   uint8_t ones = time->minutes & 0x0F;
    85   return tens * 10 + ones;
    86 }
    87 
    88 static unsigned int get_hours (ds1339_time_t *time) {
    89   uint8_t value = time->hours & 0x0F;
    90 
    91   if(time->hours & DS1339_HOURS_10_HOURS) {
     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  {
    92114    value += 10;
    93115  }
    94   if(time->hours & DS1339_HOURS_AM_PM_FLAG_OR_20_HOURS) {
    95     if(time->hours & DS1339_HOURS_12_24_FLAG) {
     116  if (time->hours & DS1339_HOURS_AM_PM_FLAG_OR_20_HOURS)
     117  {
     118    if (time->hours & DS1339_HOURS_12_24_FLAG)
    96119      value += 12;
    97     } else {
     120    else
    98121      value += 20;
    99     }
    100122  }
    101123
     
    103125}
    104126
    105 static unsigned int get_day_of_month (ds1339_time_t *time) {
    106   uint8_t tens = time->date >> 4;
    107   uint8_t ones = time->date & 0x0F;
    108   return tens * 10 + ones;
    109 }
    110 
    111 static unsigned int get_month (ds1339_time_t *time) {
    112   uint8_t tens = (time->month >> 4) & 0x07;
    113   uint8_t ones = time->month & 0x0F;
    114   return tens * 10 + ones;
    115 }
    116 
    117 static unsigned int get_year (ds1339_time_t *time) {
    118   unsigned int year = 1900;
     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
    119153  year += (time->year >> 4) * 10;
    120154  year += time->year & 0x0F;
    121   if(time->month & DS1339_MONTH_CENTURY) {
     155  if (time->month & DS1339_MONTH_CENTURY)
    122156    year += 100;
    123   }
    124   if(year < TOD_BASE_YEAR) {
     157  if (year < TOD_BASE_YEAR)
    125158    year += 200;
    126   }
     159
    127160  return year;
    128161}
    129162
    130 static void set_time (
    131   ds1339_time_t *time,
    132   unsigned int second,
    133   unsigned int minute,
    134   unsigned int hour,
    135   unsigned int day,
    136   unsigned int month,
    137   unsigned int year
    138 ) {
    139   unsigned int tens;
    140   unsigned int ones;
    141   uint8_t century = 0;
     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;
    142176
    143177  tens = second / 10;
     
    162196  tens = month / 10;
    163197  ones = month % 10;
    164   if(year >= 2000 && year < 2100) {
     198  if ((year >= 2000) && (year < 2100))
    165199    century = DS1339_MONTH_CENTURY;
    166   }
    167200  time->month = century | tens << 4 | ones;
    168201
     
    170203  ones = year % 10;
    171204  time->year = tens << 4 | ones;
    172 }
    173 
    174 static rtems_status_code ds1339_open_file(int *fd)
    175 {
    176   int rv = 0;
    177   rtems_status_code sc = RTEMS_SUCCESSFUL;
     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;
    178215
    179216  *fd = open(DS1339_I2C_BUS_DEVICE, O_RDWR);
    180   if ( *fd == -1 ) {
     217  if (*fd == -1)
    181218    sc = RTEMS_IO_ERROR;
    182   }
    183 
    184   if ( sc == RTEMS_SUCCESSFUL ) {
     219
     220  if (sc == RTEMS_SUCCESSFUL)
     221  {
    185222    rv = ioctl(*fd, I2C_IOC_SET_SLAVE_ADDRESS, DS1339_I2C_ADDRESS);
    186     if ( rv == -1 ) {
     223    if (rv == -1)
    187224      sc = RTEMS_IO_ERROR;
    188     }
    189225  }
    190226
     
    192228}
    193229
     230
    194231/* Read size bytes from ds1339 register address addr to buf. */
    195 static rtems_status_code ds1339_read(uint8_t addr, void *buf, size_t size)
    196 {
    197   int fd = -1;
    198   int rv = 0;
    199   rtems_status_code sc = RTEMS_SUCCESSFUL;
     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;
    200238
    201239  sc = ds1339_open_file(&fd);
    202240
    203   if ( sc == RTEMS_SUCCESSFUL ) {
     241  if (sc == RTEMS_SUCCESSFUL)
     242  {
    204243    rv = write(fd, &addr, sizeof(addr));
    205     if ( rv != sizeof(addr) ) {
     244    if (rv != sizeof(addr))
    206245      sc = RTEMS_IO_ERROR;
    207     }
    208   }
    209 
    210   if ( sc == RTEMS_SUCCESSFUL ) {
     246  }
     247
     248  if (sc == RTEMS_SUCCESSFUL)
     249  {
    211250    rv = read(fd, buf, size);
    212     if ( rv != size ) {
     251    if (rv != size)
    213252      sc = RTEMS_IO_ERROR;
    214     }
    215253  }
    216254
    217255  rv = close(fd);
    218   if ( rv != 0 ) {
     256  if (rv != 0)
    219257    sc = RTEMS_IO_ERROR;
    220   }
    221258
    222259  return sc;
    223260}
    224261
     262
    225263/* Write size bytes from buf to ds1339 register address addr. */
    226 static rtems_status_code ds1339_write(uint8_t addr, void *buf, size_t size)
    227 {
    228   int fd = -1;
    229   int rv = 0;
    230   rtems_status_code sc = RTEMS_SUCCESSFUL;
     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;
    231270  /* The driver never writes many bytes. Therefore it should be less expensive
    232271   * to reserve the maximum number of bytes that will be written in one go than
    233272   * use a malloc. */
    234   uint8_t local_buf[DS1339_MAX_WRITE_SIZE];
    235   int write_size = size + 1;
     273  uint8_t            local_buf[DS1339_MAX_WRITE_SIZE];
     274  int                write_size = size + 1;
    236275
    237276  assert(write_size <= DS1339_MAX_WRITE_SIZE);
     
    242281  sc = ds1339_open_file(&fd);
    243282
    244   if ( sc == RTEMS_SUCCESSFUL ) {
     283  if (sc == RTEMS_SUCCESSFUL)
     284  {
    245285    rv = write(fd, local_buf, write_size);
    246     if ( rv != write_size ) {
     286    if (rv != write_size)
    247287      sc = RTEMS_IO_ERROR;
    248     }
    249288  }
    250289
    251290  rv = close(fd);
    252   if ( rv != 0 ) {
     291  if (rv != 0)
    253292    sc = RTEMS_IO_ERROR;
    254   }
    255293
    256294  return RTEMS_SUCCESSFUL;
    257295}
    258296
    259 static void altera_cyclone_v_rtc_initialize(int minor)
    260 {
    261   rtems_status_code sc = RTEMS_SUCCESSFUL;
    262   uint8_t status = 0;
     297
     298static void altera_cyclone_v_ds1339_initialize(int minor)
     299{
     300
     301  rtems_status_code  sc = RTEMS_SUCCESSFUL;
     302  uint8_t            status = 0;
    263303
    264304  /* Check RTC valid */
    265305  sc = ds1339_read(DS1339_ADDR_STATUS, &status, sizeof(status));
    266306  assert(sc == RTEMS_SUCCESSFUL);
    267   if(status & DS1339_STATUS_OSF) {
     307
     308  if (status & DS1339_STATUS_OSF)
     309  {
    268310    /* RTC has been stopped. Initialise it. */
    269311    ds1339_time_t time;
    270312
    271     uint8_t write = DS1339_CTRL_DEFAULT;
     313    uint8_t  write = DS1339_CTRL_DEFAULT;
    272314    sc = ds1339_write(DS1339_ADDR_CTRL, &write, sizeof(write));
    273315    assert(sc == RTEMS_SUCCESSFUL);
     
    277319    assert(sc == RTEMS_SUCCESSFUL);
    278320
    279     set_time(&time, 0, 0, 0, 1, 1, TOD_BASE_YEAR);
     321    ds1339_set_time(&time, 0, 0, 0, 1, 1, TOD_BASE_YEAR);
    280322    sc = ds1339_write(DS1339_ADDR_TIME, &time, sizeof(time));
    281323    assert(sc == RTEMS_SUCCESSFUL);
    282324  }
    283 }
    284 
    285 static int altera_cyclone_v_rtc_get_time(int minor, rtems_time_of_day *tod)
    286 {
    287   ds1339_time_t time;
    288   rtems_status_code sc = RTEMS_SUCCESSFUL;
    289   rtems_time_of_day temp_tod;
     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;
    290335
    291336  sc = ds1339_read(DS1339_ADDR_TIME, &time, sizeof(time));
    292337
    293   if ( sc == RTEMS_SUCCESSFUL ) {
    294     temp_tod.ticks = 0;
    295     temp_tod.second = get_seconds(&time);
    296     temp_tod.minute = get_minutes(&time);
    297     temp_tod.hour = get_hours(&time);
    298     temp_tod.day = get_day_of_month(&time);
    299     temp_tod.month = get_month(&time);
    300     temp_tod.year = get_year(&time);
    301 
    302     if ( _TOD_Validate(&temp_tod) ) {
     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))
    303349      memcpy(tod, &temp_tod, sizeof(temp_tod));
    304     } else {
     350    else
    305351      sc = RTEMS_INVALID_CLOCK;
    306     }
    307352  }
    308353
     
    310355}
    311356
    312 static int altera_cyclone_v_rtc_set_time(int minor, const rtems_time_of_day *tod)
    313 {
    314   ds1339_time_t time;
    315   rtems_status_code sc = RTEMS_SUCCESSFUL;
    316 
    317   set_time (
    318     &time,
    319     tod->second,
    320     tod->minute,
    321     tod->hour,
    322     tod->day,
    323     tod->month,
    324     tod->year
    325   );
     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                 );
    326372
    327373  sc = ds1339_write(DS1339_ADDR_TIME, &time, sizeof(time));
     
    330376}
    331377
    332 static bool altera_cyclone_v_rtc_probe(int minor)
    333 {
    334   /* FIXME: Probe for i2c device */
     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");
    335397  return true;
    336 }
    337 
    338 const rtc_fns altera_cyclone_v_rtc_ops = {
    339   .deviceInitialize = altera_cyclone_v_rtc_initialize,
    340   .deviceGetTime = altera_cyclone_v_rtc_get_time,
    341   .deviceSetTime = altera_cyclone_v_rtc_set_time
     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
    342799};
    343800
    344 size_t RTC_Count = ALTERA_CYCLONE_V_RTC_NUMBER;
    345 
    346 rtems_device_minor_number RTC_Minor = 0;
    347 
    348 rtc_tbl RTC_Table [ALTERA_CYCLONE_V_RTC_NUMBER] = {
     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{
    349816  {
    350817    .sDeviceName = "/dev/rtc",
    351818    .deviceType = RTC_CUSTOM,
    352     .pDeviceFns = &altera_cyclone_v_rtc_ops,
    353     .deviceProbe = altera_cyclone_v_rtc_probe,
     819    .pDeviceFns = &altera_cyclone_v_ds1339_ops,
     820    .deviceProbe = altera_cyclone_v_ds1339_probe,
    354821    .pDeviceParams = NULL,
    355822    .ulCtrlPort1 = 0,
     
    357824    .getRegister = NULL,
    358825    .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
    359837  }
    360838};
Note: See TracChangeset for help on using the changeset viewer.