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)