Last active
April 27, 2018 16:39
-
-
Save bigjosh/a12e9e6811507937f21e2dd5f068a85d to your computer and use it in GitHub Desktop.
Turn off Beagle Bone am355x using the RTC TIMER2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define RTC_SS_BASE 0x44e3e000L | |
#define SECONDS_REG 0x00 | |
#define MINUTES_REG 0x04 | |
#define HOURS_REG 0x08 | |
#define DAYS_REG 0x0C | |
#define MONTHS_REG 0x10 | |
#define YEARS_REG 0x14 | |
#define ALARM_SECONDS_REG 0x20 | |
#define ALARM_MINUTES_REG 0x24 | |
#define ALARM_HOURS_REG 0x28 | |
#define ALARM_DAYS_REG 0x2C | |
#define ALARM_MONTHS_REG 0x30 | |
#define ALARM_YEARS_REG 0x34 | |
#define ALARM2_SECONDS_REG 0x80 | |
#define ALARM2_MINUTES_REG 0x84 | |
#define ALARM2_HOURS_REG 0x88 | |
#define ALARM2_DAYS_REG 0x8C | |
#define ALARM2_MONTHS_REG 0x90 | |
#define ALARM2_YEARS_REG 0x94 | |
#define RTCALARMINT 76 // RTC alarm interrupt | |
#define RTC_CTRL_REG 0x40 | |
#define RTC_STATUS_REG 0x44 | |
#define RTC_STATUS_ALARM (1<<6) // Indicates ALARM has happened | |
#define RTC_INTERRUPTS_REG 0x48 | |
#define RTC_INTERRUPTS_IT_ALARM2 (1<<4) // Enable interrupt on ALARM2 | |
#define RTC_INTERRUPTS_IT_ALARM (1<<3) // Enable interrupt on ALARM | |
#define RTC_INTERRUPTS_IT_TIMER (1<<2) // Enable interrupt on TIMER | |
#define RTC_SYSCONFIG 0x78 | |
#define RTC_IRQWAKEEN 0x7c | |
#define RTC_IRQWAKEEN_ALARM (1<<1) // Allow wakeup generation on ALARM | |
#define RTC_IRQWAKEEN_TIMER (1<<0) // Allow wakeup generation on TIMER | |
#define RTC_PMIC 0x98 | |
#define RTC_PMIC_PWN_ENABLE_EN (1<<16) | |
#define ASSIGN_WORD(w,v) ((*( (unsigned long *) (&(w)) ) ) = (v) ) | |
/* | |
* | |
* Based on: | |
* devmem2.c: Simple program to read/write from/to any location in memory. | |
* | |
* Copyright (C) 2000, Jan-Derk Bakker ([email protected]) | |
* | |
* | |
* This software has been developed for the LART computing board | |
* (http://www.lart.tudelft.nl/). The development has been sponsored by | |
* the Mobile MultiMedia Communications (http://www.mmc.tudelft.nl/) | |
* and Ubiquitous Communications (http://www.ubicom.tudelft.nl/) | |
* projects. | |
* | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <signal.h> | |
#include <fcntl.h> | |
#include <ctype.h> | |
#include <termios.h> | |
#include <sys/types.h> | |
#include <sys/mman.h> | |
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \ | |
__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0) | |
#define MAP_SIZE 4096UL | |
#define MAP_MASK (MAP_SIZE - 1) | |
int bcd2n( int bcd ) { | |
return ((bcd/16) * 10 ) + ( bcd & 15); | |
} | |
int n2bcd( int n ) { | |
return (( n / 10 ) * 16 ) + (n % 10 ); | |
} | |
int main(int argc, char **argv) { | |
int fd; | |
void *map_base, *virt_addr; | |
unsigned long read_result, writeval; | |
off_t target; | |
target = RTC_SS_BASE; | |
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL; | |
printf("/dev/mem opened.\n"); | |
fflush(stdout); | |
/* Map one page */ | |
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target ); | |
if(map_base == (void *) -1) FATAL; | |
printf("Memory mapped at address %p.\n", map_base); | |
fflush(stdout); | |
unsigned char *base = (unsigned char *) map_base; | |
printf("Value at address %d\n", *base ); | |
fflush(stdout); | |
// HERE IS THE BEEF | |
printf("Turn off PMIC OFF bit...\n"); | |
system("i2cset -f -y 0 0x24 0x0a 0x00"); // Turn off OFF bit | |
printf("First lets set the alarm...\n"); | |
printf("Get current time ...\n"); | |
int secs = bcd2n( base[ SECONDS_REG] ); | |
int mins = bcd2n( base[ MINUTES_REG] ); | |
int hours = bcd2n( base[ HOURS_REG ] ); | |
int days = bcd2n( base[ DAYS_REG ] ); | |
int months = bcd2n( base[ MONTHS_REG ] ); | |
int years = bcd2n( base[ YEARS_REG ] ); | |
printf("Bump forward 5 secs in the future......\n"); | |
secs += 5; | |
if (secs >= 60 ) { | |
secs %= 60; | |
mins++; | |
if (mins >= 60 ) { | |
mins %=60; | |
hours++; | |
if (hours >=24 ) { | |
hours %=24; | |
days++; | |
// TODO: Make work last day of the month at midnight | |
} | |
} | |
} | |
/* | |
printf("Set ALARM for wakeup......\n"); | |
base[ALARM_SECONDS_REG] = n2bcd( secs ); | |
base[ALARM_MINUTES_REG] = n2bcd( mins ); | |
base[ALARM_HOURS_REG] = n2bcd( hours ); | |
base[ALARM_DAYS_REG] = n2bcd( days ); | |
base[ALARM_MONTHS_REG] = n2bcd( months ); | |
base[ALARM_YEARS_REG] = n2bcd( years ); | |
printf("NOW ALARM\n"); | |
printf("%3.3d %3.3d\n" , base[ SECONDS_REG], base[ ALARM_SECONDS_REG] ); | |
printf("%3.3d %3.3d\n" , base[ MINUTES_REG], base[ ALARM_MINUTES_REG] ); | |
printf("%3.3d %3.3d\n" , base[ HOURS_REG], base[ ALARM_HOURS_REG] ); | |
printf("%3.3d %3.3d\n" , base[ DAYS_REG], base[ ALARM_DAYS_REG] ); | |
printf("%3.3d %3.3d\n" , base[ MONTHS_REG], base[ ALARM_MONTHS_REG] ); | |
printf("%3.3d %3.3d\n" , base[ YEARS_REG], base[ ALARM_YEARS_REG] ); | |
printf(" Enable ALARM interrupt (necessary?)... \n"); | |
base[ RTC_INTERRUPTS_REG ] |= RTC_INTERRUPTS_IT_ALARM; | |
printf("Enable PWR_ENABLE_EN to be controlled ON->OFF by ALARM2...\n"); | |
base[RTC_PMIC] |= RTC_PMIC_PWN_ENABLE_EN; | |
base[RTC_IRQWAKEEN ] |= RTC_IRQWAKEEN_ALARM; | |
*/ | |
printf("Set ALARM2 for sleep......\n"); | |
base[ALARM2_SECONDS_REG] = n2bcd( secs ); | |
base[ALARM2_MINUTES_REG] = n2bcd( mins ); | |
base[ALARM2_HOURS_REG] = n2bcd( hours ); | |
base[ALARM2_DAYS_REG] = n2bcd( days ); | |
base[ALARM2_MONTHS_REG] = n2bcd( months ); | |
base[ALARM2_YEARS_REG] = n2bcd( years ); | |
printf("NOW ALARM2\n"); | |
printf("%3.3d %3.3d\n" , base[ SECONDS_REG], base[ ALARM2_SECONDS_REG] ); | |
printf("%3.3d %3.3d\n" , base[ MINUTES_REG], base[ ALARM2_MINUTES_REG] ); | |
printf("%3.3d %3.3d\n" , base[ HOURS_REG], base[ ALARM2_HOURS_REG] ); | |
printf("%3.3d %3.3d\n" , base[ DAYS_REG], base[ ALARM2_DAYS_REG] ); | |
printf("%3.3d %3.3d\n" , base[ MONTHS_REG], base[ ALARM2_MONTHS_REG] ); | |
printf("%3.3d %3.3d\n" , base[ YEARS_REG], base[ ALARM2_YEARS_REG] ); | |
//base[RTC_IRQWAKEEN ] |= RTC_IRQWAKEEN_ALARM; | |
printf("DONE setting Alarm time...\n"); | |
printf("Enable PWR_ENABLE_EN to be controlled ON->OFF by ALARM2...\n"); | |
ASSIGN_WORD( base[RTC_PMIC] , RTC_PMIC_PWN_ENABLE_EN ); | |
// Check with... | |
// devmem2 0x44e3e098 | |
//printf("Enable Wake pin, invert polarity, PWR_ENABLE_EN to be controlled ON->OFF by ALARM2...\n"); | |
//base[RTC_PMIC]=0x10011; //Enable wakeup pin, invert polarity, POWER_ENABLE_EN | |
printf(" Enable ALARM2 interrupt (necessary?)... \n"); | |
ASSIGN_WORD( base[ RTC_INTERRUPTS_REG ] , RTC_INTERRUPTS_IT_ALARM2 ); | |
/* | |
for(int i=0; i<15;i++) { | |
printf("%d-%d\n",i, base[RTC_STATUS_REG] & RTC_STATUS_ALARM ); | |
sleep(1); | |
} | |
*/ | |
printf("Close memmap...\n"); | |
if(munmap(map_base, MAP_SIZE) == -1) FATAL; | |
close(fd); | |
// Now got to sleep! | |
// system("devmem2 0x44e3e098 w 0x10011"); //Enable wakeup pin, invert polarity, POWER_ENABLE_EN | |
// system("i2cset -f -y 0 0x24 0x0a 0x080"); // Turn on OFF bit | |
// system("i2cset -f -y 0 0x24 0x0b 0x63"); // PAssword to access 1e | |
//printf("Sending SEQDWN+SEQUP...\n"); | |
//system("i2cset -f -y 0 0x24 0x1e 0x06"); // Set DWNSEQ bit to start shutdown sequence | |
//system("i2cset -f -y 0 0x24 0x1e 0x02"); // Set DWNSEQ bit to start shutdown sequence | |
printf("Waiting for turnoff via TIMER2 in 5 seconds!...\n"); | |
//__asm__ __volatile__ ("cpsie i"); /* Clear PRIMASK */ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment