860 rtc problem
Alex Zeffertt
ajz at cambridgebroadband.com
Fri Oct 18 02:14:47 EST 2002
On Thu, 17 Oct 2002, Der Herr Hofrat wrote:
> > On Thu, 17 Oct 2002, leeyang wrote:
> >
> > Hi,
> >
> > I've written a rtc driver for the mpc860. See attached files.
>
> you seem to have atached the object file not the source file - could
> you resend ?
>
Yes, sorry everyone! See attached.
Alex
> thx !
> hofrat
>
Hope it helps.
-------------- next part --------------
/*
* Linux/PowerPC Real Time Clock Driver
*
* heavily based on:
* Linux/SPARC Real Time Clock Driver
* Copyright (C) 1996 Thomas K. Dyas (tdyas at eden.rutgers.edu)
*
* This is a little driver that lets a user-level program access
* the PPC clocks chip. It is no use unless you
* use the modified clock utility.
*
* Get the modified clock utility from:
* ftp://vger.rutgers.edu/pub/linux/Sparc/userland/clock.c
*/
#ifndef USERLAND_TESTCODE
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/mc146818rtc.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/machdep.h>
#include <asm/time.h>
static int rtc_busy = 0;
/* Retrieve the current date and time from the real time clock. */
void get_rtc_time(struct rtc_time *t)
{
unsigned long nowtime;
nowtime = (ppc_md.get_rtc_time)();
to_tm(nowtime, t);
t->tm_year -= 1900;
t->tm_mon -= 1;
t->tm_wday -= 1;
}
/* Set the current date and time in the real time clock. */
void set_rtc_time(struct rtc_time *t)
{
unsigned long nowtime;
printk(KERN_INFO "rtc.c:set_rtc_time: %04d-%02d-%02d %02d:%02d:%02d.\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
nowtime = mktime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
printk(KERN_INFO "rtc.c:set_rtc_time: set rtc time to %ld seconds.\n", nowtime);
(ppc_md.set_rtc_time)(nowtime);
}
static loff_t rtc_lseek(struct file *file, loff_t offset, int origin)
{
return -ESPIPE;
}
static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
struct rtc_time rtc_tm;
switch (cmd)
{
case RTC_RD_TIME:
if (ppc_md.get_rtc_time)
{
get_rtc_time(&rtc_tm);
if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
return -EFAULT;
return 0;
}
else
return -EINVAL;
case RTC_SET_TIME:
if (!capable(CAP_SYS_TIME))
return -EPERM;
if (ppc_md.set_rtc_time)
{
if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
return -EFAULT;
set_rtc_time(&rtc_tm);
return 0;
}
else
return -EINVAL;
default:
return -EINVAL;
}
}
static int rtc_open(struct inode *inode, struct file *file)
{
if (rtc_busy)
return -EBUSY;
rtc_busy = 1;
MOD_INC_USE_COUNT;
return 0;
}
static int rtc_release(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
rtc_busy = 0;
return 0;
}
static struct file_operations rtc_fops = {
owner: THIS_MODULE,
llseek: rtc_lseek,
ioctl: rtc_ioctl,
open: rtc_open,
release: rtc_release
};
static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops };
EXPORT_NO_SYMBOLS;
static int __init rtc_init(void)
{
int error;
error = misc_register(&rtc_dev);
if (error) {
printk(KERN_ERR "rtc: unable to get misc minor\n");
return error;
}
return 0;
}
static void __exit rtc_exit(void)
{
misc_deregister(&rtc_dev);
}
module_init(rtc_init);
module_exit(rtc_exit);
#else /* ifndef USERLAND_TESTCODE */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <asm/ioctls.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <time.h>
#include <linux/rtc.h> /* get the user-level API */
static char * days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
static char * months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
static void print_time(struct rtc_time * t)
{
printf("%s %s %d %02d:%02d:%02d (DST=%s) %d\n",
days[t->tm_wday],
months[t->tm_mon],
t->tm_mday,
t->tm_hour,t->tm_min,t->tm_sec,
(t->tm_isdst)?"On":"Off",
t->tm_year+1900);
}
int main (int argc, char **argv)
{
int s;
struct rtc_time rtctime;
s = open("/dev/rtc", O_RDWR);
if (argc < 2)
goto usage;
if (strcmp(argv[1],"r") == 0)
{
if(ioctl(s, RTC_RD_TIME, &rtctime))
perror("ioctl");
else
print_time(&rtctime);
}
else if (strcmp(argv[1],"w") == 0)
{
if (argc == 2) {
time_t t = time(NULL);
struct tm *systime = localtime(&t);
rtctime.tm_sec = systime->tm_sec;
rtctime.tm_min = systime->tm_min;
rtctime.tm_hour = systime->tm_hour;
rtctime.tm_mday = systime->tm_mday;
rtctime.tm_mon = systime->tm_mon;
rtctime.tm_year = systime->tm_year;
rtctime.tm_wday = systime->tm_wday;
rtctime.tm_yday = 0; /* unused by mpc8xx */
rtctime.tm_isdst = systime->tm_isdst;
} else {
if (argc < 10)
goto usage;
if (sscanf(argv[2],"%d", &rtctime.tm_sec) != 1)
goto usage;
if (sscanf(argv[3],"%d", &rtctime.tm_min) != 1)
goto usage;
if (sscanf(argv[4],"%d", &rtctime.tm_hour) != 1)
goto usage;
if (sscanf(argv[5],"%d", &rtctime.tm_mday) != 1)
goto usage;
if (sscanf(argv[6],"%d", &rtctime.tm_mon) != 1)
goto usage;
if (sscanf(argv[7],"%d", &rtctime.tm_year) != 1)
goto usage;
if (sscanf(argv[8],"%d", &rtctime.tm_wday) != 1)
goto usage;
rtctime.tm_yday = 0; /* unused by mpc8xx */
if (sscanf(argv[9],"%d", &rtctime.tm_isdst) != 1)
goto usage;
}
if(ioctl(s, RTC_SET_TIME, &rtctime))
perror("ioctl");
}
else
goto usage;
close(s);
return 0;
usage:
close(s);
printf("i) %s r\n"
"ii) %s w\n"
"iii) %s w sec min hour mday mon year wday isdst\n"
"Notes:\n"
"\t(i) reads time from RTC.\n"
"\t(ii) writes current system time to RTC.\n"
"\t(iii) writes remaining params to RTC.\n"
"\t(All parameters are decimal integers\n"
"\tSee man mktime for parameter ranges)\n", argv[0],argv[0],argv[0]);
return -1;
}
#endif /* USERLAND_TESTCODE */
-------------- next part --------------
##########################################################################
#
# Copyright (C) 2001 Cambridge Broadband Ltd,
# Edinburgh House, Cowley Road
# Cambridge, England
# CB4 0DS
#
# ++44 1223 713000
#
# enquiries at cambridgebroadband.com
#
# http://www.cambridgebroadband.com
#
##########################################################################
CC = ppc_8xx-gcc
KERNELDIR = ../../kernel
DEBUG = -g
NODEBUG =
KERN_CFLAGS = -DMODULE -D__KERNEL__ -I$(KERNELDIR)/include -O2 -Wall $(NODEBUG)
USER_CFLAGS = -DUSERLAND_TESTCODE -I$(KERNELDIR)/include -O2 -Wall $(NODEBUG)
TARGETS = rtc.o rtc
all: $(TARGETS)
rtc.o: rtc.c
$(CC) $(KERN_CFLAGS) -c rtc.c
rtc: rtc.c
$(CC) $(USER_CFLAGS) -o $@ rtc.c
clean:
rm -f $(TARGETS)
More information about the Linuxppc-embedded
mailing list