Hi All,

I was exploring the beagle code base to find a task to get hands on
experience with RTEMS internals. I found that "Real time Clock (RTC)" support is
missing for beaglebone. I made the effort to add the driver for the device.
Included the patch for the driver. RTEMS already have a RTC framework.
I defined the necessary structures to hook the driver to the framework.
Enabled the driver by defining the macro
"CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER" and tested the following.
Testing is done from the shell using "date" and "rtc" commands.
1. Able to read the time from rtc.
2. Able to set the time
3. Time values are preserved between reboots

Pls review the patch and let me know if you have any comments.

I have following doubts

1. The support is applicable only to beaglebone black. It is not valid
for beagleboard. Both of them seem to have same codebase.  Is there any compile
time flags available to not compile the driver for beagleboard?
2. What is procedure to commit the change (In case the patch is
accepted)? Do we need to open a bug to track the changes?

Thanks,
Ragunath
From 03b7fccb6605ada6a5c022d960efa4a9e653c3bb Mon Sep 17 00:00:00 2001
From: ragunath <ragunath3...@gmail.com>
Date: Tue, 10 Mar 2015 15:09:37 +0530
Subject: [PATCH] RTC driver for Beaglebone black

---
 c/src/lib/libbsp/arm/beagle/Makefile.am          |   4 +
 c/src/lib/libbsp/arm/beagle/rtc.c                | 250 +++++++++++++++++++++++
 c/src/lib/libcpu/arm/shared/include/am335x_rtc.h |  27 +++
 c/src/lib/libcpu/arm/shared/include/omap3.h      |   6 +
 4 files changed, 287 insertions(+)
 create mode 100644 c/src/lib/libbsp/arm/beagle/rtc.c
 create mode 100644 c/src/lib/libcpu/arm/shared/include/am335x_rtc.h

diff --git a/c/src/lib/libbsp/arm/beagle/Makefile.am b/c/src/lib/libbsp/arm/beagle/Makefile.am
index abef8ba..13569fc 100644
--- a/c/src/lib/libbsp/arm/beagle/Makefile.am
+++ b/c/src/lib/libbsp/arm/beagle/Makefile.am
@@ -45,6 +45,7 @@ include_libcpu_HEADERS += ../../../libcpu/arm/shared/include/arm-cp15.h
 include_libcpu_HEADERS += ../../../libcpu/arm/shared/include/omap3.h
 include_libcpu_HEADERS += ../../../libcpu/arm/shared/include/am335x.h
 include_libcpu_HEADERS += ../../../libcpu/arm/shared/include/omap_timer.h
+include_libcpu_HEADERS += ../../../libcpu/arm/shared/include/am335x_rtc.h
 
 ###############################################################################
 #                  Data                                                       #
@@ -114,6 +115,9 @@ libbsp_a_SOURCES += ../../shared/console.c \
 # I2C
 libbsp_a_SOURCES += misc/i2c.c
 
+#RTC
+libbsp_a_SOURCES += rtc.c
+libbsp_a_SOURCES += ../../shared/tod.c
 # Clock
 libbsp_a_SOURCES += clock.c
 libbsp_a_SOURCES += ../../shared/clockdrv_shell.h
