source: rtems/c/src/lib/libbsp/arm/beagle/rtc.c @ 2e3ba71

5
Last change on this file since 2e3ba71 was d55d7a0, checked in by ragunath <ragunath3252@…>, on 05/03/15 at 09:55:55

beagle bsp: RTC support for BBB

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