source: rtems/bsps/powerpc/gen5200/rtc/pcf8563.c @ e560ee85

Last change on this file since e560ee85 was e560ee85, checked in by Joel Sherrill <joel@…>, on 03/01/22 at 21:38:55

bsps/powerpc/: Scripted embedded brains header file clean up

Updates #4625.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*===============================================================*\
2| Project: RTEMS generic MPC5200 BSP                              |
3+-----------------------------------------------------------------+
4| Partially based on the code references which are named below.   |
5| Adaptions, modifications, enhancements and any recent parts of  |
6| the code are:                                                   |
7|                    Copyright (c) 2005                           |
8|                    embedded brains GmbH                         |
9|                    Obere Lagerstr. 30                           |
10|                    82178 Puchheim                             |
11|                    Germany                                      |
12|                    rtems@embedded-brains.de                     |
13+-----------------------------------------------------------------+
14| The license and distribution terms for this file may be         |
15| found in the file LICENSE in this distribution or at            |
16|                                                                 |
17| http://www.rtems.org/license/LICENSE.                           |
18|                                                                 |
19+-----------------------------------------------------------------+
20| this file contains the tod driver for a Philips pcf8563 I2C RTC |
21\*===============================================================*/
22/*
23 * This file interfaces with the real-time clock found in a
24 * Philips PCF8563 serial real-time clock chip.
25 * This RTC have I2C bus interface. BSP have to provide I2C bus primitives
26 * to make this driver working. getRegister and setRegister primitives is
27 * not used here to avoid multiple transactions over I2C bus (each transaction
28 * require significant time and error when date/time information red may
29 * occurs). ulControlPort contains I2C bus number; ulDataPort contains
30 * RTC I2C device address.
31 *
32 * Based on a ds1307 driver from:
33 *
34 * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia
35 * Author: Victor V. Vengerov <vvv@oktet.ru>
36 *
37 * The license and distribution terms for this file may be
38 * found in the file LICENSE in this distribution or at
39 *
40 * http://www.rtems.org/license/LICENSE.
41 */
42
43#include <rtems.h>
44#include <bsp/fatal.h>
45#include <bsp/i2c.h>
46#include <libchip/rtc.h>
47#include <string.h>
48#include "pcf8563.h"
49
50/* Convert from/to Binary-Coded Decimal representation */
51#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
52#define To_BCD( _x )   ((((_x) / 10) << 4) + ((_x) % 10))
53
54/* pcf8563_initialize --
55 *     Initialize PCF8563 real-time clock chip. If RTC is halted, this
56 *     function resume counting.
57 *
58 * PARAMETERS:
59 *     minor -- minor RTC device number
60 */
61static void
62pcf8563_initialize(int minor)
63{
64    i2c_message_status status;
65    int try;
66    uint8_t         ctrl1;
67    i2c_bus_number bus;
68    i2c_address addr;
69
70    bus = RTC_Table[minor].ulCtrlPort1;
71    addr = RTC_Table[minor].ulDataPort;
72
73    /* Read SECONDS register */
74    try = 0;
75    do {
76        status = i2c_wbrd(bus, addr, PCF8563_CONTROL1_ADR,
77                          &ctrl1, sizeof(ctrl1));
78        try++;
79    } while ((status != I2C_SUCCESSFUL) && (try < 15));
80
81    /* If clock is halted, reset and start the clock */
82    if ((ctrl1 & PCF8563_CONTROL1_STOP) != 0)
83    {
84        uint8_t         start[8];
85        memset(start, 0, sizeof(start));
86        start[0] = PCF8563_CONTROL1_ADR;
87        try = 0;
88        do {
89            status = i2c_write(bus, addr, start, 2);
90        } while ((status != I2C_SUCCESSFUL) && (try < 15));
91    }
92}
93
94/* pcf8563_get_time --
95 *     read current time from PCF8563 real-time clock chip and convert it
96 *     to the rtems_time_of_day structure.
97 *
98 * PARAMETERS:
99 *     minor -- minor RTC device number
100 *     time -- place to put return value (date and time)
101 *
102 * RETURNS:
103 *     0, if time obtained successfully
104 *     -1, if error occured
105 */
106static int
107pcf8563_get_time(int minor, rtems_time_of_day *time)
108{
109    i2c_bus_number bus;
110    i2c_address addr;
111    uint8_t         info[10];
112    uint32_t         v1, v2;
113    i2c_message_status status;
114    int try;
115
116    if (time == NULL)
117        return -1;
118
119    bus = RTC_Table[minor].ulCtrlPort1;
120    addr = RTC_Table[minor].ulDataPort;
121
122    memset(time, 0, sizeof(rtems_time_of_day));
123    try = 0;
124    do {
125        status = i2c_wbrd(bus, addr, PCF8563_SECOND_ADR, info, sizeof(info));
126        try++;
127    } while ((status != I2C_SUCCESSFUL) && (try < 10));
128
129    if (status != I2C_SUCCESSFUL)
130    {
131        return -1;
132    }
133
134    v1 = info[PCF8563_YEAR_ADR-PCF8563_SECOND_ADR];
135    v2 = From_BCD(v1);
136    if ((info[PCF8563_MONTH_ADR-PCF8563_SECOND_ADR]
137         & PCF8563_MONTH_CENTURY) == 0) {
138      time->year = 1900 + v2;
139    }
140    else {
141      time->year = 2000 + v2;
142    }
143
144    v1 = info[PCF8563_MONTH_ADR-PCF8563_SECOND_ADR] & PCF8563_MONTH_MASK;
145    time->month = From_BCD(v1);
146
147    v1 = info[PCF8563_DAY_ADR-PCF8563_SECOND_ADR] & PCF8563_DAY_MASK;
148    time->day = From_BCD(v1);
149
150    v1 = info[PCF8563_HOUR_ADR-PCF8563_SECOND_ADR] & PCF8563_HOUR_MASK;
151    time->hour = From_BCD(v1);
152
153    v1 = info[PCF8563_MINUTE_ADR-PCF8563_SECOND_ADR] & PCF8563_MINUTE_MASK;
154    time->minute = From_BCD(v1);
155
156    v1 = info[PCF8563_SECOND_ADR-PCF8563_SECOND_ADR] & PCF8563_SECOND_MASK;
157    time->second = From_BCD(v1);
158
159    return 0;
160}
161
162/* pcf8563_set_time --
163 *     set time to the PCF8563 real-time clock chip
164 *
165 * PARAMETERS:
166 *     minor -- minor RTC device number
167 *     time -- new date and time to be written to PCF8563
168 *
169 * RETURNS:
170 *     0, if time obtained successfully
171 *     -1, if error occured
172 */
173static int
174pcf8563_set_time(int minor, const rtems_time_of_day *time)
175{
176    i2c_bus_number bus;
177    i2c_address addr;
178    uint8_t         info[8];
179    i2c_message_status status;
180    int try;
181
182    if (time == NULL)
183        return -1;
184
185    bus = RTC_Table[minor].ulCtrlPort1;
186    addr = RTC_Table[minor].ulDataPort;
187
188    if ((time->year >= 2100) || (time->year <  1900)) {
189      bsp_fatal(MPC5200_FATAL_PCF8563_INVALID_YEAR);
190    }
191    info[0] = PCF8563_SECOND_ADR;
192    info[1 + PCF8563_YEAR_ADR  -PCF8563_SECOND_ADR] = To_BCD(time->year % 100);
193    info[1 + PCF8563_MONTH_ADR -PCF8563_SECOND_ADR] = To_BCD(time->month);
194    info[1 + PCF8563_DAY_ADR   -PCF8563_SECOND_ADR] = To_BCD(time->day);
195    info[1 + PCF8563_HOUR_ADR  -PCF8563_SECOND_ADR] = To_BCD(time->hour);
196    info[1 + PCF8563_MINUTE_ADR-PCF8563_SECOND_ADR] = To_BCD(time->minute);
197    info[1 + PCF8563_SECOND_ADR-PCF8563_SECOND_ADR] = To_BCD(time->second);
198    /* Do not set day of week */
199    info[1 + PCF8563_DAY_OF_WEEK_ADR-PCF8563_SECOND_ADR] = 1;
200
201    /*
202     * add century info
203     */
204    if (time->year >= 2000) {
205      info[1 + PCF8563_MONTH_ADR -PCF8563_SECOND_ADR] |= PCF8563_MONTH_CENTURY;
206    }
207    /*
208     * send to device
209     */
210    try = 0;
211    do {
212        status = i2c_write(bus, addr, info,sizeof(info));
213        try++;
214    } while ((status != I2C_SUCCESSFUL) && (try < 10));
215
216    if (status != I2C_SUCCESSFUL)
217        return -1;
218    else
219        return 0;
220}
221
222/* Driver function table */
223
224rtc_fns pcf8563_fns = {
225    pcf8563_initialize,
226    pcf8563_get_time,
227    pcf8563_set_time
228};
Note: See TracBrowser for help on using the repository browser.