diff --git a/c/src/lib/libbsp/arm/beagle/rtc.c b/c/src/lib/libbsp/arm/beagle/rtc.c
new file mode 100644
index 0000000..e64df11
--- /dev/null
+++ b/c/src/lib/libbsp/arm/beagle/rtc.c
@@ -0,0 +1,250 @@
+/**
+ * @file
+ *
+ * @ingroup arm_beagle
+ *
+ * @brief RTC driver for AM335x SoC.
+ * 
+ */
+
+/*
+ * Copyright (c) 2015 Ragunath <ragunath3...@gmail.com>.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+#include <rtems.h>
+#include <bsp.h>
+#include <time.h>
+#include <libchip/rtc.h>
+#include <libcpu/am335x_rtc.h>
+#include <libcpu/omap3.h>
+
+#if IS_AM335X
+#define setbit(a,x) (a | (1<<x))
+#define bcd(a) ((a & 0x0f)+ (((a & 0xf0) >> 4 )*10))
+#define dec(a) (((a / 10) << 4) | (a % 10))
+
+rtems_device_minor_number RTC_Minor;
+size_t RTC_Count = 1;
+
+static void rtc_write_enable(void);
+static void rtc_write_disable(void);
+static void rtc_clk_init(void);
+void rtc_init(int minor);
+void print_time(void);
+int am335x_rtc_gettime(int minor,rtems_time_of_day *t);
+int am335x_rtc_settime(int minor, const rtems_time_of_day *t);
+void am335x_rtc_debug(void);
+
+/*
+ * probe for a rtc. we always claim to have one.
+ */
+static bool am335x_rtc_probe (int minor)
+{
+  return true;
+}
+
+/*
+ * Write key values to kick0 and kick1 registers to enable write access
+ */
+static void rtc_write_enable(void)
+{	
+  mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK0,AM335X_RTC_KICK0_KEY);
+  mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK1,AM335X_RTC_KICK1_KEY);
+	
+}
+
+/*
+ * Write random (0x11111111) value to kick0 and kick1 registers to disabl write access
+ */
+static void rtc_write_disable(void)
+{
+  /* Write some random value other than key to disable*/
+  mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK0,0x11111111);
+  mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK1,0x11111111);
+}
+
+/*
+ * Initialize RTC clock
+ */
+static void rtc_clk_init(void)
+{
+  uint32_t a=0x0;
+
+  a=setbit(a,1);
+  /* IDLEST = 0x0 & MODULEMODE = 0x1*/
+  mmio_write(CM_RTC_BASE+CM_RTC_RTC_CLKCTRL,a);
+  a=0x0;
+
+  /*32K rtc clock active*/	
+  a=setbit(a,9);
+  a=setbit(a,8);	
+  mmio_write(CM_RTC_BASE+CM_RTC_CLKSTCTRL,a);
+}
+
+void rtc_init(int minor)
+{
+  int rmajor,rminor,reg;
+  uint32_t a=0x0;	
+
+  rtc_clk_init();
+  reg = mmio_read(AM335X_RTC_BASE+AM335X_RTC_REV_REG);
+  rminor = (reg & 0x001f);
+  rmajor = (reg & 0x0700) >> 8;
+  printk("\n\r Rtc Major %d minor %d",rmajor,rminor);
+
+  /*
+   * Steps to enable RTC
+   * 	1. Enable the module clock domains (rtc_clk_init).
+	2. Enable the RTC module using CTRL_REG.RTC_disable. (Default enabled. Nothing done)
+	3. Enable the 32K clock from PER PLL, if using the internal RTC oscillator.
+	4. Write to the kick registers (KICK0R, KICK1R) in the RTC.
+	5. Configure the timer in RTCSS for desired application (set time and date, alarm wakeup, and so on).
+	6. Start the RTC (in CTRL_REG.STOP_RTC).
+   */
+  rtc_write_enable();
+  a=setbit(a,0);
+  mmio_write(AM335X_RTC_BASE+AM335X_RTC_SYSCONFIG,a);		
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_OSC_CLOCK);
+  a=setbit(a,6);
+  mmio_write(AM335X_RTC_BASE+AM335X_RTC_OSC_CLOCK,a);
+  a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_CTRL_REG);
+  a = setbit(a,0);
+  mmio_write(AM335X_RTC_BASE+AM335X_RTC_CTRL_REG,a);		
+
+  rtc_write_disable();
+
+}
+
+int am335x_rtc_gettime(int minor,rtems_time_of_day *t)
+{
+  uint32_t a=0x0;
+
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_SECS);
+  t->second = bcd(a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_MINS);
+  t->minute = bcd(a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_HOURS);
+  t->hour = bcd(a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_DAYS);
+  t->day = bcd(a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_MONTHS);
+  t->month = bcd(a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_YEARS);	
+  t->year = bcd(a)+2000;
+  t->ticks=0;
+  return 0;
+
+}
+
+int am335x_rtc_settime(int minor,const rtems_time_of_day *t)
+{
+  uint32_t a=0x0;
+
+  rtc_write_enable();
+
+  /* Wait till the busy bit is reset to write again*/
+  a = t->second ;
+  while(mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1);
+  a=mmio_write(AM335X_RTC_BASE+AM335X_RTC_SECS,dec(a) & 0x7f);
+
+  a = t->minute ;
+  while(mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1);
+  a=mmio_write(AM335X_RTC_BASE+AM335X_RTC_MINS,dec(a) & 0x7f);
+
+  a = t->hour ;
+  while(mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1);
+  a=mmio_write(AM335X_RTC_BASE+AM335X_RTC_HOURS,dec(a) & 0x3f);
+
+  a = t->day ;
+  while(mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1);
+  a=mmio_write(AM335X_RTC_BASE+AM335X_RTC_DAYS,dec(a) & 0x3f);
+
+  a = t->month ;
+  while(mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1);
+  a=mmio_write(AM335X_RTC_BASE+AM335X_RTC_MONTHS,dec(a) & 0x1f);
+		
+  a = t->year ;
+  while(mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1);
+  a=mmio_write(AM335X_RTC_BASE+AM335X_RTC_YEARS,(dec(a)%100) & 0xff);
+
+  rtc_write_disable();
+  return 0;
+
+}
+
+#ifdef RTEMS_DEBUG
+void print_time(void)
+{
+  uint32_t a=0x0;
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_SECS);
+  printk("\n\rSecs %x",a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_MINS);
+  printk("\n\rMins %x",a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_HOURS);
+  printk("\n\rHours %x",a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_DAYS);
+  printk("\n\rDays %x",a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_MONTHS);
+  printk("\n\r Months %x",a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_YEARS);
+  printk("\n\rYears %x",a);
+  a=mmio_read(AM335X_RTC_BASE+AM335X_RTC_WEEKS);
+  printk("\n\rWeeks %x",a);
+}
+
+void am335x_rtc_debug(void)
+{
+  int i;
+  rtems_time_of_day t,r;
+
+  t.second = 1;
+  t.minute = 1;
+  t.hour = 1;
+  t.day = 7;
+  t.month=3;
+  t. year = 2015;
+
+  am335x_rtc_settime(0,&t);
+  am335x_rtc_gettime(0,&r);
+	
+  printk("Secs %x",r.second);
+  printk("Mins %x",r.minute);
+  printk("Hours %x",r.hour);
+  printk("Days %x",r.day);
+  printk("Months %x",r.month);
+  printk("Years %x",r.year);
+	
+}
+#endif
+
+/*
+ * driver function table.
+ */
+rtc_fns am335x_rtc_fns = {
+  rtc_init,
+  am335x_rtc_gettime,
+  am335x_rtc_settime
+};
+
+/*
+ * the following table configures the RTC drivers used in this BSP
+ */
+
+rtc_tbl RTC_Table[] = {
+  {
+   "/dev/rtc",                  /* sDeviceName */
+   RTC_CUSTOM,                  /* deviceType */
+   &am335x_rtc_fns,                /* pDeviceFns */
+   am335x_rtc_probe,               /* deviceProbe */
+   NULL,                        /* pDeviceParams */
+   0,                           /* ulCtrlPort1 */
+   0,                           /* ulDataPort */
+   NULL,                        /* getRegister */
+   NULL                         /* setRegister */
+   }
+};
+
+#endif /*IS_AM335X*/
diff --git a/c/src/lib/libcpu/arm/shared/include/am335x_rtc.h b/c/src/lib/libcpu/arm/shared/include/am335x_rtc.h
new file mode 100644
index 0000000..da24858
--- /dev/null
+++ b/c/src/lib/libcpu/arm/shared/include/am335x_rtc.h
@@ -0,0 +1,27 @@
+/**
+ * @file
+ *
+ * @brief RTC driver header file.
+ */
+
+/* RTC registers */
+#define AM335X_RTC_BASE         0x44E3E000
+#define AM335X_RTC_SECS         0x0
+#define AM335X_RTC_MINS         0x4
+#define AM335X_RTC_HOURS        0x8
+#define AM335X_RTC_DAYS         0xc
+#define AM335X_RTC_MONTHS       0x10
+#define AM335X_RTC_YEARS        0x14
+#define AM335X_RTC_WEEKS        0x18
+#define AM335X_RTC_CTRL_REG     0x40
+#define AM335X_RTC_STATUS_REG   0x44
+#define AM335X_RTC_REV_REG      0x74
+#define AM335X_RTC_SYSCONFIG    0x78
+#define AM335X_RTC_KICK0    	0x6c
+#define AM335X_RTC_KICK1    	0x70
+#define AM335X_RTC_OSC_CLOCK        0x54
+
+#define AM335X_RTC_KICK0_KEY	0x83E70B13
+#define AM335X_RTC_KICK1_KEY    0x95A4F1E0
+
+
diff --git a/c/src/lib/libcpu/arm/shared/include/omap3.h b/c/src/lib/libcpu/arm/shared/include/omap3.h
index 2c044a1..f9c108b 100644
--- a/c/src/lib/libcpu/arm/shared/include/omap3.h
+++ b/c/src/lib/libcpu/arm/shared/include/omap3.h
@@ -288,6 +288,12 @@
 #define CLKSEL_TIMER7_CLK_SEL_SEL3 (0x2 << 0) /* Select CLK_32KHZ clock */
 #define CLKSEL_TIMER7_CLK_SEL_SEL4 (0x3 << 0) /* Reserved */
 
+/*RTC CLOCK BASE & Registers*/
+#define CM_RTC_BASE            0x44E00800
+#define CM_RTC_RTC_CLKCTRL     0x0
+#define CM_RTC_CLKSTCTRL       0x4 
+
+
 #define OMAP3_CLKSEL_GPT1    (1 << 0)
 #define OMAP3_CLKSEL_GPT10   (1 << 6)
 #define OMAP3_CLKSEL_GPT11   (1 << 7)
-- 
1.9.1

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to