source: rtems/c/src/lib/libbsp/arm/beagle/rtc.c @ 0057e38f

Last change on this file since 0057e38f was 0057e38f, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 4, 2016 at 9:06:53 AM

libchip: Simplify RTC driver

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup arm_beagle
5 *
6 * @brief RTC driver for AM335x SoC.
7 *
8 */
9
10/*
11 * Copyright (c) 2015 Ragunath <ragunath3252@gmail.com>.
12 *
13 * The license and distribution terms for this file may be
14 * found in the file LICENSE in this distribution or at
15 * http://www.rtems.com/license/LICENSE.
16 */
17
18#include <bspopts.h>
19
20#if IS_AM335X
21#include <rtems.h>
22#include <bsp.h>
23#include <time.h>
24#include <libchip/rtc.h>
25#include <libcpu/omap3.h>
26
27#define setbit(a,x) (a | (1<<x))
28#define bcd(a) ((a & 0x0f)+ (((a & 0xf0) >> 4 )*10))
29#define dec(a) (((a / 10) << 4) | (a % 10))
30#define WRITE_WAIT_MAX_COUNT 10000
31
32size_t RTC_Count = 1;
33
34static void rtc_write_enable(void);
35static void rtc_write_disable(void);
36static int rtc_write_wait(void);
37static void rtc_clk_init(void);
38void rtc_init(int minor);
39void print_time(void);
40int am335x_rtc_gettime(int minor,rtems_time_of_day *t);
41int am335x_rtc_settime(int minor, const rtems_time_of_day *t);
42void am335x_rtc_debug(void);
43
44/*
45 * probe for a rtc. we always claim to have one.
46 */
47static bool am335x_rtc_probe (int minor)
48{
49  return true;
50}
51
52/*
53 * Write key values to kick0 and kick1 registers to enable write access
54 */
55static void rtc_write_enable(void)
56{
57  mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK0,AM335X_RTC_KICK0_KEY);
58  mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK1,AM335X_RTC_KICK1_KEY);
59}
60
61/*
62 * Write random (0x11111111) value to kick0 and kick1 registers to disable write access
63 */
64static void rtc_write_disable(void)
65{
66  /* Write some random value other than key to disable*/
67  mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK0,0x11111111);
68  mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK1,0x11111111);
69}
70
71/*
72 * Wait till busy bit is reset
73 */
74static int rtc_write_wait(void)
75{
76  int i = WRITE_WAIT_MAX_COUNT;
77  while((mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1) && (i--));
78
79  if(i == 0)
80      return RTEMS_RESOURCE_IN_USE;
81  else
82      return RTEMS_SUCCESSFUL;
83}
84
85
86/*
87 * Initialize RTC clock
88 */
89static void rtc_clk_init(void)
90{
91  uint32_t a = 0x0;
92
93  a = setbit(a,1);
94  /* IDLEST = 0x0 & MODULEMODE = 0x1*/
95  mmio_write(CM_RTC_BASE+CM_RTC_RTC_CLKCTRL,a);
96  a = 0x0;
97
98  /*32K rtc clock active*/
99  a = setbit(a,9);
100  a = setbit(a,8);
101  mmio_write(CM_RTC_BASE+CM_RTC_CLKSTCTRL,a);
102}
103
104void rtc_init(int minor)
105{
106  uint32_t a = 0x0;
107
108  rtc_clk_init();
109   /*
110   * Steps to enable RTC
111   * 1. Enable the module clock domains (rtc_clk_init).
112   * 2. Enable the RTC module using CTRL_REG.RTC_disable. (Default enabled. Nothing done)
113   * 3. Enable the 32K clock from PER PLL, if using the internal RTC oscillator.
114   * 4. Write to the kick registers (KICK0R, KICK1R) in the RTC.
115   * 5. Configure the timer in RTCSS for desired application (set time and date, alarm wakeup, and so on).
116   * 6. Start the RTC (in CTRL_REG.STOP_RTC).
117   */
118  rtc_write_enable();
119  a = setbit(a,0);
120  mmio_write(AM335X_RTC_BASE+AM335X_RTC_SYSCONFIG,a);
121  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_OSC_CLOCK);
122  a = setbit(a,6);
123  mmio_write(AM335X_RTC_BASE+AM335X_RTC_OSC_CLOCK,a);
124  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_CTRL_REG);
125  a = setbit(a,0);
126  mmio_write(AM335X_RTC_BASE+AM335X_RTC_CTRL_REG,a);
127
128  rtc_write_disable();
129}
130
131int am335x_rtc_gettime(int minor,rtems_time_of_day *t)
132{
133  uint32_t a = 0x0;
134
135  if(minor != 0)
136    return RTEMS_INVALID_NUMBER;
137
138  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_SECS);
139  t->second = bcd(a);
140  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MINS);
141  t->minute = bcd(a);
142  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_HOURS);
143  t->hour = bcd(a);
144  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_DAYS);
145  t->day = bcd(a);
146  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MONTHS);
147  t->month = bcd(a);
148  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_YEARS);
149  t->year = bcd(a)+2000;
150  t->ticks=0;
151  return RTEMS_SUCCESSFUL;
152}
153
154int am335x_rtc_settime(int minor,const rtems_time_of_day *t)
155{
156  uint32_t a=0x0;
157  int rv;
158
159  if(minor != 0)
160    return RTEMS_INVALID_NUMBER;
161
162  rtc_write_enable();
163
164  /* Wait till the busy bit is reset to write again*/
165  a = t->second;
166  rv=rtc_write_wait();
167  if(rv != RTEMS_SUCCESSFUL)
168      return rv;
169  a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_SECS,dec(a) & 0x7f);
170
171  a = t->minute;
172  rv=rtc_write_wait();
173  if(rv != RTEMS_SUCCESSFUL)
174      return rv;
175  a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_MINS,dec(a) & 0x7f);
176
177  a = t->hour;
178  rv=rtc_write_wait();
179  if(rv != RTEMS_SUCCESSFUL)
180      return rv;
181  a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_HOURS,dec(a) & 0x3f);
182
183  a = t->day;
184  rv=rtc_write_wait();
185  if(rv != RTEMS_SUCCESSFUL)
186      return rv;
187  a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_DAYS,dec(a) & 0x3f);
188
189  a = t->month;
190  rv=rtc_write_wait();
191  if(rv != RTEMS_SUCCESSFUL)
192      return rv;
193  a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_MONTHS,dec(a) & 0x1f);
194
195  a = t->year;
196  rv=rtc_write_wait();
197  if(rv != RTEMS_SUCCESSFUL)
198      return rv;
199  a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_YEARS,(dec(a)%100) & 0xff);
200
201  rtc_write_disable();
202  return rv;
203}
204
205#if BBB_DEBUG
206void print_time(void)
207{
208  uint32_t a = 0x0;
209  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_SECS);
210  printk("\n\rSecs %x",a);
211  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MINS);
212  printk("\n\rMins %x",a);
213  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_HOURS);
214  printk("\n\rHours %x",a);
215  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_DAYS);
216  printk("\n\rDays %x",a);
217  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MONTHS);
218  printk("\n\r Months %x",a);
219  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_YEARS);
220  printk("\n\rYears %x",a);
221  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_WEEKS);
222  printk("\n\rWeeks %x",a);
223}
224
225void am335x_rtc_debug(void)
226{
227  int i;
228  rtems_time_of_day t,r;
229
230  t.second = 1;
231  t.minute = 1;
232  t.hour = 1;
233  t.day = 7;
234  t.month = 3;
235  t. year = 2015;
236
237  am335x_rtc_settime(0,&t);
238  am335x_rtc_gettime(0,&r);
239
240  printk("Secs %x",r.second);
241  printk("Mins %x",r.minute);
242  printk("Hours %x",r.hour);
243  printk("Days %x",r.day);
244  printk("Months %x",r.month);
245  printk("Years %x",r.year);
246}
247#endif
248
249/*
250 * driver function table.
251 */
252rtc_fns am335x_rtc_fns = {
253  rtc_init,
254  am335x_rtc_gettime,
255  am335x_rtc_settime
256};
257
258/*
259 * the following table configures the RTC drivers used in this BSP
260 */
261
262rtc_tbl RTC_Table[] = {
263  {
264   "/dev/rtc",                  /* sDeviceName */
265   RTC_CUSTOM,                  /* deviceType */
266   &am335x_rtc_fns,             /* pDeviceFns */
267   am335x_rtc_probe,            /* deviceProbe */
268   NULL,                        /* pDeviceParams */
269   0,                           /* ulCtrlPort1 */
270   0,                           /* ulDataPort */
271   NULL,                        /* getRegister */
272   NULL                         /* setRegister */
273   }
274};
275
276#endif
Note: See TracBrowser for help on using the repository browser.