Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:48

0001 /**
0002  * @file
0003  *
0004  * @ingroup arm_beagle
0005  *
0006  * @brief RTC driver for AM335x SoC.
0007  *
0008  */
0009 
0010 /*
0011  * Copyright (c) 2015 Ragunath <ragunath3252@gmail.com>.
0012  *
0013  * The license and distribution terms for this file may be
0014  * found in the file LICENSE in this distribution or at
0015  * http://www.rtems.com/license/LICENSE.
0016  */
0017 
0018 #include <bspopts.h>
0019 
0020 #if IS_AM335X
0021 #include <rtems.h>
0022 #include <bsp.h>
0023 #include <time.h>
0024 #include <libchip/rtc.h>
0025 #include <libcpu/omap3.h>
0026 
0027 #define setbit(a,x) (a | (1<<x))
0028 #define bcd(a) ((a & 0x0f)+ (((a & 0xf0) >> 4 )*10))
0029 #define dec(a) (((a / 10) << 4) | (a % 10))
0030 #define WRITE_WAIT_MAX_COUNT 10000
0031 
0032 size_t RTC_Count = 1;
0033 
0034 static void rtc_write_enable(void);
0035 static void rtc_write_disable(void);
0036 static int rtc_write_wait(void);
0037 static void rtc_clk_init(void);
0038 void rtc_init(int minor);
0039 void print_time(void);
0040 int am335x_rtc_gettime(int minor,rtems_time_of_day *t);
0041 int am335x_rtc_settime(int minor, const rtems_time_of_day *t);
0042 void am335x_rtc_debug(void);
0043 
0044 /*
0045  * probe for a rtc. we always claim to have one.
0046  */
0047 static bool am335x_rtc_probe (int minor)
0048 {
0049   return true;
0050 }
0051 
0052 /*
0053  * Write key values to kick0 and kick1 registers to enable write access
0054  */
0055 static void rtc_write_enable(void)
0056 {
0057   mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK0,AM335X_RTC_KICK0_KEY);
0058   mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK1,AM335X_RTC_KICK1_KEY);
0059 }
0060 
0061 /*
0062  * Write random (0x11111111) value to kick0 and kick1 registers to disable write access
0063  */
0064 static void rtc_write_disable(void)
0065 {
0066   /* Write some random value other than key to disable*/
0067   mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK0,0x11111111);
0068   mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK1,0x11111111);
0069 }
0070 
0071 /*
0072  * Wait till busy bit is reset
0073  */
0074 static int rtc_write_wait(void)
0075 {
0076   int i = WRITE_WAIT_MAX_COUNT;
0077   while((mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1) && (i--));
0078 
0079   if(i == 0)
0080       return RTEMS_RESOURCE_IN_USE;
0081   else
0082       return RTEMS_SUCCESSFUL;
0083 }
0084 
0085 
0086 /*
0087  * Initialize RTC clock
0088  */
0089 static void rtc_clk_init(void)
0090 {
0091   uint32_t a = 0x0;
0092 
0093   a = setbit(a,1);
0094   /* IDLEST = 0x0 & MODULEMODE = 0x1*/
0095   mmio_write(CM_RTC_BASE+CM_RTC_RTC_CLKCTRL,a);
0096   a = 0x0;
0097 
0098   /*32K rtc clock active*/
0099   a = setbit(a,9);
0100   a = setbit(a,8);
0101   mmio_write(CM_RTC_BASE+CM_RTC_CLKSTCTRL,a);
0102 }
0103 
0104 void rtc_init(int minor)
0105 {
0106   uint32_t a = 0x0;
0107 
0108   rtc_clk_init();
0109    /*
0110    * Steps to enable RTC
0111    * 1. Enable the module clock domains (rtc_clk_init).
0112    * 2. Enable the RTC module using CTRL_REG.RTC_disable. (Default enabled. Nothing done)
0113    * 3. Enable the 32K clock from PER PLL, if using the internal RTC oscillator.
0114    * 4. Write to the kick registers (KICK0R, KICK1R) in the RTC.
0115    * 5. Configure the timer in RTCSS for desired application (set time and date, alarm wakeup, and so on).
0116    * 6. Start the RTC (in CTRL_REG.STOP_RTC).
0117    */
0118   rtc_write_enable();
0119   a = setbit(a,0);
0120   mmio_write(AM335X_RTC_BASE+AM335X_RTC_SYSCONFIG,a);
0121   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_OSC_CLOCK);
0122   a = setbit(a,6);
0123   mmio_write(AM335X_RTC_BASE+AM335X_RTC_OSC_CLOCK,a);
0124   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_CTRL_REG);
0125   a = setbit(a,0);
0126   mmio_write(AM335X_RTC_BASE+AM335X_RTC_CTRL_REG,a);
0127 
0128   rtc_write_disable();
0129 }
0130 
0131 int am335x_rtc_gettime(int minor,rtems_time_of_day *t)
0132 {
0133   uint32_t a = 0x0;
0134 
0135   if(minor != 0)
0136     return RTEMS_INVALID_NUMBER;
0137 
0138   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_SECS);
0139   t->second = bcd(a);
0140   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MINS);
0141   t->minute = bcd(a);
0142   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_HOURS);
0143   t->hour = bcd(a);
0144   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_DAYS);
0145   t->day = bcd(a);
0146   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MONTHS);
0147   t->month = bcd(a);
0148   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_YEARS);
0149   t->year = bcd(a)+2000;
0150   t->ticks=0;
0151   return RTEMS_SUCCESSFUL;
0152 }
0153 
0154 int am335x_rtc_settime(int minor,const rtems_time_of_day *t)
0155 {
0156   uint32_t a=0x0;
0157   int rv;
0158 
0159   if(minor != 0)
0160     return RTEMS_INVALID_NUMBER;
0161 
0162   rtc_write_enable();
0163 
0164   /* Wait till the busy bit is reset to write again*/
0165   a = t->second;
0166   rv=rtc_write_wait();
0167   if(rv != RTEMS_SUCCESSFUL)
0168       return rv;
0169   a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_SECS,dec(a) & 0x7f);
0170 
0171   a = t->minute;
0172   rv=rtc_write_wait();
0173   if(rv != RTEMS_SUCCESSFUL)
0174       return rv;
0175   a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_MINS,dec(a) & 0x7f);
0176 
0177   a = t->hour;
0178   rv=rtc_write_wait();
0179   if(rv != RTEMS_SUCCESSFUL)
0180       return rv;
0181   a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_HOURS,dec(a) & 0x3f);
0182 
0183   a = t->day;
0184   rv=rtc_write_wait();
0185   if(rv != RTEMS_SUCCESSFUL)
0186       return rv;
0187   a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_DAYS,dec(a) & 0x3f);
0188 
0189   a = t->month;
0190   rv=rtc_write_wait();
0191   if(rv != RTEMS_SUCCESSFUL)
0192       return rv;
0193   a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_MONTHS,dec(a) & 0x1f);
0194 
0195   a = t->year;
0196   rv=rtc_write_wait();
0197   if(rv != RTEMS_SUCCESSFUL)
0198       return rv;
0199   a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_YEARS,(dec(a)%100) & 0xff);
0200 
0201   rtc_write_disable();
0202   return rv;
0203 }
0204 
0205 #if BBB_DEBUG
0206 void print_time(void)
0207 {
0208   uint32_t a = 0x0;
0209   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_SECS);
0210   printk("\n\rSecs %x",a);
0211   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MINS);
0212   printk("\n\rMins %x",a);
0213   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_HOURS);
0214   printk("\n\rHours %x",a);
0215   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_DAYS);
0216   printk("\n\rDays %x",a);
0217   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MONTHS);
0218   printk("\n\r Months %x",a);
0219   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_YEARS);
0220   printk("\n\rYears %x",a);
0221   a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_WEEKS);
0222   printk("\n\rWeeks %x",a);
0223 }
0224 
0225 void am335x_rtc_debug(void)
0226 {
0227   int i;
0228   rtems_time_of_day t,r;
0229 
0230   t.second = 1;
0231   t.minute = 1;
0232   t.hour = 1;
0233   t.day = 7;
0234   t.month = 3;
0235   t. year = 2015;
0236 
0237   am335x_rtc_settime(0,&t);
0238   am335x_rtc_gettime(0,&r);
0239 
0240   printk("Secs %x",r.second);
0241   printk("Mins %x",r.minute);
0242   printk("Hours %x",r.hour);
0243   printk("Days %x",r.day);
0244   printk("Months %x",r.month);
0245   printk("Years %x",r.year);
0246 }
0247 #endif
0248 
0249 /*
0250  * driver function table.
0251  */
0252 rtc_fns am335x_rtc_fns = {
0253   rtc_init,
0254   am335x_rtc_gettime,
0255   am335x_rtc_settime
0256 };
0257 
0258 /*
0259  * the following table configures the RTC drivers used in this BSP
0260  */
0261 
0262 rtc_tbl RTC_Table[] = {
0263   {
0264    "/dev/rtc",                  /* sDeviceName */
0265    RTC_CUSTOM,                  /* deviceType */
0266    &am335x_rtc_fns,             /* pDeviceFns */
0267    am335x_rtc_probe,            /* deviceProbe */
0268    NULL,                        /* pDeviceParams */
0269    0,                           /* ulCtrlPort1 */
0270    0,                           /* ulDataPort */
0271    NULL,                        /* getRegister */
0272    NULL                         /* setRegister */
0273    }
0274 };
0275 
0276 #endif