From d55d7a067fedd9feb48fcd9755205da1558ab709 Mon Sep 17 00:00:00 2001 From: ragunath Date: Sun, 3 May 2015 15:25:55 +0530 Subject: beagle bsp: RTC support for BBB --- c/src/lib/libbsp/arm/beagle/Makefile.am | 3 + c/src/lib/libbsp/arm/beagle/configure.ac | 3 + c/src/lib/libbsp/arm/beagle/rtc.c | 277 +++++++++++++++++++++++++++ c/src/lib/libcpu/arm/shared/include/am335x.h | 20 ++ c/src/lib/libcpu/arm/shared/include/omap3.h | 6 + 5 files changed, 309 insertions(+) create mode 100644 c/src/lib/libbsp/arm/beagle/rtc.c (limited to 'c/src/lib') diff --git a/c/src/lib/libbsp/arm/beagle/Makefile.am b/c/src/lib/libbsp/arm/beagle/Makefile.am index abef8ba808..aa96294109 100644 --- a/c/src/lib/libbsp/arm/beagle/Makefile.am +++ b/c/src/lib/libbsp/arm/beagle/Makefile.am @@ -114,6 +114,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/configure.ac b/c/src/lib/libbsp/arm/beagle/configure.ac index a7e99eb589..b0c99a3e7c 100644 --- a/c/src/lib/libbsp/arm/beagle/configure.ac +++ b/c/src/lib/libbsp/arm/beagle/configure.ac @@ -30,6 +30,9 @@ RTEMS_BSPOPTS_HELP([CONSOLE_BAUD],[initial baud for console UART]) RTEMS_BSPOPTS_SET([CONSOLE_POLLED],[*],[0]) RTEMS_BSPOPTS_HELP([CONSOLE_POLLED],[polled console i/o (e.g. to run testsuite)]) +RTEMS_BSPOPTS_SET([BBB_DEBUG],[beaglebone*],[0]) +RTEMS_BSPOPTS_HELP([BBB_DEBUG],[Enable BBB debug]) + RTEMS_BSP_CLEANUP_OPTIONS(0, 0) RTEMS_BSP_LINKCMDS 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 0000000000..342caf7fa4 --- /dev/null +++ b/c/src/lib/libbsp/arm/beagle/rtc.c @@ -0,0 +1,277 @@ +/** + * @file + * + * @ingroup arm_beagle + * + * @brief RTC driver for AM335x SoC. + * + */ + +/* + * Copyright (c) 2015 Ragunath . + * + * 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 + +#if IS_AM335X +#include +#include +#include +#include +#include + +#define setbit(a,x) (a | (1<> 4 )*10)) +#define dec(a) (((a / 10) << 4) | (a % 10)) +#define WRITE_WAIT_MAX_COUNT 10000 + +rtems_device_minor_number RTC_Minor; +size_t RTC_Count = 1; + +static void rtc_write_enable(void); +static void rtc_write_disable(void); +static int rtc_write_wait(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 disable 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); +} + +/* + * Wait till busy bit is reset + */ +static int rtc_write_wait(void) +{ + int i = WRITE_WAIT_MAX_COUNT; + while((mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1) && (i--)); + + if(i == 0) + return RTEMS_RESOURCE_IN_USE; + else + return RTEMS_SUCCESSFUL; +} + + +/* + * 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) +{ + uint32_t a = 0x0; + + rtc_clk_init(); + /* + * 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; + + if(minor != 0) + return RTEMS_INVALID_NUMBER; + + 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 RTEMS_SUCCESSFUL; +} + +int am335x_rtc_settime(int minor,const rtems_time_of_day *t) +{ + uint32_t a=0x0; + int rv; + + if(minor != 0) + return RTEMS_INVALID_NUMBER; + + rtc_write_enable(); + + /* Wait till the busy bit is reset to write again*/ + a = t->second; + rv=rtc_write_wait(); + if(rv != RTEMS_SUCCESSFUL) + return rv; + a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_SECS,dec(a) & 0x7f); + + a = t->minute; + rv=rtc_write_wait(); + if(rv != RTEMS_SUCCESSFUL) + return rv; + a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_MINS,dec(a) & 0x7f); + + a = t->hour; + rv=rtc_write_wait(); + if(rv != RTEMS_SUCCESSFUL) + return rv; + a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_HOURS,dec(a) & 0x3f); + + a = t->day; + rv=rtc_write_wait(); + if(rv != RTEMS_SUCCESSFUL) + return rv; + a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_DAYS,dec(a) & 0x3f); + + a = t->month; + rv=rtc_write_wait(); + if(rv != RTEMS_SUCCESSFUL) + return rv; + a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_MONTHS,dec(a) & 0x1f); + + a = t->year; + rv=rtc_write_wait(); + if(rv != RTEMS_SUCCESSFUL) + return rv; + a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_YEARS,(dec(a)%100) & 0xff); + + rtc_write_disable(); + return rv; +} + +#if BBB_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 diff --git a/c/src/lib/libcpu/arm/shared/include/am335x.h b/c/src/lib/libcpu/arm/shared/include/am335x.h index 1f638bda76..37c5eeb666 100644 --- a/c/src/lib/libcpu/arm/shared/include/am335x.h +++ b/c/src/lib/libcpu/arm/shared/include/am335x.h @@ -280,3 +280,23 @@ /* Command posted status */ #define AM335X_WDT_WSPR 0x48 /* Activate/deactivate sequence */ + +/* 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 1316f6d4b0..f28e5e5406 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) -- cgit v1.2.3