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