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